Skip to content

security(gateway): add baseline HTTP security headers#6171

Closed
unisone wants to merge 2 commits intoopenclaw:mainfrom
unisone:security/http-security-headers
Closed

security(gateway): add baseline HTTP security headers#6171
unisone wants to merge 2 commits intoopenclaw:mainfrom
unisone:security/http-security-headers

Conversation

@unisone
Copy link
Copy Markdown
Contributor

@unisone unisone commented Feb 1, 2026

Summary

Adds a small set of conservative, baseline HTTP security headers to gateway HTTP responses (Control UI + API).

Why

These headers reduce common web attack surface (content sniffing, clickjacking, overly-permissive browser features, referrer leakage) in cases where the gateway is exposed on a LAN/tailnet or behind a reverse proxy.

Changes

  • Add baseline headers: X-Content-Type-Options, Referrer-Policy, X-Frame-Options, Permissions-Policy
  • Add an e2e test to assert headers are present on Control UI responses
  • Intentionally does not add CSP yet (to avoid breaking existing UI builds); CSP can be layered in a follow-up PR once validated.

Testing

  • pnpm exec vitest run --config vitest.e2e.config.ts test/security-headers.e2e.test.ts

Greptile Overview

Greptile Summary

This PR adds a small set of baseline HTTP response security headers (nosniff, referrer-policy, frame blocking, and a restrictive permissions-policy) to the gateway HTTP server, and adds an e2e test that asserts these headers are present on the Control UI root response.

The header logic is applied at the top of handleRequest in src/gateway/server-http.ts, before dispatching to the various route handlers (hooks/tools/slack/openai/canvas/control-ui), making it a cross-cutting behavior for most HTTP responses produced by the gateway.

Confidence Score: 4/5

  • This PR is largely safe to merge and implements conservative header hardening with minor scoping/testing concerns.
  • Changes are straightforward and localized: a new helper applies headers and an e2e test asserts presence. The main risk is behavioral/compat impact from globally applying X-Frame-Options: DENY beyond just the Control UI, and potential test flakiness from process-wide env mutation under concurrency.
  • src/gateway/server-http.ts (header scoping/intent); test/security-headers.e2e.test.ts (env isolation under parallel tests)

(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!

Context used:

  • Context from dashboard - CLAUDE.md (source)
  • Context from dashboard - AGENTS.md (source)

@openclaw-barnacle openclaw-barnacle bot added the gateway Gateway runtime label Feb 1, 2026
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +264 to 266
applyBaselineSecurityHeaders(res);

try {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] applyBaselineSecurityHeaders runs before routing, so it will also apply to non-UI/API responses (e.g., webhook/slack/etc.) and to error responses generated later, but not to early-return cases like WebSocket upgrades. If the intent is “Control UI + API”, this may be broader than expected and could impact embedded/iframe use cases due to X-Frame-Options: DENY.

If you want to scope it, consider applying these headers only for the UI routes / API routes, or at least documenting that it is intentionally global for all HTTP responses (except upgrade path).

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/gateway/server-http.ts
Line: 264:266

Comment:
[P1] `applyBaselineSecurityHeaders` runs before routing, so it will also apply to non-UI/API responses (e.g., webhook/slack/etc.) and to *error responses generated later*, but not to early-return cases like WebSocket upgrades. If the intent is “Control UI + API”, this may be broader than expected and could impact embedded/iframe use cases due to `X-Frame-Options: DENY`.

If you want to scope it, consider applying these headers only for the UI routes / API routes, or at least documenting that it is intentionally global for all HTTP responses (except upgrade path).

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +18 to +22
const token = "test-token-security-headers";
process.env.OPENCLAW_GATEWAY_TOKEN = token;
process.env.OPENCLAW_SKIP_CHANNELS = "1";
process.env.OPENCLAW_SKIP_CRON = "1";
process.env.OPENCLAW_SKIP_CANVAS_HOST = "1";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] This test mutates process-wide env vars (process.env.*) and assumes no other tests are running concurrently in the same worker that depend on these values. In parallel test runs this can cause flaky cross-test interference.

If the test runner is configured for concurrency, consider isolating via vi.stubEnv (or an equivalent helper used in this repo) or ensuring this file runs serially.

Prompt To Fix With AI
This is a comment left during a code review.
Path: test/security-headers.e2e.test.ts
Line: 18:22

Comment:
[P2] This test mutates process-wide env vars (`process.env.*`) and assumes no other tests are running concurrently in the same worker that depend on these values. In parallel test runs this can cause flaky cross-test interference.

If the test runner is configured for concurrency, consider isolating via `vi.stubEnv` (or an equivalent helper used in this repo) or ensuring this file runs serially.

How can I resolve this? If you propose a fix, please make it concise.

@unisone
Copy link
Copy Markdown
Contributor Author

unisone commented Feb 1, 2026

Addressed Greptile notes:

  • Use X-Frame-Options: SAMEORIGIN (instead of DENY) to avoid surprising breakage for same-origin embedding while still blocking third-party framing.
  • Test now uses vi.stubEnv/vi.unstubAllEnvs to avoid cross-test env pollution.

@clawdinator
Copy link
Copy Markdown
Contributor

clawdinator bot commented Feb 1, 2026

CLAWDINATOR FIELD REPORT // PR Closure

I am CLAWDINATOR — cybernetic crustacean, maintainer triage bot for OpenClaw. I was sent from the future to keep this repo shipping clean code.

OpenClaw has 800+ open PRs. We're aggressively closing features, CI changes, and non-critical improvements. If this change is important, open an issue first to discuss with maintainers.

TERMINATED.

🤖 This is an automated message from CLAWDINATOR, the OpenClaw maintainer bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant