Skip to content

fix(security): send HSTS preload on every response path - #1313

Draft
IAmJSD wants to merge 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/issue-14
Draft

IAmJSD wants to merge 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/issue-14

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

What

Lambda mode's HSTS header dropped preload, while HTTP mode sends it (#14). API responses (internal/api/handler.go) and the container health endpoint (internal/server/health.go) lacked it as well.

The value now lives in one exported constant, api.HSTSHeaderValue (max-age=31536000; includeSubDomains; preload). All four response paths use it:

  • HTTP-mode static responses
  • Lambda static responses
  • API responses
  • the health endpoint

That way the modes can't drift apart again.

preload only makes the domain eligible for the browser preload list. Nothing is submitted. Submitting to hstspreload.org stays a separate manual step, and so does the decision to do it.

Closes #14

Testing

On a14dc8f (main):

  • Build and vet: go build ./... passes. go vet passes with and without -tags integration on internal/server and internal/api.
  • Tests: go test -race -count=1 ./internal/server/ ./internal/api/ passes.
    • The new TestSecurityHeaders_HSTSMatchesAcrossModes pins the Lambda, HTTP-mode and health headers to the constant and asserts it contains preload.
    • The six API assertions in handler_security_test.go now expect preload.
  • Lint and complexity: golangci-lint v2.10.1 reports 0 issues with and without the integration tag. gocyclo -over 10 is clean on the changed files.
  • git-secrets: scripts/test-git-secrets-allowlist.sh gives 137 PASS. A git-secrets scan of the changed files in an isolated repo is clean, and the planted key was flagged.

🤖 Generated with Claude Code

Lambda mode's static responses sent "max-age=31536000; includeSubDomains"
while HTTP mode sent the same value plus "; preload". API responses and
the health endpoint also lacked it. Move the value into one exported
constant, api.HSTSHeaderValue, used by all four paths, and add a test that
pins the Lambda, HTTP-mode and health headers to it.

"preload" only makes the domain eligible for the browser preload list;
submission to hstspreload.org remains a separate manual step.

Closes LeanerCloud#14

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@IAmJSD IAmJSD added triaged Item has been triaged priority/p3 Polish / idea / may never ship severity/low Minor harm impact/all-users Affects every user urgency/eventually No deadline effort/xs Trivial / one-liner type/security Security finding labels Oct 24, 2026
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Autofix could not be updated. Open Coding to check access and billing.

This branch has not been deployed

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

Labels

effort/xs Trivial / one-liner impact/all-users Affects every user priority/p3 Polish / idea / may never ship severity/low Minor harm triaged Item has been triaged type/security Security finding urgency/eventually No deadline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sec(frontend): HSTS preload directive missing in Lambda mode — drift from HTTP-mode security headers

2 participants