module

NoirPassiveScan

Class methods

detect(file_path : String, file_content : String, rules : Array(PassiveScan), logger : NoirLogger | Nil) : Array(PassiveScanResult)

Runs every supplied rule against file_content. The only side effect is recording a rule that raised (see record_rule_failure). Callers are responsible for pre-filtering by severity (see filter_rules_by_severity). Returns an empty array (no allocation beyond the literal) when there are no rules to run, so callers can short-circuit on passive_scans.empty? before reading the file.

file_content must be valid UTF-8 — the scan reads it through Noir::TextFile.read — because matching skips PCRE2's per-call re-validation (Noir::TextFile::MATCH_OPTIONS).

Each matcher keeps its own whole-file pre-check. Folding every rule's patterns into one alternation looks cheaper but measured ~6x slower: the union has no common first byte, so PCRE2 loses the literal-prefix skip that lets each separate matcher jump straight to candidates.

Pass a nil logger to run silently — the detect walk runs this on its read threads and logs the matches itself, in walk order.

Source
filter_rules_by_severity(rules : Array(PassiveScan), min_severity : String) : Array(PassiveScan)

Pre-filter the rule set against min_severity. Callers should run this once at scan-startup and pass the result into detect per file, so the per-(file × rule) severity comparison is amortized down to a single pass over the rule set.

Source
load_rules(path : String, logger : NoirLogger) : Array(PassiveScan)
Source
reject_duplicate_ids(rules : Array(PassiveScan), logger : NoirLogger) : Array(PassiveScan)

Keep the first rule for each id and drop the rest.

A rule id is the finding's identity: it is what -f json reports, what SARIF uses as ruleId, and what a CI gate suppresses on. Two rules sharing an id therefore emitted two findings for the same line under the same id (SARIF then described both with whichever rule's metadata was seen first), and nothing said the rule set was inconsistent. This is also what deduplicates a repeated --passive-scan-path, which used to double every finding.

Source

Nested types