Problem
PR #484 fixed the original false positive (#483) but over-corrected, introducing 3 new issues identified in post-merge audit.
Finding 1 — Regex misses common real-world patterns (MAJOR)
The narrowed regex only catches 3 narrow forms. 13 of 14 common framework CORS patterns are MISSED:
| Pattern |
Framework |
Currently Detected? |
Access-Control-Allow-Origin: * |
HTTP Header |
✅ |
cors = "*" |
Generic |
✅ |
origin: * |
Generic |
✅ |
add_header Access-Control-Allow-Origin *; |
nginx |
❌ |
CORS_ALLOW_ALL_ORIGINS = True |
Django |
❌ |
.allowedOrigins("*") |
Spring Boot |
❌ |
AllowAnyOrigin() |
.NET |
❌ |
.allow_origin(Any) |
tower-http (Rust) |
❌ |
allow_origins=["*"] |
FastAPI/Starlette |
❌ |
cors({ origin: true }) |
Express.js |
❌ |
AllowOrigins: ["*"] |
Go Fiber |
❌ |
cors_origins = ["*"] |
Rust config |
❌ |
set_header Access-Control-Allow-Origin "*" |
actix-web |
❌ |
Finding 2 — Negation filter false negatives (MAJOR)
is_false_positive_cors() in builtin.rs:258-278 uses unanchored .* patterns that match across comment→code boundaries:
"except.*wildcard", // Matches: "Except for wildcard: cors = \"*\"" (suppresses real finding!)
"not.*wildcard", // Matches: "if not_wildcard_mode { origin = \"*\" }"
Real-world cases wrongly suppressed:
# Except for wildcard endpoints: cors = "*" — actual wildcard after comment
if not_wildcard_mode { origin = "*" } — variable name triggers negation match
// no wildcard for now, but origin = "*" — actual code after comment
Finding 3 — CORS_CONFIG env-key suppression is too broad (MAJOR)
builtin.rs:284 — lower.contains("cors_config") suppresses any line containing that substring, including actual dangerous assignments:
// Suppressed (correctly — env var read):
let origins = env::var("CORS_CONFIG").unwrap();
// Also suppressed (WRONG — real wildcard assignment):
CORS_CONFIG = "*"
Finding 4 — Performance: 12 regexes compiled per call (MINOR)
builtin.rs:272-277 compiles 12 regexes inside is_false_positive_cors() on every match. Several markers are plain strings that could use str::contains(). Regex compilation should use LazyLock<Vec<Regex>> or std::sync::OnceLock.
Suggested Fix
- Widen regex to cover framework patterns (nginx
add_header, Django CORS_ALLOW_ALL, Spring allowedOrigins, etc.)
- Anchor negation patterns — require negation marker at line start (after comment trim), not anywhere on line
- Scope env-key suppression — only suppress when
env::var("...") or getenv("...") pattern is present
- Pre-compile regexes — use
LazyLock for static regex patterns
Related
Problem
PR #484 fixed the original false positive (#483) but over-corrected, introducing 3 new issues identified in post-merge audit.
Finding 1 — Regex misses common real-world patterns (MAJOR)
The narrowed regex only catches 3 narrow forms. 13 of 14 common framework CORS patterns are MISSED:
Access-Control-Allow-Origin: *cors = "*"origin: *add_header Access-Control-Allow-Origin *;CORS_ALLOW_ALL_ORIGINS = True.allowedOrigins("*")AllowAnyOrigin().allow_origin(Any)allow_origins=["*"]cors({ origin: true })AllowOrigins: ["*"]cors_origins = ["*"]set_header Access-Control-Allow-Origin "*"Finding 2 — Negation filter false negatives (MAJOR)
is_false_positive_cors()inbuiltin.rs:258-278uses unanchored.*patterns that match across comment→code boundaries:Real-world cases wrongly suppressed:
# Except for wildcard endpoints: cors = "*"— actual wildcard after commentif not_wildcard_mode { origin = "*" }— variable name triggers negation match// no wildcard for now, but origin = "*"— actual code after commentFinding 3 —
CORS_CONFIGenv-key suppression is too broad (MAJOR)builtin.rs:284—lower.contains("cors_config")suppresses any line containing that substring, including actual dangerous assignments:Finding 4 — Performance: 12 regexes compiled per call (MINOR)
builtin.rs:272-277compiles 12 regexes insideis_false_positive_cors()on every match. Several markers are plain strings that could usestr::contains(). Regex compilation should useLazyLock<Vec<Regex>>orstd::sync::OnceLock.Suggested Fix
add_header, DjangoCORS_ALLOW_ALL, SpringallowedOrigins, etc.)env::var("...")orgetenv("...")pattern is presentLazyLockfor static regex patternsRelated