Which of these findings do I fix first?
◉ᴥ◉ 412 files / quick / node (detected) / 1.4s
23 findings (10 high, 11 medium, 2 low)
3 internet-reachable, 8 behind auth, 9 internal, 3 unclassified
Three findings is an afternoon. Twenty-three is a backlog. Same scan.
Severity does not answer the question
Severity is a property of the rule. insecure-cookie is
medium on the public login route and medium on the internal admin tool behind
a VPN. Confidence is a property of the evidence. Neither says whether
an attacker can reach the code, which is what every experienced reviewer
triages on before anything else.
| Value | Meaning |
|---|---|
internet | on a request-handling path, and no authentication gate was identified on it |
authenticated | on a request-handling path with a positively identified gate |
internal | not on a request path - a build script, a worker, a CLI, a migration |
unknown | the framework profile could not place it |
Absence of evidence yields internet
This is the one thing about the design that is not negotiable, and it runs against the grain of everything else in the tool.
Everywhere else, uncertainty resolves downward: a rule that cannot prove a
value came from the request reports possible rather than guessing,
because the cost of a false likely is a wasted hour.
Exposure inverts that cost. A finding wrongly marked authenticated
is a finding somebody deprioritises - and the tool would have reassured them
about something it never checked. So:
- A middleware module that does not resolve to a file in your tree
is not a gate.
import { requireAuth } from './middleware/auth'gates nothing if that file was deleted. - A name that does not read as an authentication check
is not a gate.
app.use(logger)mounts something; it does not gate anything. - A session call whose result is never checked
is not a gate.
const session = await getServerSession()with nothing done about the answer gates nothing. - A
config.matcherwe could not parse covers nothing, rather than everything.
The fixtures assert the direction, not only the value: for every
framework, deleting the gate and re-running must never produce
authenticated.
What it does not claim
It does not judge whether the gate is correct. A broken auth
check classifies as authenticated. Verifying authentication logic
is a different tool.
It is not reachability analysis. There is no call graph. A
finding in a library called only from a guarded handler classifies as
unknown, not authenticated.
unknown is not a quiet internal.
internal is a claim that nothing reaches the file;
unknown means the question was not answered. They are counted
separately, and coverage reports the unclassified rate.
Gating on it
npx owlwarden scan --fail-on-exposure internet
# Composes with --fail-on as an OR, because they are different policies:
# "nothing worse than medium" and "nothing an anonymous caller can reach".
npx owlwarden scan --fail-on medium --fail-on-exposure internet
Exposure never raises severity. A medium on an internet-reachable route is still a medium - it sorts first and can trip its own gate, and that is all. Severity has to keep meaning how bad is this class of bug, or SARIF output stops being comparable between versions.
Keep reading
- owlwarden turnWhich of these did I just do?
- RulesTrigger, confidence, and framework-specific fix.
- Agent configHooks, MCP servers, instructions, and editor tasks.
- owlwarden vetCheck a repository before you open it.
- owlwarden sealNotice when your agent's execution surface moves.
- ExposureWhich of these findings do I fix first?
- RuntimesDoes this fix run on Bun, Deno, or Workers?
- CoverageMapped rules and categories static analysis cannot cover.