Repository navigation
auth: 400 for a segment of dots and whitespace alone; keep an unknown name's ladder to its table - #70
Merged
Merged
Conversation
shreeve
force-pushed
the
auth/strict-dot-runs
branch
from
October 11, 2026 12:32
b72a3db to
3901ec9
Compare
…g whitespace, and keep an unknown name's ladder to its table A segment such as ..%20, ..., or %20.. reads three ways on a backend: kept, dropped, or climbed as .., and a path mixing readings (/app/x/.../..%20/..%20/admin/s) escaped every fixed set of gate forms, including the dot-run reading of #66. The wall now answers 400 for such a segment in the decoded path or its one further decoding, before any gate, so that reading never sees a request and is removed. The fold trims trailing Unicode whitespace, not only spaces, and a gate prefix holding any Unicode whitespace is refused. A name no users table holds shared one account-ladder row across every table, so burning it on one site answered 429 on another where a held name answered 401. It now keys on the table's realm.
shreeve
force-pushed
the
auth/strict-dot-runs
branch
from
October 11, 2026 13:04
3901ec9 to
fb407a4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows #66 (merged) and adds the follow-up #65 needs. Both came out of an adversarial review of the two PRs.
A segment of dots and whitespace alone is 400
#66 read a run of dots and spaces that folds away (
..%20,...,%20..) two ways: dropped, or as... A path that mixes readings matches neither. Behind a backend that trims spaces but keeps...as a name,/app/x/.../..%20/..%20/admin/sresolves to/app/admin/s. With gates/app/admin/ {alice}and/ {alice, bob}, bob passed. With only the/app/admin/gate, the request passed with no session at all. #66's own test missed this because its gate sits at the root.No fixed set of forms covers every mix, so the wall refuses instead (rule 1). On a gated site, any request whose decoded path, or its one further decoding, has a segment (
\read as/,;parametercut) made of dots and Unicode whitespace alone, other than.and.., gets a 400 before any gate is matched. That also closes..%09,..%0b, and..%c2%a0, which astrip/TrimSpacebackend reads as... Names that merely contain dots or spaces still pass (report..pdf,v1.2.,a b,.hidden).With the 400 in place, #66's dot-run reading (
authFoldPath'sdotRuns) never sees a request, so this PR removes it.The fold trims any trailing whitespace
Segments shed trailing Unicode whitespace as well as dots and spaces. A gate prefix holding any Unicode whitespace is refused; before, only space, tab, CR, and LF were.
An unknown name's account ladder stays with its table (#65 follow-up)
#65 keyed the account ladder on the credential. Every name a table doesn't hold has the empty credential, so those names shared one row across every table in the process. Burning
daveon site B made site A answer 429 fordave, where a held name answered 401. That let an attacker tell which names a table holds. A name the table doesn't hold now keys on that table's realm (authSite.accountScope).Tests
TestAuthWallRefusesAmbiguousSegments: the reproductions above, with and without a session, under a nested gate and a lone gate, plus names that must still pass. All 30 refusal checks fail with the 400 disabled.TestAuthGateFoldsTrailingDotsAndSpaces: adds%09,%c2%a0,.%0b, and a prefix holding NBSP.TestAuthAccountLadderFollowsTheCredential: burnsdaveon site A, then signs in asdaveon site B through the real door and expects 401. It fails on the old key.a segment of dots and whitespace alone is 400(nothing reaches the app).make test: unit suites pass, and acceptance passes 175/175 in the foreground.Not in scope (flagged by the review, left for a decision)
Full-width dots and slashes, overlong
%c0%ae,..%00, triple encoding, and.%20.are outside the declared forms. Rejecting control characters and invalid UTF-8 on gated sites would close most of them.