Repository navigation
fix(auth): harden login/session handling (#334) - #355
Merged
Merged
Conversation
- trust X-Forwarded-For only when TRAPFALL_TRUST_PROXY is set - per-(email,IP) lockout so remote attackers cannot lock out the admin - run Argon2 on the blocking pool; equalise timing for unknown users - atomic first-admin setup - store hashed session tokens, purge legacy plaintext sessions - change_password revokes other sessions Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- add global per-email ceiling (30 fails/15min across all IPs) - raise per-IP cap to 100 and warn once when proxy headers arrive from a private/loopback peer while TRAPFALL_TRUST_PROXY is unset Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…/334-auth-hardening
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.
Refs #334 (partial: login/session items; remaining items listed below, so not auto-closing)
What
X-Forwarded-For/X-Real-IPare used only whenTRAPFALL_TRUST_PROXY=true(rightmost XFF entry).TRAPFALL_TRUST_PROXYis unset.Trade-off: an attacker with 30+ distinct IPs can still lock an account for the rest of the window; a single IP cannot.
spawn_blocking; unknown-email logins burn one dummy verify to equalise timing.INSERT ... WHERE NOT EXISTS; Postgres adds an advisory xact lock).h1:<blake3>; legacy plaintext rows are purged at startup.change_passwordrevokes all other sessions (keeps the caller's).count_failed_attempts_email_ip,create_first_user,delete_user_sessions_except,purge_sessions_without_prefix(SQLite + Postgres).Why
Security audit findings in #334 (spoofable IP limit, lockout DoS, Argon2 stalling the single-threaded runtime, setup race, plaintext session tokens, sessions surviving password change).
Breaking / upgrade notes
TRAPFALL_TRUST_PROXY=trueor all clients share the proxy IP for rate limiting.Confighas a newtrust_proxyfield.Deferred (not in this PR): ingest rate limiter keyed by attacker-chosen project_id / unbounded map; DSN host from
Hostheader whenpublic_urlunset; setup token printed at startup; docker-composeSecurecookie default (config default is alreadytrue).Testing
cargo fmt --check: OKcargo clippy --workspace --all-targets -- -D warnings: cleancargo test --workspace: all suites pass (0 failures)🤖 Generated with Claude Code