Repository navigation
False positives: SVG xmlns, form variable names, and duplicate rule engines #357
Description
Problem
The static security scanner and built-in rule engine both detect hardcoded-secret and hardcoded-url independently with different regex patterns and different sensitivity, causing recurring false positives that block PRs.
False Positive 1: sec-hardcoded-url on SVG xmlns
Rule: sec-hardcoded-url (builtin.rs)
Regex: http://[a-zA-Z0-9][\w.\-]+(:\d+)?(/\S*)?
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" ...>The W3C XML namespace URI http://www.w3.org/2000/svg is an identifier, not a network connection. It should never be flagged.
Current post_match_filter only excludes localhost addresses — not xmlns=.
Fix: Extend post_match_filter in builtin.rs to also exclude lines containing xmlns= and xlink:href=.
False Positive 2: crypto/hardcoded-secret on form variable names
Rule: crypto/hardcoded-secret (security_scanner.rs line 47)
Regex: (?i)(?:password|passwd|pwd|secret|api_key|apikey|token)\s*[=:]\s*\S{8,}
let formAppSecret = $state(''); // line 21
...(formAppSecret && { app_secret: formAppSecret }), // line 103formAppSecret contains secret, and $state('') / formAppSecret matches \S{8,}. These are UI form state variables, not hardcoded credentials.
The sec-hardcoded-secret builtin rule (which requires "[^"]+" — non-empty quoted string) correctly does NOT fire here. But security_scanner.rs has its own looser regex that does.
Fix options:
- A) Exclude empty string assignments via negative context
- B) Require value to look like an actual credential (mix of alphanumeric + special chars)
- C) Exclude lines with UI binding signals (
$state,bind:,form) - D) Merge both scanners into one unified system (longer-term, eliminates divergence)
Structural Issue: Two duplicate rule engines
security_scanner.rs |
rules/builtin.rs |
|
|---|---|---|
| Hardcoded secret | \S{8,} (very loose) |
"[^"]+" (requires quoted non-empty string) |
| Hardcoded URL | not checked | http://... regex |
| Post-match filter | none | localhost exclusions |
| Test file skip | path-segment aware | simple prefix |
Both run independently on the same diff. Results are merged. The looser regex in security_scanner.rs produces findings the tighter builtin rule would not, and vice versa. This is the root cause of the divergence.
Evidence
PR: codecoradev/titen#16
CI job CodeCora failed with 3 false positive errors (all sec-hardcoded-url rule ID, but sourced from both scanners):
web/src/routes/admin/accounts/+page.svelte:21—let formAppSecret = $state('')web/src/routes/admin/accounts/+page.svelte:103—app_secret: formAppSecretweb/src/routes/admin/accounts/+page.svelte:191— SVGxmlns="http://www.w3.org/2000/svg"
Proposed Fix
- Quick: Extend
post_match_filterforsec-hardcoded-urlto excludexmlns=andxlink:href= - Quick: Tighten
crypto/hardcoded-secretregex insecurity_scanner.rs— exclude empty string values and UI binding context - Medium: Unify the two scanners into a single rule engine to eliminate regex divergence permanently
Priority
P2 — false positives block PRs and erode trust in the tool. The xmlns fix is trivial and high-impact.
Activity