PST-070: API throttling gaps: invalid tokens are not throttled, scope is checked before the allowance is charged, and tokens multiply the allowance #799
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#799
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the security audit of 2026-10-10 (
SECURITY-AUDIT-2026-10-10.md), run againstmainatc30851bfrom 8 to 10 October 2026, as PST-070. Severity: Informational.The text below is the audit's entry, unchanged apart from links to the other issues it names. The finding was produced by automated review and checked by a second automated pass; re-check it before acting on it.
src/postulo/api/auth.py(45-56; 102-133; 22-38)Who can do it, and what they need. A stranger on the internet. No precondition.
How it works.
throttle.api()is only applied after a token is found, so it bounds valid tokens, not guessing./logsand/metricscall throttle.barred/refused and lock an address out after ten wrong tokens an hour (#472).Impact. No credential risk given the token entropy; an inconsistency in the project's own hardening pattern rather than a vulnerability.
Verification (verdict: confirmed; severity after verification: Informational). Keep as informational. Line references: lookup is auth.py:42-52 (not 45-56); the per-address wrong-token pattern is throttle.py:186-207. Note token_hash is unique (indexed), so each wrong guess is one indexed SELECT. No exploitable effect beyond cheap 401s, which are out of scope per THREAT-MODEL.md line 136.
Suggested remediation. If wanted, apply throttle.barred/refused per REMOTE_ADDR around
lookup()failures in TokenAuth/ScopedAuth/_no_such_address/for_readers_of_the_api, as /logs does; otherwise record in the threat model that the API relies on token entropy and the reverse proxy for this.Also covered by this issue.
src/postulo/api/auth.py(102-133); Informational). Unbounded cheap probing (one indexed query each) and the ability to enumerate which scopes a token lacks without consuming allowance; no data exposure.src/postulo/api/auth.py(22-38); Informational). The per-account bounds that matter (capture fetches 30/h, phone-number collision answers 20/h) are keyed on the account and hold. …Fixed in
0020410a4on main.