Skip to content

fix(gate-7): the auth token may be the FIRST segment too (.github#360) - #368

Merged
rubenvdlinde merged 1 commit into
mainfrom
fix/gate-7-auth-token-may-lead
Aug 11, 2026
Merged

fix(gate-7): the auth token may be the FIRST segment too (.github#360)#368
rubenvdlinde merged 1 commit into
mainfrom
fix/gate-7-auth-token-may-lead

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Closes #360.

#353 relaxed where the auth token may sit in a guard-helper name, but left
the segment before it mandatory[A-Z][A-Za-z0-9_]* with no ? — so the
token could never be the first segment after the is|has|can|may prefix. The
most conventional per-object guard names in the fleet are exactly that shape, and
gate-7 reported every method delegating to one as an unguarded IDOR, before
AND after #353.

-    r"^(?:is|has|can|may)[A-Z][A-Za-z0-9_]*"
+    r"^(?:is|has|can|may)(?:[A-Z][a-z0-9_]*)*?"
     r"(?:Admin|Access|Permission|Permitted|Owner|Allowed|Authori[sz]ed)"
     r"(?:[A-Z][A-Za-z0-9_]*)?$"
name old new
hasPermission canAccess isOwner isAllowed mayAccess hasAccess
canUserAccessAgent hasOwnerPermissionForRun isAdmin canEditPermission canViewOwner hasACLAccess assertOwner
canRender hasChanges canUserModifyAgent hasPendingRevision isVisible canDelete hasItems

The token set is unchanged and a token is still REQUIRED. The newly admitted
names are exactly {is,has,can,may} + token + optional object noun. Widening this
to "any is/has/can/may method" would let gate-7 clear real IDORs
strictly worse than the false positives it removes — so canRender/hasChanges
must stay non-guards, and there is now a unit test saying so by name
(test_360_did_not_widen_into_silence).

Blast radius: NONE, and it is measured rather than argued

The new pattern is a strict superset of the old. 400,000 fuzzed identifiers
over the prefix/token grammar produced zero names the old regex matched and
the new one does not. This change can therefore only turn gate-7 findings green;
it cannot redden any repo, which is why it is sequenced first.

Observed red, then green — not asserted

control before after
test_gate7_verb_object_guards.sh short-guard arm 2 findings, carried as a live KNOWN DEFECT 0 findings
the same arm under the reconstructed pre-#360 regex 2 findings — so the fixture genuinely discriminates fixed from broken, and is not a dead test
test_check_no_admin_idor.py 93 pass 95 pass; the new test_the_auth_token_may_be_the_first_segment fails on the old regex with AssertionError: hasPermission should be a guard name

The #353 anti-dead-test arm demanded its own update the moment the regex was
reshaped — "Re-derive the revert and update it here rather than deleting this
arm"
— which is what a suite that refuses to rot looks like. Done, and it still
proves clean/ goes red (3) under the pre-#353 regex.

One correction carried into the code

The #353 commit message says canAccess matched. Measured against both
regexes, it never did. #353 remains a clean widening — nothing it used to match
was lost — but its message overstated the scope, and the comment above the regex
is now where that stops being repeated. Same for canUserModifyAgent, which
SHARED-LESSONS listed as fixed by #353 and which correctly still does not match:
"Modify" is not an auth token.

ShellCheck clean (koalaman/shellcheck:stable against the repo's own .shellcheckrc).

#353 relaxed WHERE the auth token may sit in a guard-helper name, but left the
segment before it mandatory -- `[A-Z][A-Za-z0-9_]*` with no `?` -- so the token
could never be the first segment after the is/has/can/may prefix. The most
conventional per-object guard names in the fleet are exactly that shape, and
gate-7 reported every method delegating to one as an unguarded IDOR, before AND
after #353.

Making that segment repeatable and optional admits the token in any position:

    hasPermission canAccess isOwner isAllowed mayAccess hasAccess   x -> ok
    canUserAccessAgent hasOwnerPermissionForRun isAdmin
    canEditPermission canViewOwner hasACLAccess assertOwner         ok -> ok
    canRender hasChanges canUserModifyAgent hasPendingRevision
    isVisible canDelete hasItems                                    x -> x

THE TOKEN SET IS UNCHANGED and a token is still REQUIRED. The newly admitted
names are exactly {is,has,can,may} + token + optional object noun. Widening this
to "any is/has/can/may method" would let gate-7 clear real IDORs -- strictly
worse than the false positives it removes -- so `canRender`/`hasChanges` must
stay non-guards, and there is now a unit test that says so by name.

BLAST RADIUS: NONE, and this is measured, not argued. The new pattern is a
STRICT SUPERSET of the old: 400,000 fuzzed identifiers over the prefix/token
grammar produced ZERO names the old regex matched and the new one does not. So
this change can only turn gate-7 findings green; it cannot redden any repo.

EVIDENCE, observed red-then-green rather than asserted:

  test_gate7_verb_object_guards.sh   before: the hasPermission()/canAccess()
                                     controller produced 2 findings, carried as
                                     a live KNOWN DEFECT
                                     after:  0 findings, and the same fixture
                                     still goes RED (2) under the pre-#360 regex
  test_check_no_admin_idor.py        95 tests pass; the new
                                     test_the_auth_token_may_be_the_first_segment
                                     FAILS on the old regex
                                     ("hasPermission should be a guard name")

The #353 anti-dead-test arm demanded its own update when the regex was reshaped
-- "Re-derive the revert and update it here rather than deleting this arm" --
which is what a suite that refuses to rot looks like. Done, and it still proves
clean/ goes red (3) under the pre-#353 regex.

Corrected for the record, in the code comment where it will be read: the #353
commit message says `canAccess` matched. Measured against BOTH regexes, it never
did. #353 remains a clean widening; its message overstated the scope.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gate-7: hasPermission() and canAccess() still reported as unguarded IDOR after #353

1 participant