Skip to content

CSP: flag policies missing both default-src and object-src#97

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/nice-mendel-s9yjgg
Open

CSP: flag policies missing both default-src and object-src#97
dmchaledev wants to merge 1 commit into
mainfrom
claude/nice-mendel-s9yjgg

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

Problem

checkCSP (src/rules.ts) already has explicit checks for form-action and base-uri — both directives that do not inherit from default-src — with comments explaining exactly why. But it has no check for the far more common case: a policy that sets narrow fetch directives (e.g. script-src) and never sets default-src at all.

Per the CSP spec, object-src, img-src, media-src, connect-src, frame-src, style-src, font-src, worker-src, etc. all fall back to default-srcbut only when default-src is present. If it's omitted, every one of those directives that isn't explicitly listed defaults to allow-all.

Concretely, before this change:

checkCSP({ 'content-security-policy': "script-src 'self'; form-action 'self'; base-uri 'self'" })
// => { score: 20, maxScore: 30, status: 'good', findings: [], recommendations: [] }

A policy that restricts scripts but leaves object-src, img-src, media-src, connect-src, frame-src, etc. completely unrestricted scores full marks with zero findings. This is one of the most common real-world CSP misconfigurations (a site restricts script-src for XSS and assumes that's "the CSP," never realizing everything else defaults open) and is one of the first things flagged by comparable scanners — Google's CSP Evaluator (missing-default-src-fallback / no object-src fallback) and Mozilla's HTTP Observatory both check for it.

object-src specifically remains a legacy but still-audited vector: <object>/<embed> plugin content is not governed by script-src, so without a default-src fallback or an explicit object-src 'none', plugin-based content injection is entirely unrestricted.

Fix

Added one more explicit check to checkCSP, following the exact same pattern as the existing form-action/base-uri checks: if neither default-src nor object-src is present in the policy, deduct 2 points and emit a finding + remediation. Matching object-src 'none' or any default-src (regardless of its own value — that's already covered by the existing wildcard check) satisfies it.

checkCSP({ 'content-security-policy': "script-src 'self'; form-action 'self'; base-uri 'self'" })
// => score: 18, finding: "No default-src or object-src directive — plugin content
//     (<object>/<embed>) is unrestricted, and any other fetch directive not
//     explicitly listed defaults to allow-all"

Changes

  • src/rules.ts: new check in checkCSP, same shape/weight (-2) as the existing base-uri check.
  • test/analyzer.test.ts: 3 new tests (missing both → flagged, default-src present → satisfied, object-src 'none' alone → satisfied) plus an existing test's expected score updated from 20 → 18, since its fixture policy (script-src + strict-dynamic/nonce, no default-src/object-src) is exactly the case this now catches.
  • README.md: updated the CSP row in "Headers Checked" to mention the new object-src fallback check.

Verified: npm run typecheck, npm test (88/88 passing), and npm run build all pass locally. No other existing test needed changes — every other CSP fixture in the suite already sets default-src explicitly (even ones with bad/permissive values, which is a separate, already-covered wildcard check), so this is purely additive for the one gap it targets.

🤖 Generated with Claude Code


Generated by Claude Code

object-src falls back to default-src, but only when default-src is
actually set. A policy like `script-src 'self'; form-action 'self'`
currently scores 20/30 (good, zero findings) even though it leaves
object-src and every other unlisted fetch directive (img-src, media-src,
connect-src, etc.) completely unrestricted with no fallback to inherit
from. This is one of the most common real-world CSP misconfigurations
and is flagged by every comparable scanner (Google's CSP Evaluator,
Mozilla Observatory).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants