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 103
formAppSecret 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: formAppSecret
web/src/routes/admin/accounts/+page.svelte:191 — SVG xmlns="http://www.w3.org/2000/svg"
Proposed Fix
- Quick: Extend
post_match_filter for sec-hardcoded-url to exclude xmlns= and xlink:href=
- Quick: Tighten
crypto/hardcoded-secret regex in security_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.
Problem
The static security scanner and built-in rule engine both detect
hardcoded-secretandhardcoded-urlindependently with different regex patterns and different sensitivity, causing recurring false positives that block PRs.False Positive 1:
sec-hardcoded-urlon SVGxmlnsRule:
sec-hardcoded-url(builtin.rs)Regex:
http://[a-zA-Z0-9][\w.\-]+(:\d+)?(/\S*)?The W3C XML namespace URI
http://www.w3.org/2000/svgis an identifier, not a network connection. It should never be flagged.Current
post_match_filteronly excludes localhost addresses — notxmlns=.Fix: Extend
post_match_filterinbuiltin.rsto also exclude lines containingxmlns=andxlink:href=.False Positive 2:
crypto/hardcoded-secreton form variable namesRule:
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 103formAppSecretcontainssecret, and$state('')/formAppSecretmatches\S{8,}. These are UI form state variables, not hardcoded credentials.The
sec-hardcoded-secretbuiltin rule (which requires"[^"]+"— non-empty quoted string) correctly does NOT fire here. Butsecurity_scanner.rshas its own looser regex that does.Fix options:
$state,bind:,form)Structural Issue: Two duplicate rule engines
security_scanner.rsrules/builtin.rs\S{8,}(very loose)"[^"]+"(requires quoted non-empty string)http://...regexBoth run independently on the same diff. Results are merged. The looser regex in
security_scanner.rsproduces 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
CodeCorafailed with 3 false positive errors (allsec-hardcoded-urlrule 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
post_match_filterforsec-hardcoded-urlto excludexmlns=andxlink:href=crypto/hardcoded-secretregex insecurity_scanner.rs— exclude empty string values and UI binding contextPriority
P2 — false positives block PRs and erode trust in the tool. The xmlns fix is trivial and high-impact.