feat: User-Agent gate for known-client strict mode#157
Merged
Conversation
…entifies known WXYC client Closes #155. Adds a structural pre-check that rejects 403 when the caller's User-Agent matches a registered WXYC client at-or-above its strict-mode version (currently WXYC-iOS >= 3.2) and X-Device-Fingerprint is absent. Independent of ENFORCE_REQUEST_BANS; default-off via STRICT_FINGERPRINT_FOR_KNOWN_CLIENTS so the code can deploy before iOS 3.2 reaches App Store rollout. Unknown UAs (curl, browsers, v3.1 iOS) keep the existing lenient contract. Closes the only ban-evasion vector the BS ban check (#150) can't reach: a banned listener stripping both Authorization and X-Device-Fingerprint headers. iOS 3.2 will unconditionally send fingerprint + WXYC-iOS UA (WXYC/wxyc-ios-64#351), so after rollout completes, missing fingerprint from a self-identified 3.2+ client is by-construction evasion. Telemetry uses ban_source='rom_strict_mode' + ban_reason='ua_gate_missing_fingerprint' so PostHog dashboards distinguish UA-gate rejections from real fingerprint/user bans (#150's ban_source='bs').
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.
Closes #155.
Summary
POST /request: whenSTRICT_FINGERPRINT_FOR_KNOWN_CLIENTS=trueand the request'sUser-Agentmatches a registered WXYC client at-or-above its strict-mode version (currentlyWXYC-iOS >= 3.2), missingX-Device-Fingerprinttriggers a 403 before parse and before the BS ban round-trip.ENFORCE_REQUEST_BANS— this is a structural requirement on known clients, not a ban decision.services/ua_gate.py) keep the existing lenient contract. The registry is a one-line addition when WXYC-Android ships its own ban-aware version.ban_source='rom_strict_mode'+ban_reason='ua_gate_missing_fingerprint'so PostHog dashboards distinguish UA-gate rejections from real BS-driven bans (ban_source='bs'from Enforce request-line ban on POST /request via BS /auth/check-request-ban #150).Why this exists
The BS ban check (#150) plugs every ban-evasion vector except "strip both
AuthorizationandX-Device-Fingerprintheaders." ROM'sproceed-as-unauthon missing headers is required for v3.1 iOS in the App Store (which sends no headers), so we can't reject blank-header requests globally. The UA gate closes the gap for clients that should have headers — iOS 3.2+ unconditionally sends fingerprint, so a self-identified 3.2 UA without a fingerprint is by-construction evasion.UA spoofing is in scope but not a blocker: a determined attacker who spoofs
User-Agent: WXYC-iOS/3.2.0then has to also send a fingerprint, at which point they're back on the BS fingerprint-banned path.Test plan
tests/unit/test_ua_gate.py:BanCheckResult(banned=False))request_blockedemittedruff check,ruff format --check,mypyall green.