Skip to content

Security hardening: sanitize MCP App CSP domains - #17192

Merged
gr2m merged 5 commits into
mainfrom
dnukumamras/csp-injection-mcp-apps
Jul 14, 2026
Merged

Security hardening: sanitize MCP App CSP domains#17192
gr2m merged 5 commits into
mainfrom
dnukumamras/csp-injection-mcp-apps

Conversation

@dnukumamras

Copy link
Copy Markdown
Contributor

getMCPAppCSP in packages/react/src/mcp-apps/sandbox.ts interpolated server-supplied domain values (connectDomains, resourceDomains, frameDomains) straight into the Content-Security-Policy string. Since CSP directives are ;-separated and sources are whitespace-separated, a value could break out of its directive and inject arbitrary sources, directives, or policies.

This adds a sanitizeCSPSources filter that drops any value containing whitespace, ;, or , before it reaches the policy string.

Behavior

Happy path:

  • Valid domains (e.g. https://api.example.com) pass through unchanged into their directives.
  • Benign policies produce the exact same output as before.

Unhappy path:

  • A value like https://api.example.test; script-src-elem https://attacker.example is dropped entirely, so no extra directive appears.
  • A value containing , (which could split into a second policy) is dropped.
  • The generated policy always keeps exactly its seven intended directives.

Tests

Added sandbox.test.ts covering valid passthrough and injection-attempt rejection.

🤖 Generated with Claude Code

Filter out domain values containing whitespace, ";" or "," before
interpolating them into the generated Content-Security-Policy so a
malicious value cannot inject additional sources, directives, or
policies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Validate each server-supplied CSP domain by parsing it as an absolute
URL, keeping only https/wss origins, and re-checking the decoded origin.
This closes an encoding bypass where a percent-encoded separator (e.g.
"%3B") passes a raw-string filter but decodes back into ";" downstream,
and additionally rejects non-https/wss schemes and bare keyword sources.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lock base-uri and form-action to 'none' so a sandboxed app cannot
retarget <base href> or submit forms to an arbitrary destination.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…P sources

Drop a bare "*" host (which allows every origin, defeating the scheme
allowlist) and reject quote/backtick characters that survive URL parsing
and could break out of an HTML attribute the policy is embedded in.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gr2m
gr2m merged commit 519c72b into main Jul 14, 2026
49 checks passed
@gr2m
gr2m deleted the dnukumamras/csp-injection-mcp-apps branch July 14, 2026 19:26
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Published in:

Package Version
@ai-sdk/react 4.0.29 github npm

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants