Skip to content

add Cache-Control: no-store via security headers middleware - #3712

Closed
aydnOktay wants to merge 8 commits into
NousResearch:mainfrom
aydnOktay:feat/security-cache-control-no-store
Closed

add Cache-Control: no-store via security headers middleware#3712
aydnOktay wants to merge 8 commits into
NousResearch:mainfrom
aydnOktay:feat/security-cache-control-no-store

Conversation

@aydnOktay

Copy link
Copy Markdown
Contributor

This PR adds a secure default Cache-Control: no-store header to all API responses via the existing security_headers_middleware. This prevents intermediaries and browsers from persisting sensitive payloads, aligning with best practices and reducing data leakage risk. The change is minimal and low risk, and includes a focused unit test asserting the header is present on a simple GET /v1/models response

@alt-glitch alt-glitch added type/security Security vulnerability or hardening P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery labels May 2, 2026

@teknium1 teknium1 left a comment

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.

Thanks for the focused security goal. The current middleware is still the correct live integration point: gateway/platforms/api_server.py:698-703 has no Cache-Control default and is installed by the server at gateway/platforms/api_server.py:4766-4767.

Problems

  • The added setdefault does not cover streaming responses. Four current SSE constructors explicitly set Cache-Control: no-cache at gateway/platforms/api_server.py:2031, :2420, :2650, and :4516; those values remain unchanged.
  • The added /v1/models test covers only a normal response, not those streaming paths.
  • agent/skill_commands.py and the CORS expose-header change are unrelated to the stated cache-control scope. The linked salvage PR #62759 also identifies the skill changes as drive-bys.

Suggested changes

  • Keep this change API-header-only, set the intended cache directive on the four SSE response constructors too, and add streamed-response coverage.

Automated hermes-sweeper review.

response = await handler(request)
for k, v in _SECURITY_HEADERS.items():
response.headers.setdefault(k, v)
response.headers.setdefault("Cache-Control", "no-store")

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.

setdefault leaves existing Cache-Control: no-cache headers untouched. The API server has explicit SSE response headers, so this does not provide the PR's stated all-responses no-store guarantee; update and test those streaming header paths too.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
Bartok9 pushed a commit to Bartok9/hermes-agent that referenced this pull request Aug 1, 2026
@aydnOktay

Copy link
Copy Markdown
Contributor Author

Closing to concentrate review on a single linked product bug: #89979.

@aydnOktay aydnOktay closed this Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants