mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
security: add baseline security headers to gateway HTTP responses (#10526)
* security: add baseline security headers to gateway HTTP responses All responses from the gateway HTTP server now include X-Content-Type-Options: nosniff and Referrer-Policy: no-referrer. These headers are applied early in handleRequest, before any handler runs, ensuring coverage for every response including error pages and 404s. Headers that restrict framing (X-Frame-Options, CSP frame-ancestors) are intentionally omitted at this global level because the canvas host and A2UI handlers serve content that may be loaded inside frames. * fix: apply security headers before WebSocket upgrade check Move setDefaultSecurityHeaders() above the WebSocket early-return so the headers are set on every HTTP response path including upgrades. --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -2,6 +2,17 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import type { GatewayAuthResult } from "./auth.js";
|
||||
import { readJsonBody } from "./hooks.js";
|
||||
|
||||
/**
|
||||
* Apply baseline security headers that are safe for all response types (API JSON,
|
||||
* HTML pages, static assets, SSE streams). Headers that restrict framing or set a
|
||||
* Content-Security-Policy are intentionally omitted here because some handlers
|
||||
* (canvas host, A2UI) serve content that may be loaded inside frames.
|
||||
*/
|
||||
export function setDefaultSecurityHeaders(res: ServerResponse) {
|
||||
res.setHeader("X-Content-Type-Options", "nosniff");
|
||||
res.setHeader("Referrer-Policy", "no-referrer");
|
||||
}
|
||||
|
||||
export function sendJson(res: ServerResponse, status: number, body: unknown) {
|
||||
res.statusCode = status;
|
||||
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
resolveHookChannel,
|
||||
resolveHookDeliver,
|
||||
} from "./hooks.js";
|
||||
import { sendGatewayAuthFailure } from "./http-common.js";
|
||||
import { sendGatewayAuthFailure, setDefaultSecurityHeaders } from "./http-common.js";
|
||||
import { getBearerToken, getHeader } from "./http-utils.js";
|
||||
import { isPrivateOrLoopbackAddress, resolveGatewayClientIp } from "./net.js";
|
||||
import { handleOpenAiHttpRequest } from "./openai-http.js";
|
||||
@@ -474,6 +474,8 @@ export function createGatewayHttpServer(opts: {
|
||||
});
|
||||
|
||||
async function handleRequest(req: IncomingMessage, res: ServerResponse) {
|
||||
setDefaultSecurityHeaders(res);
|
||||
|
||||
// Don't interfere with WebSocket upgrades; ws handles the 'upgrade' event.
|
||||
if (String(req.headers.upgrade ?? "").toLowerCase() === "websocket") {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user