EXT-003 Extension CSP allows remote code load
The Content Security Policy in a browser extension's manifest
constrains what scripts the extension can run. A CSP that
permits unsafe-eval inside a script-src directive lets the
extension call eval(), new Function(), and similar
runtime-string-to-code primitives. A CSP that permits
unsafe-inline lets the extension execute scripts injected
into a page at runtime. Either is effectively a remote-code-
load primitive: static review of the extension's bundle never
sees the payload because the payload is built or fetched at
runtime.
A publisher compromise of an extension with this CSP reaches every user the next time they open the browser.
What Vulkro detects
Rule fires when an extension's manifest content_security_policy
contains unsafe-eval or unsafe-inline AND the keyword sits
inside a script-src or default-src directive. (Manifest V3
nests CSP under extension_pages / sandbox; the parser
collapses both into a single scan string so the same check
covers MV2 and MV3.)
unsafe-inline inside a style-src directive does NOT fire:
runtime-styled CSS is not a remote-code-load primitive in this
threat model.
Severity: High. Confidence: High. Evidence signal:
extension-remote-code-load-csp, weight 0.9, source Pattern.
Non-compliant manifest (Manifest V2 form)
{
"manifest_version": 2,
"name": "Inline-friendly tool",
"version": "1.0.0",
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}
Non-compliant manifest (Manifest V3 form)
{
"manifest_version": 3,
"name": "Inline-friendly tool",
"version": "1.0.0",
"content_security_policy": {
"extension_pages": "script-src 'self' 'unsafe-inline'; object-src 'self'"
}
}
Both let the extension execute string-to-code at runtime. A publisher account compromise can push an update whose payload the marketplace's static review never saw.
Compliant manifest
{
"manifest_version": 3,
"name": "Inline-friendly tool",
"version": "1.0.0",
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
}
}
'self' only: the extension can only execute scripts bundled
inside its own package, which marketplace review reads at
publish time.
Remediation
- Replace the permissive CSP with the marketplace default:
script-src 'self'; object-src 'self'. This is the value Chrome and Firefox bake in when no CSP is declared, and the value extensions should keep unless they have an explicit reason to widen it. - If the extension genuinely needs to evaluate runtime- generated code (a sandboxed live-coding tool, a notebook- style UI), bundle the evaluator. Ship a complete interpreter inside the extension rather than asking the browser to permit string-to-code.
- If the extension needs third-party scripts, list each host
explicitly in
script-src. A surgical allowlist (script-src 'self' https://cdn.example.com/) is reviewable;unsafe-evalis not. - When auditing a third-party extension, treat an
unsafe-evalCSP as equivalent to a remote-code-load primitive. A publisher compromise reaches every user the next time they open the browser.
See also
vulkro extension-audit- parent CLI command.- EXT-001 - catalog hit for an already-compromised extension.
- EXT-002 - overbroad permissions on the same manifest.
- Confidence model - what
High,Medium,Lowmean.