security(relay): fix lockout DoS and DOM XSS in web client
Addresses two Major findings from PR review: - Auth lockout no longer griefable: the throttle key is namespaced per path and includes the client IP (web:<session>:<ip> vs desktop:<session>:<ip>), so a flood of bad web-client auths can neither lock other clients of the same session nor block the desktop from (re)authenticating. Per-socket failure close and brute-force lockout are preserved. - Relay web client XSS eliminated: app.html tab/macro rendering rebuilt with createElement/textContent (no macro/tab value reaches innerHTML); inline scripts/handlers externalized to /static/app.js and /static/login.js so the helmet CSP now uses script-src 'self' (dropped 'unsafe-inline' for scripts). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -89,12 +89,15 @@ export function createServer() {
|
||||
|
||||
// Middleware
|
||||
app.use(helmet({
|
||||
// The bundled login/app pages rely on inline <script> and inline event
|
||||
// handlers, so script/style inline is permitted; images may be blobs.
|
||||
// Page scripts are served as external files (/static/app.js,
|
||||
// /static/login.js) with no inline handlers, so scripts are restricted to
|
||||
// 'self' (no 'unsafe-inline'). The pages still use inline <style> blocks,
|
||||
// so style-src keeps 'unsafe-inline'. Images may be data:/blob: (macro
|
||||
// images are loaded as blob object URLs) and WS connections need ws:/wss:.
|
||||
contentSecurityPolicy: {
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
scriptSrc: ["'self'", "'unsafe-inline'"],
|
||||
scriptSrc: ["'self'"],
|
||||
styleSrc: ["'self'", "'unsafe-inline'"],
|
||||
imgSrc: ["'self'", 'data:', 'blob:'],
|
||||
connectSrc: ["'self'", 'ws:', 'wss:'],
|
||||
@@ -192,7 +195,7 @@ export function createServer() {
|
||||
// Desktop connection: /desktop
|
||||
if (pathname === '/desktop') {
|
||||
wss.handleUpgrade(request, socket, head, (ws) => {
|
||||
handleDesktopConnection(ws, connectionManager, sessionManager);
|
||||
handleDesktopConnection(ws, connectionManager, sessionManager, ip);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -202,7 +205,7 @@ export function createServer() {
|
||||
if (webClientMatch) {
|
||||
const sessionId = webClientMatch[1];
|
||||
wss.handleUpgrade(request, socket, head, (ws) => {
|
||||
handleWebClientConnection(ws, sessionId, connectionManager, sessionManager);
|
||||
handleWebClientConnection(ws, sessionId, connectionManager, sessionManager, ip);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user