Exploitable
2Reproduced, with real impact.
- Invoice detail returns any tenant’s invoice app.py:134
- Admin user list has no role check app.py:146
alice received bob’s canary data across an auth boundary
SARIF error, fails CI
For teams buried in AI security findings
Alethix replays each finding from your AI reviewer or scanner against a disposable copy of your app. Only the bugs it can prove reach your queue.
$ alethix verify --repo ./ledger --findings review.sarif --fix
alethix — verifying 8 finding(s) against ledger in a local Docker sandbox
· booting a disposable copy of ledger …
· ready — replaying each finding as an independent, read-only check
· 0-0-broken-object-level-authz: exploitable
· 0-1-missing-function-level-authz: exploitable
· 0-2-broken-object-level-authz: reachable
· 0-3-missing-authorization: not-an-issue
· 0-4-missing-security-headers: hardening
alethix — 8 finding(s) checked
2 exploitable 1 reachable, not proven 4 hardening only 1 not an issue
EXPLOITABLE (2)
- Invoice detail endpoint returns an invoice to any authenticated user … [app.py:134]
alice received bob's canary data across an auth boundary
- Admin users listing endpoint has no role check … [app.py:146]
alice received bob's canary data across an auth boundary
✓ fix verified Invoice detail endpoint returns an invoice … [app.py]
re-ran the same check: request as alice was denied (403); access control held
✓ fix verified Admin users listing endpoint has no role check … [app.py]
re-ran the same check: request as alice was denied (403); access control held
Real CLI output, trimmed to fit. Ledger is our demo invoicing API with two planted access-control bugs. The eight findings came from a claude-code-security-review export.
Working with teams at
AI reviewers and scanners flag issues faster than any team can check them. Much of the queue is hardening advice, unreachable code, or a guess labeled critical.
So a senior engineer reads every one by hand, or the queue gets ignored. Both are expensive.
“the mind-numbing AI slop”
' OR 1=1 --GET /invoices/2002POST /login ×500http://169.254.169.254<script>500 Traceback../../etc/passwd"alg": "none"GET /admin/users__proto__nosniff?next=//evil.exampleIf the canary reaches the wrong user, the bug is real. If it doesn’t, you get the evidence for that too.
// review.sarif, result 1 of 8 { "ruleId": "broken-object-level-authz", "level": "error", "message": { "text": "Invoice detail endpoint returns an invoice to any authenticated user …" }, "locations": [{ … "uri": "app.py", "startLine": 134 }] }
8 findings, one shape
$ docker compose up (a throwaway project name)
· booting a disposable copy of ledger …
· GET /healthz 200 ready
ledger, disposable copy
tenant acme
a alice tok-alice
invoice 1001 acme website redesign
tenant globex
b bob tok-bob
invoice 2002 globex retainer LEDGER-canary-9b1f4c2a7d
Only bob should ever see the canary. If a request made as alice returns it, a tenant boundary was crossed.
→ GET /api/invoices/2002 Authorization: Bearer tok-alice ← 200 {"id": "2002", "tenant": "globex", "amount": 9900.0, "memo": "globex retainer LEDGER-canary-9b1f4c2a7d"}
GET /api/invoices/2002/pdf as alice was denied (403); access control held
@@ app.py GET /api/invoices/<id> @@ inv = data["invoices"].get(inv_id) if not inv: return self._send(404, {"error": "no such invoice"}) - # BUG: returns the invoice to any authenticated caller + # Authorization: invoice must belong to the caller's tenant. + if inv["tenant"] != who["tenant"]: + return self._send(403, {"error": "forbidden"}) return self._send(200, inv)
Each bucket carries the evidence that put the finding there. A check that can’t run is reported as errored, never as all clear.
Reproduced, with real impact.
alice received bob’s canary data across an auth boundary
SARIF error, fails CI
Not proven. The input reaches the code, no impact shown.
no bob data seen in alice’s response (status 200)
SARIF warning
Defense in depth. Not a live bug.
no code path returns a stack trace, so there is nothing to reproduce
SARIF note
The check ran and the app held.
request as alice was denied (403); access control held
SARIF none, safe to close
No dashboard to log into. Point it at a repo and the findings file you already have.
$ alethix verify --repo . --findings review.sarif --exit-code
alethix — 8 finding(s) checked
2 exploitable 1 reachable, not proven 4 hardening only 1 not an issue
EXPLOITABLE (2)
- Invoice detail endpoint returns an invoice … [app.py:134]
- Admin users listing endpoint has no role check … [app.py:146]
$ echo $?
1 # the build fails on proof, not on noise
$ alethix study
alethix study — real run against the bundled vulnerable fixture
finding expected verdict ok
idor-docs exploitable exploitable ✓
docs-download-authz not-an-issue not-an-issue ✓
profile-fields reachable reachable ✓
missing-xfo hardening hardening ✓
exact matches: 4/4 (accuracy 1.0)
real bugs MISSED: 0 (must be 0)
false 'exploitable': 0 (must be 0)
$ alethix ingest examples/report.md
1 finding(s) normalized:
- report-0: IDOR in document download endpoint
# a plain-text bug report becomes the same Finding a SARIF result does
$ alethix verify --repo . --findings review.sarif --sarif-out verdicts.sarif
// verdicts.sarif (SARIF 2.1.0), result 1
{
"ruleId": "exploitable",
"level": "error",
"kind": "fail",
"properties": {
"bucket": "exploitable",
"confidence": 0.9,
"observedEffect": "alice received bob's canary data …"
}
}
--exit-code returns 1 only when something is exploitable.SARIFSARIFSARIFplain textAlethix
Scanners, AI reviewers and AI pentesters all write findings. Alethix is the independent check that runs them, whichever tool they came from.
A model proposes each check and each patch. It never decides the verdict: a deterministic oracle looks for observable impact, and a person confirms.