fix: skip taint pass instead of erroring when a language has no taint rules - #74
Open
juangaitanv wants to merge 1 commit into
Open
fix: skip taint pass instead of erroring when a language has no taint rules#74juangaitanv wants to merge 1 commit into
juangaitanv wants to merge 1 commit into
Conversation
… rules run_taint_analysis_with_verbosity returned a hard Err when the merged rule set contained zero mode="taint" rules. In the default scan mode the taint pass runs second, so the `?` discarded the already-computed search findings and aborted with exit 1. rules/html and rules/objectscript are search-mode only, so every single-file scan of those languages hit the guard. Directory scans masked it because the count is over the merged rule set for all detected languages. A rule pack with no taint rules is a corpus property, not a failure. Emit a show_progress-gated notice on stderr and return Ok(Vec::new()), matching vulnerability_scanner.rs which already answers the strictly worse condition (both rule halves empty) the same way. Adds two feature-gated single-file regression tests (html, objectscript); a directory scan would pass without the fix.
juangaitanv
requested review from
Ibrahimrahhal,
asadeddin,
leenk7991 and
yhoztak
August 24, 2026 10:03
leenk7991
approved these changes
Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Scanning any single
.htmlfile failed with exit 1:Our release benchmark saw 179/179 html file scans error out.
Root cause
src/scanner/modes.rs:544-548—run_taint_analysis_with_verbosityreturned a hardErrwhen the loaded rule set contained zeromode = "taint"rules. The default scan mode (src/main.rs:119-130) runs the search pass first and the taint pass second; the?on the taint call discarded the already-computed search findings and aborted the process.rules/html(7 rules) andrules/objectscript(5 rules) are search-mode only, so every single-file scan of those languages hit the guard. Directory scans were unaffected — the guard counts over the merged rule set for all detected languages, so any python/javascript file in the tree masked it. That is why this shipped unnoticed; the per-file invocation contract (sighthound --output-format json <file>) is what bites.Fix
A rule pack with no taint rules is a corpus property, not a failure. The guard now emits a
show_progress-gated notice on stderr and returnsOk(Vec::new()), so the search-pass findings survive and the process exits 0. This matchesvulnerability_scanner.rs:777-783, which already answers the strictly worse condition (both rule halves empty) withOk(Vec::new()).No language is special-cased — the condition is a count over the merged rule set — so
objectscriptis fixed by the same change. No new CLI flag; the invocation contract is unchanged. stdout stays pure JSON under--output-format json.Tests
Two feature-gated regression tests in
tests/strictness/language_coverage.rs, one for html and one for objectscript. Each scans a single file — load-bearing, since a directory scan merges in python/javascript taint rules and would pass without the fix. Verified by stashing themodes.rshunk: both tests fail (left: Some(1) right: Some(0)), and pass with it.They assert exit 0, stdout parses as a JSON array, the notice appears on stderr only, and the old error string is gone.
Verification
cargo test— 258 passed, exit 0make ci— exit 0 (only pre-existing advisory CRAP/complexity lines)sighthound --output-format json <pygoat .html>— prints[], exit 0 (was exit 1)realvuln-pygoat+realvuln-lets-be-bad-guys:No taint flow rules foundwarnings 148 → 0, zero failed scans. Every scoreboard row is numerically identical to the pre-fix baseline, includinglanguage:javascript(TP=1 PREC=1.000 REC=1.000) andlanguage:python(TP=13 FN=70) — no behavior change for languages that do have taint rules.datasets/insecure-js/server.js) are byte-identical before and after.Known gap (separate work, not this PR)
The
language:htmlscoreboard row staysTP=0 FP=0 FN=17 TN=6. That row is unchanged because the benchmark already scored a failed scan as "found nothing" — TP cases became FN, hard negatives became TN. The observable win here is exit 1 → exit 0 and 148 warnings → 0.html recall is a separate rules-coverage gap, not part of this regression.
main's html pack is Thymeleaf / inline-<script>tuned and verifiably fires on those shapes; the benchmark corpus is Django/Jinja templates ({{ query|safe }},<form method="POST">with no{% csrf_token %}), which no current html rule matches. The 7 html TPs the 0.1.2 release binary scored came from a generic rule pack (rules/html/html_security.ron) that only ever existed on the orphan release lineage, and they were line-window coincidences — e.g.CASE-1536expects CWE-79 atxss_lab.html:27(the|safeline) and 0.1.2 matched it with an inlineonclickhandler finding at line 36. Porting that pack back would trade precision on the curated hard negatives for coincidental recall, so it is deliberately out of scope.