P1 security: no rate limiting or lockout on the signing-key login form #66
Reference in New Issue
Block a user
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?
Verified against
mainat61f42e6. Covers the "per-IP rate limiting" P2 item inTODO.md, scoped to the place it matters most first.handleLoginPost(internal/handlers/auth.go:37-67) compares the submitted key againstconfig.SigningKeyin constant time, logs a warning on mismatch, and re-renders the form. There is no rate limit, no lockout, no backoff, and no per-IP accounting anywhere in the codebase.The credential being guessed is not a scoped password — it is the signing key, the master secret. It also derives the encrypted-URL key and the session key (
internal/encurl,internal/seal,internal/session). Compromise means the attacker can mint arbitrary signed and encrypted URLs, i.e. use pixa as an open proxy against any host, permanently.Config validation enforces a 32-character minimum (
internal/config/config.go), so brute force is not the realistic threat against a well-chosen key. The realistic threats are a weak-but-long operator-chosen key, and the fact that an unthrottled endpoint gives an attacker unlimited free attempts with zero cost or visibility beyond log lines nobody is alerting on.Definition of done
POST /with a sane default (a few attempts per minute), returning 429 withRetry-Afteronce tripped.TODO.mdrate-limiting items (per-IP on image routes, per-origin) can reuse it. Prefer a well-maintained library over hand-rolling; check~/.claude/GO_PACKAGE_DEFAULTS.mdfirst and record the decision there.RemoteAddrlimiter would key every request to the proxy's IP and lock out all users at once. Trusted-proxy handling must be configurable, and must not trustX-Forwarded-Forblindly from untrusted sources.hostSemsmap issue).make checkgreen.Follow-on (not in this issue)
Once the limiter exists, per-IP limiting on the image routes and per-origin limiting are separate commit-sized units.