Public: anyone can read this; nobody can change it.

Every password door counts in the sign-in windows: the API session and token doors, HTTP Basic and the terminal sign-in go through one throttled verify #42

Merged opened this view on origin

Check · Review · Land done · Live — Landed; nothing deploys from this branch, so this is the end of its path.

Merged

**Problem.** Four password doors had no sign-in limit: `POST /api/v1/sessions`, the password branch of `POST /api/v1/tokens`, HTTP Basic on any request (it gives scope `admin`), and the terminal sign-in. A client could guess passwords with no limit. Each guess also used one argon2 verify.

shipped merged

opened this view on origin

Problem. Four password doors had no sign-in limit: POST /api/v1/sessions, the password branch of POST /api/v1/tokens, HTTP Basic on any request (it gives scope admin), and the terminal sign-in. A client could guess passwords with no limit. Each guess also used one argon2 verify.

Root cause. The sign-in windows (#2439, #2366, #2470) were in the /signin page handler. verifyPassword was exported, so each door had to remember to ask the windows first. Four doors did not.

Fix.

  • The windows move to src/core/signin-window.ts (per account, per source, per forge, same limits and keys). signinAllowed for the passkey, claim and parent doors calls it.
  • verifyPasswordThrottled(db, { username, password, source }) is the only exported password check. It counts the attempt before argon2. The raw check is not exported, so a new door cannot skip the windows.
  • All password doors call it: /signin, the API session and token doors (429 with retry-after), HTTP Basic (401 when throttled, also for the right password), the terminal (throttled) and the password change.
  • A right password gives its attempt back. A git client that sends the right password on each request does not fill a window. Each wrong guess stays counted.

Test. test/signin-password-doors.test.ts: with signin.per_account = 3, three wrong tries, then the right password is refused at each door. Tries at /signin close the API door. 9 right Basic passwords in a row all pass. No module but core/users.ts calls Bun.password.verify. On main: 6 of 7 fail. With the fix: 8 of 8 pass. test/throttle-scope.test.ts now expects the API password sign-in to be refused by the full sign-in window.

Validate (fast). Result: baseline. Only contain.test.ts, release-handover.test.ts and web-code.test.ts failed, and they also fail on main 1051d451 on this box. tsc passes.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs