fix(security): reject 127-prefixed websocket origins (#1263)

* fix(security): reject 127-prefixed websocket origins

* style: apply prettier formatting
This commit is contained in:
Kai (Tam Nhu) Tran
2026-05-16 13:56:10 -04:00
committed by GitHub
parent 423708f28f
commit 14cbe8fb67
2 changed files with 14 additions and 1 deletions
+2 -1
View File
@@ -9,6 +9,7 @@ import session from 'express-session';
import rateLimit from 'express-rate-limit';
import crypto from 'crypto';
import * as net from 'net';
import fs from 'fs';
import path from 'path';
import {
@@ -161,7 +162,7 @@ function isLoopbackHostname(value: string | undefined): boolean {
return (
normalized === 'localhost' ||
normalized.endsWith('.localhost') ||
isLoopbackRemoteAddress(normalized)
(net.isIP(normalized) !== 0 && isLoopbackRemoteAddress(normalized))
);
}
@@ -239,6 +239,18 @@ describe('Dashboard Auth', () => {
expect(isDashboardWebSocketUpgradeAllowed(request)).toBe(true);
});
it('blocks 127-prefixed DNS names from loopback websocket origin aliases', () => {
process.env.CCS_DASHBOARD_AUTH_ENABLED = 'false';
const request = makeUpgradeRequest('127.0.0.1', false, {
host: 'localhost:3001',
origin: 'http://127.evil.example.test:3001',
});
expect(isDashboardWebSocketOriginAllowed(request)).toBe(false);
expect(isDashboardWebSocketUpgradeAllowed(request)).toBe(false);
expect(getDashboardWebSocketRejectionStatus(request)).toBe(403);
});
it('blocks cross-site websocket origins even with an authenticated session', () => {
process.env.CCS_DASHBOARD_AUTH_ENABLED = 'true';
const request = makeUpgradeRequest('127.0.0.1', true, {