Skip to content

Comments

websocket POC demo - not production ready.#844

Draft
devinleighsmith wants to merge 1 commit intomasterfrom
websockets
Draft

websocket POC demo - not production ready.#844
devinleighsmith wants to merge 1 commit intomasterfrom
websockets

Conversation

@devinleighsmith
Copy link
Contributor

NOT a pull request, just sharing a POC.

This is not production ready, as it doesn't have a backplane or proper controls on connections or message size/rates.

Requires these env vars to run:

export CORS_DOMAIN='https://localhost:8080;http://localhost:8080'
export VITE_WS_PROXY_INSECURE=true
export VITE_WS_PROXY_ORIGIN=https://localhost:8080

@devinleighsmith devinleighsmith self-assigned this Feb 20, 2026
@devinleighsmith devinleighsmith added the question Further information is requested label Feb 20, 2026
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot

See analysis details on SonarQube Cloud


logger?.LogInformation(
"SignalR connect attempt. Origin={Origin}, CORS_DOMAIN={CorsDomain}",
origin,

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI 4 days ago

In general, to fix log forging when logging user input, ensure the values are normalized or encoded before being passed to the logger. For plain-text logs, the minimal safe step is to remove or replace newline and carriage-return characters (and optionally other control characters) so that a malicious value cannot break log structure or inject fake entries.

Here, we should avoid changing functionality, so we will keep the same logging messages and behavior but sanitize origin before it is first used. Because origin is also used in the later warning (origin mismatch), the safest place is immediately after it is read from the header: create a sanitized version that strips \r and \n, and use that sanitized value in all logging calls, while keeping the original header value for any non-logging logic (if needed). In this snippet, origin is only used for comparisons and logging; stripping newlines will not affect equality checks for valid origins, because valid origins should not contain such characters.

Concretely, in api/Hubs/NotificationsHub.cs:

  • After line 23 where origin is read, introduce a new variable sanitizedOrigin that removes newline characters from origin.
  • Use sanitizedOrigin instead of origin in the two logging calls that include the origin (lines 25–28 and 50–52).
  • No new external dependencies are required; string.Replace and the null-conditional operator are sufficient.
Suggested changeset 1
api/Hubs/NotificationsHub.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/Hubs/NotificationsHub.cs b/api/Hubs/NotificationsHub.cs
--- a/api/Hubs/NotificationsHub.cs
+++ b/api/Hubs/NotificationsHub.cs
@@ -21,10 +21,11 @@
         var allowedOrigin = config?.GetValue<string>("CORS_DOMAIN");
         var disableOriginCheck = config?.GetValue<bool>("DISABLE_SIGNALR_ORIGIN_CHECK") ?? false;
         var origin = httpContext?.Request.Headers["Origin"].ToString();
+        var sanitizedOrigin = origin?.Replace("\r", string.Empty).Replace("\n", string.Empty);
 
         logger?.LogInformation(
             "SignalR connect attempt. Origin={Origin}, CORS_DOMAIN={CorsDomain}",
-            origin,
+            sanitizedOrigin,
             allowedOrigin);
 
         if (disableOriginCheck)
@@ -49,7 +47,7 @@
             {
                 logger?.LogWarning(
                     "SignalR connection aborted due to origin mismatch. Origin={Origin}",
-                    origin);
+                    sanitizedOrigin);
                 Context.Abort();
                 return Task.CompletedTask;
             }
EOF
@@ -21,10 +21,11 @@
var allowedOrigin = config?.GetValue<string>("CORS_DOMAIN");
var disableOriginCheck = config?.GetValue<bool>("DISABLE_SIGNALR_ORIGIN_CHECK") ?? false;
var origin = httpContext?.Request.Headers["Origin"].ToString();
var sanitizedOrigin = origin?.Replace("\r", string.Empty).Replace("\n", string.Empty);

logger?.LogInformation(
"SignalR connect attempt. Origin={Origin}, CORS_DOMAIN={CorsDomain}",
origin,
sanitizedOrigin,
allowedOrigin);

