refactor: suppression dépendance User-Agent de la détection navigateur

Changements SQL :
- modern_browser_score : sec-ch-ua→100, Sec-Fetch→70 (plus de UA fallback)
- Ajout has_sec_ch_ua (UInt8) dans agg_header_fingerprint_1h et ml_all_scores
- mss_mobile_mismatch utilise has_sec_ch_ua au lieu de modern_browser_score
- header_order_confidence : PARTITION BY ja4 au lieu de first_ua
- sec_ch_mobile_mismatch : comparaison Client Hints interne (sans UA)
- Migration 03_remove_ua_browser_detection.sql

Changements Python :
- browser.py Axe 3 : Client Hints + Sec-Fetch + is_fake_navigation (PAS de UA)
- Pondération axes : ja4_known 0.30, tls_coherence 0.20 (signaux TLS renforcés)
- preprocessing.py : has_sec_ch_ua ajouté aux features et binary_features

Fichiers modifiés : 8 SQL/Python + 1 migration, 36/36 tests passent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
toto
2026-04-09 23:06:01 +02:00
parent 00e99e5464
commit 14db3d9040
9 changed files with 101 additions and 38 deletions

View File

@ -1,8 +1,8 @@
"""A9 — Identification multifactorielle des navigateurs.
5 axes indépendants combinés pour identifier les navigateurs légitimes.
Chaque axe produit un score [0,1]. La combinaison pondérée produit
browser_confidence [0,1], remplaçant l'ancien système binaire JA4-only.
Aucun axe ne repose sur le User-Agent (trivalement falsifiable).
Signaux principaux : JA4 (TLS), Client Hints, Sec-Fetch-*, comportement.
"""
import pandas as pd
import numpy as np
@ -22,10 +22,11 @@ _BROWSER_JA4_PROFILES = {
}
# Pondération des 5 axes pour le score browser_confidence.
# Favorise les signaux TLS (difficiles à falsifier) sur HTTP.
_AXIS_WEIGHTS = {
'ja4_known': 0.25, # Axe 1 — Signature JA4 dans dict_browser_ja4
'ja4_known': 0.30, # Axe 1 — Signature JA4 dans dict_browser_ja4 (TLS fingerprint)
'ja4_struct': 0.15, # Axe 2 — Structure JA4 (TLS1.3, h2, nb ciphers/ext)
'http_modern': 0.25, # Axe 3 — Headers HTTP modernes (sec-ch-ua, Sec-Fetch-*)
'http_modern': 0.20, # Axe 3 — Client Hints + Sec-Fetch-* (PAS de User-Agent)
'nav_behavior': 0.15, # Axe 4 — Comportement de navigation (assets, referers)
'tls_coherence': 0.20, # Axe 5 — Cohérence TLS/TCP (pas de mismatch)
}
@ -80,18 +81,21 @@ def _compute_browser_axes(df: pd.DataFrame) -> pd.DataFrame:
is_tls13 * 0.35 + is_h2h3 * 0.25 + ciphers_ok * 0.20 + exts_ok * 0.20
)
# ── Axe 3 — Headers HTTP modernes ──
mbs = df.get('modern_browser_score', pd.Series(0, index=df.index)).fillna(0)
# ── Axe 3 — Signaux HTTP sans User-Agent ──
# Client Hints (sec-ch-ua) = signal fort, nécessite un vrai moteur Chromium.
# Sec-Fetch-* = signal moyen, envoyé automatiquement par les navigateurs modernes.
# Le User-Agent n'est PAS utilisé (trivalement falsifiable par n'importe quel bot).
scu = df.get('has_sec_ch_ua', pd.Series(0, index=df.index)).fillna(0)
hal = df.get('has_accept_language', pd.Series(0, index=df.index)).fillna(0)
sfa = df.get('sec_fetch_absence_rate', pd.Series(1, index=df.index)).fillna(1)
gar = df.get('generic_accept_ratio', pd.Series(1, index=df.index)).fillna(1)
uam = df.get('ua_ch_mismatch', pd.Series(0, index=df.index)).fillna(0)
ifn = df.get('is_fake_navigation', pd.Series(0, index=df.index)).fillna(0)
axes['axis_http_modern'] = (
(mbs >= 50).astype(float) * 0.35
+ (hal > 0).astype(float) * 0.20
+ (sfa < 0.3).astype(float) * 0.25
+ (gar < 0.3).astype(float) * 0.10
+ (uam == 0).astype(float) * 0.10
(scu > 0).astype(float) * 0.30
+ (sfa < 0.2).astype(float) * 0.30
+ (hal > 0).astype(float) * 0.15
+ (gar < 0.3).astype(float) * 0.15
+ (ifn == 0).astype(float) * 0.10
)
# ── Axe 4 — Comportement de navigation ──