Skip to content

fix(WILDCARD_CORS): detect null-origin bypass and wildcard-subdomain origins#46

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/amazing-franklin-ezrbc8
Open

fix(WILDCARD_CORS): detect null-origin bypass and wildcard-subdomain origins#46
dmchaledev wants to merge 1 commit into
mainfrom
claude/amazing-franklin-ezrbc8

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

Summary

The WILDCARD_CORS rule (src/rules/config-rules.ts) only matched a literal "*" entry (origins.includes('*')). It silently passed two other classic permissive-origin misconfigurations that defeat the same-origin policy just as effectively:

  • The "null" origin — reachable from sandboxed iframes, data:/file: documents, and some cross-origin redirects. Allow-listing null is a well-documented way to bypass a CORS allow-list (PortSwigger: CORS vulnerabilities).
  • Wildcard-subdomain patterns such as https://*.example.com — these trust every current and future subdomain, including any that later becomes attacker-controlled (dangling DNS, takeover, a compromised low-value subdomain).

Both are now flagged under the existing MEDIUM WILDCARD_CORS rule. This is a false-negative fix in the scanner's core mission (an advertised "unsafe defaults / CORS wildcards" check), consistent with recently-accepted rule-hardening PRs that catch obvious cases an existing rule missed.

Before / after

// cors.origins: ["https://app.example.com", "null", "https://*.internal.example.com"]
before after
"*" flagged flagged
"null" missed flagged
"https://*.example.com" missed flagged
"https://app.example.com" not flagged not flagged

Behavior details

  • Detection is case-insensitive for the null origin (matches Origin: null as a browser sends it).
  • The finding's evidence lists only the offending origins, so specific/safe origins in the same allow-list are not reported as evidence.
  • A * appearing anywhere other than a bare "*" is treated as a wildcard host pattern.
  • Same ruleId, severity (MEDIUM), and docsUrl as before — the rule title is generalized from "Wildcard CORS Origin Configured" to "Insecure CORS Origin Configured" to cover all three cases. No new RuleId and no scoring change.

Tests

  • New: "null" origin (case-insensitive) fires and reports only the offending origin.
  • New: wildcard-subdomain pattern fires.
  • Broadened the negative test to a multi-origin safe allow-list (asserts no finding).
  • Full suite green: 120 passed. tsc --noEmit, eslint --max-warnings 0, and npm run build all pass; CLI smoke-tested end-to-end against a config exercising all three cases.

Acceptance criteria

  • cors.origins containing "null" produces a WILDCARD_CORS finding.
  • A wildcard-subdomain origin (https://*.example.com) produces a finding.
  • A literal "*" still fires (no regression).
  • Specific, fully-qualified origins do not fire.
  • Evidence names only the offending origins.

🤖 Generated with Claude Code

https://claude.ai/code/session_0141pv1QamJWRKky2mJxVpi1


Generated by Claude Code

…origins

The CORS rule only matched a literal "*" entry, silently passing two
other classic permissive-origin misconfigurations:

  - the "null" origin, which is reachable from sandboxed iframes,
    data:/file: documents, and some redirects — a well-known way to
    defeat an allow-list; and
  - wildcard-subdomain patterns such as "https://*.example.com", which
    trust every current and future subdomain, including any that later
    becomes attacker-controlled.

Both are now flagged under the existing MEDIUM WILDCARD_CORS rule.
Evidence lists only the offending origins (case-insensitive "null"
match), so specific, safe origins in the same allow-list are not
reported. Adds regression tests for the null-origin and
wildcard-subdomain cases and broadens the negative test to a
multi-origin safe allow-list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141pv1QamJWRKky2mJxVpi1
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