fix(gateway): enforce browser origin check regardless of proxy headers

In trusted-proxy mode, enforceOriginCheckForAnyClient was set to false
whenever proxy headers were present. This allowed browser-originated
WebSocket connections from untrusted origins to bypass origin validation
entirely, as the check only ran for control-ui and webchat client types.

An attacker serving a page from an untrusted origin could connect through
a trusted reverse proxy, inherit proxy-injected identity, and obtain
operator.admin access via the sharedAuthOk / roleCanSkipDeviceIdentity
path without any origin restriction.

Remove the hasProxyHeaders exemption so origin validation runs for all
browser-originated connections regardless of how the request arrived.

Fixes GHSA-5wcw-8jjv-m286
This commit is contained in:
Robin Waslander
2026-03-12 01:15:59 +01:00
parent 3c0fd3dffe
commit ebed3bbde1
3 changed files with 128 additions and 1 deletions

View File

@@ -114,7 +114,7 @@ function resolveHandshakeBrowserSecurityContext(params: {
);
return {
hasBrowserOriginHeader,
enforceOriginCheckForAnyClient: hasBrowserOriginHeader && !params.hasProxyHeaders,
enforceOriginCheckForAnyClient: hasBrowserOriginHeader,
rateLimitClientIp:
hasBrowserOriginHeader && isLoopbackAddress(params.clientIp)
? BROWSER_ORIGIN_LOOPBACK_RATE_LIMIT_IP