if (disableOriginCheck)
@@ -49,7 +47,7 @@
{
logger?.LogWarning(
"SignalR connection aborted due to origin mismatch. Origin={Origin}",
origin);
sanitizedOrigin);
Context.Abort();
return Task.CompletedTask;
}
Copilot is powered by AI and may make mistakes. Always verify output.
{
logger?.LogWarning(
"SignalR connection aborted due to origin mismatch. Origin={Origin}",
origin);

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI 4 days ago

In general, to fix log-forging issues, any user-controlled value should be normalized or encoded before being written to logs. For plain-text logs, this typically means removing or replacing newline characters (\r, \n) and possibly other non-printable control characters so an attacker cannot break the log format or inject extra entries. For logs destined to HTML, HTML-encoding is recommended.

In this specific code, the problematic value is origin read from Request.Headers["Origin"]. The best minimal fix is to sanitize this value once, immediately after reading it, and then use the sanitized value for all logging calls. That keeps observable behavior the same for normal Origin values while stripping potentially dangerous characters (such as newlines) that could be used for log forging. A simple approach, consistent with the recommendation, is to replace any \r and \n with empty strings (or another benign character). We should not alter other logic (such as the origin comparison) unless necessary; to keep functionality unchanged, we can continue to use the original origin for the origin-check logic and use a separate sanitized variable for logging.

Concretely in api/Hubs/NotificationsHub.cs:

  • After obtaining origin at line 23, introduce a new variable, e.g., sanitizedOrigin, which is origin with \r and \n removed.
  • Update all logging calls that currently pass origin as a parameter (lines 25–28 and 50–52) to pass sanitizedOrigin instead.
  • No new external dependencies are needed; this can be done using string.Replace, which is part of the base class library.

This keeps the origin-matching logic identical (still using the original header value) while ensuring logged values cannot contain raw newlines.

Suggested changeset 1
api/Hubs/NotificationsHub.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/Hubs/NotificationsHub.cs b/api/Hubs/NotificationsHub.cs
--- a/api/Hubs/NotificationsHub.cs
+++ b/api/Hubs/NotificationsHub.cs
@@ -21,10 +21,13 @@
         var allowedOrigin = config?.GetValue<string>("CORS_DOMAIN");
         var disableOriginCheck = config?.GetValue<bool>("DISABLE_SIGNALR_ORIGIN_CHECK") ?? false;
         var origin = httpContext?.Request.Headers["Origin"].ToString();
+        var sanitizedOrigin = origin?
+            .Replace("\r", string.Empty)
+            .Replace("\n", string.Empty);
 
         logger?.LogInformation(
             "SignalR connect attempt. Origin={Origin}, CORS_DOMAIN={CorsDomain}",
-            origin,
+            sanitizedOrigin,
             allowedOrigin);
 
         if (disableOriginCheck)
@@ -49,7 +49,7 @@
             {
                 logger?.LogWarning(
                     "SignalR connection aborted due to origin mismatch. Origin={Origin}",
-                    origin);
+                    sanitizedOrigin);
                 Context.Abort();
                 return Task.CompletedTask;
             }
EOF
@@ -21,10 +21,13 @@
var allowedOrigin = config?.GetValue<string>("CORS_DOMAIN");
var disableOriginCheck = config?.GetValue<bool>("DISABLE_SIGNALR_ORIGIN_CHECK") ?? false;
var origin = httpContext?.Request.Headers["Origin"].ToString();
var sanitizedOrigin = origin?
.Replace("\r", string.Empty)
.Replace("\n", string.Empty);

logger?.LogInformation(
"SignalR connect attempt. Origin={Origin}, CORS_DOMAIN={CorsDomain}",
origin,
sanitizedOrigin,
allowedOrigin);

if (disableOriginCheck)
@@ -49,7 +49,7 @@
{
logger?.LogWarning(
"SignalR connection aborted due to origin mismatch. Origin={Origin}",
origin);
sanitizedOrigin);
Context.Abort();
return Task.CompletedTask;
}
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

question Further information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant