HTTP Accept-Language contradicts the JS navigator.languages locale
net.accept_lang_vs_navigator · convicts
What it catches
Cross-layer locale coherence: a real browser's HTTP Accept-Language always matches its JS navigator.languages[0] (same browser config drives both). A bot that geo-spoofs the JS locale (to a proxy's country) but forgets the HTTP stack disagrees across layers. v0.74.14 FIRST LIVE POSITIVE: the accept-lang-spoof evader (stealth ACCEPT_LANG_SPOOF=1 — context locale en-US so the real Accept-Language=en is sent, while navigator.language/languages are JS-patched to fr) fires it (accept_language_primary=en vs nav_language_primary=fr) — previously 'evaded' (read signals present in the corpus but no evader created the mismatch). GROUNDED FP-safe across the real-browser second source: the headful Chromium/Firefox/WebKit captures all have accept_lang==nav_lang (match → no fire). Browserforge calibration carries no HTTP Accept-Language, so it cannot raise the legit flag rate.
Signals it reads
network.accept_language_primary browser.nav_language_primary
How it fires
not_equal
Evaders it caught 1
Bypassed by 10
Frontier evaders that reach the detector uncaught (scored only suspicious, defeating every convicting tell) — this check is not one that stops them. The red-team frontier this detection still has to convict.