fix(auth): harden middleware and auto-ban against IP spoofing and map growth #130

Merged
David merged 1 commit from fix/bunyip-72 into main 2026-06-12 12:39:06 +02:00
Owner

Trust X-Forwarded-For / X-Real-IP only from a configured trusted-proxy CIDR. extract_client_ip now keys off the real socket peer address and honours forwarding headers solely when that peer falls inside Config::trusted_proxies (new TRUSTED_PROXY_CIDR env, comma-separated CIDRs, empty by default). This closes the spoofing vector that let any client evade the auto-ban or ban a victim by forging its IP. With no Config in app data (unit tests) the socket address is always used.

Route at+jwt case-insensitively: token_is_atjwt now compares typ with eq_ignore_ascii_case, so a mixed-case At+JWT reaches the EdDSA verifier instead of silently falling back to HS256.

Bound the auto-ban map: is_banned evicts expired entries on read (read-lock fast path, write-lock eviction only when an entry is expired, re-checked under the write lock) rather than waiting for the 5-minute sweep.

Clear dead middleware structures: remove the write-only AuthenticatedClaims request-extensions insert (never extracted) and the unused HttpMessage import, drop the write-only StrikeEntry.last_path field, and narrow SuspiciousPatterns to pub(crate) (no external callers).

Make the auto-ban test real: test_record_strike_triggers_ban now drives record_strike to the threshold over a lazy (never-connecting) pool and asserts ban promotion plus is_banned, replacing the placeholder. Adds a case-insensitive token_is_atjwt test.

#BUNYIP-72

Branch-backed replacement for #124 (original was AGit/branchless, no merge button once behind main). Rebased clean onto current main.

Trust X-Forwarded-For / X-Real-IP only from a configured trusted-proxy CIDR. extract_client_ip now keys off the real socket peer address and honours forwarding headers solely when that peer falls inside Config::trusted_proxies (new TRUSTED_PROXY_CIDR env, comma-separated CIDRs, empty by default). This closes the spoofing vector that let any client evade the auto-ban or ban a victim by forging its IP. With no Config in app data (unit tests) the socket address is always used. Route at+jwt case-insensitively: token_is_atjwt now compares typ with eq_ignore_ascii_case, so a mixed-case At+JWT reaches the EdDSA verifier instead of silently falling back to HS256. Bound the auto-ban map: is_banned evicts expired entries on read (read-lock fast path, write-lock eviction only when an entry is expired, re-checked under the write lock) rather than waiting for the 5-minute sweep. Clear dead middleware structures: remove the write-only AuthenticatedClaims request-extensions insert (never extracted) and the unused HttpMessage import, drop the write-only StrikeEntry.last_path field, and narrow SuspiciousPatterns to pub(crate) (no external callers). Make the auto-ban test real: test_record_strike_triggers_ban now drives record_strike to the threshold over a lazy (never-connecting) pool and asserts ban promotion plus is_banned, replacing the placeholder. Adds a case-insensitive token_is_atjwt test. #BUNYIP-72 Branch-backed replacement for #124 (original was AGit/branchless, no merge button once behind main). Rebased clean onto current main.
fix(auth): harden middleware and auto-ban against IP spoofing and map growth
All checks were successful
Check / fmt / clippy / build / test (pull_request) Successful in 1m9s
Create release / Create release from merged PR (pull_request) Has been skipped
54b01afde3
Trust X-Forwarded-For / X-Real-IP only from a configured trusted-proxy CIDR. extract_client_ip now keys off the real socket peer address and honours forwarding headers solely when that peer falls inside Config::trusted_proxies (new TRUSTED_PROXY_CIDR env, comma-separated CIDRs, empty by default). This closes the spoofing vector that let any client evade the auto-ban or ban a victim by forging its IP. With no Config in app data (unit tests) the socket address is always used.

Route at+jwt case-insensitively: token_is_atjwt now compares typ with eq_ignore_ascii_case, so a mixed-case At+JWT reaches the EdDSA verifier instead of silently falling back to HS256.

Bound the auto-ban map: is_banned evicts expired entries on read (read-lock fast path, write-lock eviction only when an entry is expired, re-checked under the write lock) rather than waiting for the 5-minute sweep.

Clear dead middleware structures: remove the write-only AuthenticatedClaims request-extensions insert (never extracted) and the unused HttpMessage import, drop the write-only StrikeEntry.last_path field, and narrow SuspiciousPatterns to pub(crate) (no external callers).

Make the auto-ban test real: test_record_strike_triggers_ban now drives record_strike to the threshold over a lazy (never-connecting) pool and asserts ban promotion plus is_banned, replacing the placeholder. Adds a case-insensitive token_is_atjwt test.

#BUNYIP-72
David merged commit e37a93e80c into main 2026-06-12 12:39:06 +02:00
David deleted branch fix/bunyip-72 2026-06-12 12:39:06 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
psa-systems/bunyip!130
No description provided.