Two bugs, together making 4.1 report "no bug" on a textbook IDOR. Both found by
running it against a real corpus pair rather than a fixture.
1. constraint_params were treated as dischargers. A field named `user_id` is
what an IDOR is MADE OF -- `filter_by(id=user_id)` with user_id off the
request is the bug, not the fix. The deleted checker only counted an identity
constraint whose value's PROVENANCE was the authenticated context, so the
parameter name alone evidences nothing. This is the mirror of group 2's
sanitizer bug: a thing that must never count as a discharge, counted.
2. Guard tokens matched as substrings. With `user` in the token list, the string
"SELECT * FROM users WHERE id = ?" contains `user`, so the query reported
every operation in the handler as guarded. Matching is word-boundary now.
On threatbyte-api-v1-delete the arbiter previously found three operations, all
"guarded" by evidence like '"SELECT * FROM users WHERE id = ?"' and '(user_id,)',
and returned no verdict at all. After the fix, on the real pairs:
threatbyte-api-v1-delete vuln=model_corroborated fixed=none
vampi-users-update-password vuln=model_corroborated fixed=none
Both distinguished, deterministically, with no model call. Corroborated rather
than entailed is right for these: they are single-handler excerpts with no
guarded sibling to be inconsistent with, which is the asymmetry the rung
distinction exists to express.
identity_sources still discharge; request_sources and permissive_values remain
excluded because they describe the vulnerable shape rather than the fix.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG