Skip to main content

Confidence model

Every finding carries a confidence level and a one-line confidence_reason that says why it fired and what would make it a false positive.

vulkro scan . # default: Medium and above
vulkro scan . --min-confidence high # strictest report
vulkro scan . --all-confidence # everything, including Low

Levels​

LevelMeaningTypical examples
VerifiedThe finding is on an unprotected route whose handler reads user input.Missing auth on a handler that reads the request body.
HighStrong evidence.Provider-format secrets, traced injection paths, KEV-listed CVEs.
MediumThe pattern matches, with a known false-positive shape.Unscoped :id lookup with no visible auth check; generic secret pattern.
LowHeuristic only. Hidden by default.Pattern match with little context; test, fixture or migration code.

Confidence is separate from the finding's disposition (Proven, Unproven, Not checked) and from its exploitability grade.

Strict-confidence filter​

--strict-confidence (or VULKRO_STRICT_CONFIDENCE=1) also drops any High finding with an empty evidence list. A High finding survives only with at least one corroborating signal: a traced data flow, an exact-match rule, or several pattern signals that add up. Off by default.

Per-detector-category tiers​

What each level means depends on the detector. Every rule page links here.

CategoryHighMediumLow
SecretsProvider-format match (AKIA, sk_live_, ghp_) outside test code.High-entropy value assigned to a *_KEY, *_TOKEN or *_PASSWORD name.Long hex or base64 string with no naming signal.
AuthReachable route with no visible auth middleware, decorator or guard.Looks unprotected in the file, but a global mount or framework convention may apply auth.Route name suggests admin or internal, nothing else.
IDOR / BOLA:id param flows into an unscoped object lookup.Unscoped lookup, flow not confirmed.:id route with no visible check.
Mass assignmentRequest body bound to a model with fields the API does not allowlist.Model schema not fully resolved.Pattern match only.
InjectionTraced flow from request to SQL, shell, template or eval sink with no sanitiser.Sink with a likely tainted argument.Sink call, pattern only.
CryptoProvably wrong use: md5 for passwords, ECB mode, verify=False on TLS.Weak primitive, possibly non-security use.Mention in a comment or test name.
SCA / CVEDirect dependency on a KEV-listed advisory at the exact version.Transitive dependency, or a range match.Typosquat or new-package signal with no CVE.
SSRFTainted URL reaches an HTTP client with no allowlist or host check.Chain crosses an unresolved function.URL-shaped argument to an HTTP client.
LLMUser input or a secret flows into a model SDK call without isolation.Input near an LLM call, no full chain.Template string passed to an LLM call.
CSRF / cookiesSession middleware without CSRF protection; SameSite=None without Secure.CSRF middleware unclear; cookie missing one flag.Session-like cookie name only.

confidence_reason​

taint flowed from req.body to db.query without sanitiser
auth helper not found in import scope
AKIA-prefix matches AWS access-key format

It appears in JSON, SARIF (properties.confidence_reason) and the local console.

Calibration table​

Detector categories with a measured true-positive rate under 30% are lowered from High to Medium by default, and the reason says so. The table is updated when benchmark results change.

Where the bar is​

Precision and recall at each confidence cut are published, with the corpus and scoring method, on Benchmark.

Offline false-positive triage (--triage)​

--triage lowers confidence by one level for findings in test, fixture, example, generated, vendored and migration paths. It is path-based, deterministic, uses no model and makes no network call. It never drops a finding.

vulkro scan . --triage --min-confidence high

See also: vulkro scan, Glossary