Skip to content

fix(coderd): add frame-ancestors CSP directive to prevent clickjacking#24474

Merged
jdomeracki-coder merged 3 commits intomainfrom
fix/clickjacking-frame-ancestors
Apr 20, 2026
Merged

fix(coderd): add frame-ancestors CSP directive to prevent clickjacking#24474
jdomeracki-coder merged 3 commits intomainfrom
fix/clickjacking-frame-ancestors

Conversation

@jdomeracki-coder
Copy link
Copy Markdown
Contributor

The Coder dashboard CSP headers did not include a frame-ancestors
directive, allowing any external site to embed dashboard pages in an iframe
for clickjacking attacks. Only the OAuth2 consent page had hardcoded
protection (frame-ancestors 'none' + X-Frame-Options: DENY).

This change adds frame-ancestors 'self' as the default for all pages
served through the CSP middleware, and registers agent embed routes
(/agents/{id}/embed) with frame-ancestors * so the VS Code extension
iframe continues to work. Deployments that already set frame-ancestors
via CODER_ADDITIONAL_CSP_POLICY keep their custom value — the default
only applies when no override is present.

Implementation notes
  • coderd/httpmw/csp.go: After the staticAdditions loop, set
    frame-ancestors 'self' only if no entry already exists. This lets
    staticAdditions (including the deployment-level
    CODER_ADDITIONAL_CSP_POLICY) override the default.
  • coderd/coderd.go: Extract proxy-hosts closure into a shared
    cspProxyHosts variable. Create a second CSP middleware instance for
    embed routes with frame-ancestors *, and register
    /agents/{agentId}/embed + /agents/{agentId}/embed/* before the
    r.NotFound catch-all.
  • coderd/httpmw/csp_test.go: Two new subtests — default 'self' and
    override via staticAdditions.

🤖 Generated by Coder Agents

Add frame-ancestors 'self' as a default CSP directive to prevent
clickjacking attacks against all Coder dashboard pages. Agent embed
routes (/agents/{id}/embed) use frame-ancestors * so the VS Code
extension iframe continues to work.
@jdomeracki-coder
Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e7ae293ee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/coderd.go Outdated
for k, v := range additionalCSPHeaders {
embedCSPHeaders[k] = v
}
embedCSPHeaders[httpmw.CSPFrameAncestors] = []string{"*"}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Respect operator frame-ancestors on embed routes

This assignment unconditionally replaces any frame-ancestors value from CODER_ADDITIONAL_CSP_POLICY for /agents/{agentId}/embed*. In deployments that intentionally set a stricter policy (for example 'none' or a specific allowlist), the embed route is now force-opened to all origins, which weakens an explicit security configuration and contradicts the expected “operator override wins” behavior. The embed override should be a fallback only when no explicit frame-ancestors is configured.

Useful? React with 👍 / 👎.

Only default embed routes to frame-ancestors * when the operator
has not explicitly set frame-ancestors via CODER_ADDITIONAL_CSP_POLICY.
If they configured a stricter policy, it takes precedence.
Copy link
Copy Markdown
Contributor Author

Addressed in 8d6e2e1 — the embed route now only defaults to frame-ancestors * when the operator hasn't explicitly set frame-ancestors via CODER_ADDITIONAL_CSP_POLICY. If they configured a stricter policy, it takes precedence.

🤖 Generated by Coder Agents

@jdomeracki-coder jdomeracki-coder marked this pull request as ready for review April 17, 2026 14:18
Copy link
Copy Markdown
Contributor

@jeremyruppel jeremyruppel left a comment

Choose a reason for hiding this comment

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

LGTM

@jdomeracki-coder jdomeracki-coder merged commit 615be17 into main Apr 20, 2026
31 checks passed
@jdomeracki-coder jdomeracki-coder deleted the fix/clickjacking-frame-ancestors branch April 20, 2026 11:01
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants