# Audit de conformité : Code vs Thèse — Mise à jour 8 avril 2026 **Date** : 8 avril 2026 **Référence** : `docs/THESIS_HTTP_Traffic_Detection.md` **Périmètre** : `services/bot-detector/`, `services/dashboard/`, schéma SQL --- ## Légende | Statut | Signification | |--------|---------------| | ✅ CONFORME | Implémenté conformément à la thèse | | ⚠️ PARTIEL | Implémenté mais incomplet ou dégradé | | ❌ ABSENT | Décrit dans la thèse, non implémenté | | 🔄 DIVERGENT | Implémenté différemment de ce que décrit la thèse | | 🐛 BUG | Implémenté mais avec un bug qui empêche le fonctionnement correct | --- ## Partie A — Conformité bot-detector vs Thèse ### A1. Architecture multi-couches (Thèse §3) | Composant thèse | Statut | Détail | |-----------------|--------|--------| | Pipeline L3-L5 (ja4sentinel) | ✅ | TTL, IP-ID, DF, TCP win/mss/scale, JA4/JA3, ALPN, SNI | | Pipeline L7 (mod_reqin_log) | ✅ | Headers, méthode, path, query, timestamps ns | | Corrélation (logcorrelator) | ✅ | Clé `src_ip:src_port`, Keep-Alive, orphelins | | Enrichissement ASN | ✅ | `dict_iplocate_asn` (714K CIDRs, 4 colonnes) | | Enrichissement Anubis | ✅ | 5 niveaux priorité (UA+IP > UA > IP > ASN > Country) | | Agrégation 1h | ✅ | `agg_host_ip_ja4_1h` + `agg_header_fingerprint_1h` | | Vue features | ✅ | `view_ai_features_1h` (72+ colonnes) | | Bifurcation Complet/Applicatif | ✅ | Complet (63 features L3→L7, correlated=1) + Applicatif (51 features L7, correlated=0) | ### A2. Features L3 IP (Thèse §3.2) | Feature thèse | Statut | Colonne SQL / Python | |--------------|--------|---------------------| | avg_ttl | ✅ | `avg_ttl` dans `view_ai_features_1h` | | ttl_std | ✅ | `ttl_std` | | ip_id_zero_ratio | ✅ | `ip_id_zero_ratio` | | ip_df_variance | ✅ | `ip_df_variance` | | request_size_variance | ✅ | `request_size_variance` | | anomalous_payload_ratio | ✅ | `anomalous_payload_ratio` | ### A3. Features L4 TCP (Thèse §3.3) | Feature thèse | Statut | Détail | |--------------|--------|--------| | true_window_size | ⚠️ PARTIEL | Calculé dans SQL mais **non inclus dans `feats_complet`** — pas utilisé par l'EIF | | window_mss_ratio | ⚠️ PARTIEL | Calculé dans SQL, **absent de `feats_complet`** | | mss_mobile_mismatch | ✅ | Dans `feats_complet` | | no_window_scale_ratio | ✅ | Dans `feats_complet` | | tcp_shared_count | ✅ | Dans `feats` | | tcp_jitter_variance | ✅ | Dans `feats_complet` | | src_port_density | ✅ | Dans `feats` | | port_exhaustion_ratio | ✅ | Dans `feats` | | max_keepalives | ✅ | Dans `feats` | ### A4. Features L5 TLS (Thèse §3.4) | Feature thèse | Statut | Détail | |--------------|--------|--------| | JA4 fingerprint | ✅ | Clé de corrélation + feature | | is_rare_ja4 | ✅ | Dans `feats_complet` | | ja3_diversity_ratio | ✅ | Dans `feats_complet` | | is_alpn_missing | ✅ | Dans `feats_complet` | | sni_host_mismatch | ✅ | Dans `feats_complet` | | tls12_ratio | ✅ | Dans `feats_complet` | | alpn_http_mismatch | ✅ | Dans `feats_complet` | ### A5. Features L7 HTTP (Thèse §3.5 + §2.3) | Feature thèse | Statut | Détail | |--------------|--------|--------| | hits, hit_velocity | ✅ | | | fuzzing_index | ✅ | | | post_ratio, head_ratio | ✅ | | | asset_ratio, direct_access_ratio | ✅ | | | modern_browser_score | ✅ | 0/50/100 | | ua_ch_mismatch | ✅ | | | has_accept_language, has_cookie, has_referer | ✅ | | | sec_fetch_absence_rate | ✅ | | | generic_accept_ratio | ✅ | | | missing_accept_enc_ratio | ✅ | | | header_count, header_order_confidence | ✅ | | | temporal_entropy | ✅ | Shannon entropie | | path_diversity_ratio, url_depth_variance | ✅ | | | http10_ratio, http_scheme_ratio | ✅ | | | orphan_ratio | ✅ | | | is_ua_rotating | ✅ | | ### A6. ML Pipeline (Thèse §2.4 + §3.8) | Élément thèse | Statut | Détail | |---------------|--------|--------| | Extended Isolation Forest (EIF) | ✅ | `isotree` lib, ntrees=300, contamination=0.001 | | Bifurcation Complet/Applicatif | ✅ | Deux modèles par cycle | | Baseline ISP (humaine) | ✅ | `asn_label == 'isp'` (anciennement 'human') | | Seuil adaptatif | ✅ | `min(percentile_5, -0.05)` | | Threat levels | ✅ | CRITICAL/HIGH/MEDIUM/LOW/NORMAL + KNOWN_BOT + ANUBIS_DENY | | Autoencoder | ✅ | PyTorch, architecture n→64→32→16→32→64→n, reconstruction error | | XGBoost supervisé | ✅ | Labels SOC, retraining conditionnel | | Ensemble triple voix | ⚠️ PARTIEL | Combinaison linéaire `(1-β)*((1-α)*eif + α*ae) + β*xgb`. **Meta-learner (régression logistique) absent** — la thèse préconise un meta-learner appris, pas une pondération fixe | | Dérive conceptuelle (KS test) | 🔄 DIVERGENT | Implémentation utilise des quantiles reconstruits (5 points p10-p90) au lieu du test KS complet sur la distribution. Approximation grossière pour distributions multimodales | | Validation gate | ✅ | Taux anomalie >20% → rejet modèle | | Feature pruning (variance) | ✅ | Seuil 1e-6 | | SHAP explainability | ✅ | Top-5 features par anomalie | | HDBSCAN clustering | ✅ | Campagnes coordonnées | | Feedback loop SOC | ✅ | FP→baseline, TP→exclusion | | Déduplication TTL | ✅ | Inter-cycles, configurable | | Récurrence penalty | ✅ | log1p(recurrence) × weight | | Browser légitime (LEGITIMATE_BROWSER) | ✅ | JA4 + consistency score ≥ 4/5 | ### A7. Techniques originales (Thèse §5) | Technique | Statut | Détail | |-----------|--------|--------| | §5.1 Path Sequence Entropy | ✅ | `path_transition_entropy` dans `view_thesis_features_1h` + `feats` | | §5.2 Bipartite JA4×ASN Graph | ❌ ABSENT | Non implémenté | | §5.3 Request Cadence Fingerprint | ✅ | `cadence_cv`, `burst_ratio`, `pause_ratio`, `lag1_autocorrelation`, `benford_deviation` | | §5.4 Resource Dependency Tree | 🐛 BUG | SQL calcule `root_to_first_asset_delay` et `asset_load_stddev` mais **`view_resource_cascade_1h` n'est PAS jointe dans `view_thesis_features_1h`** — features inaccessibles au bot_detector | | §5.5 Intra-Session JA4 Drift | ✅ | `ja4_drift_ratio` dans `view_thesis_features_1h` + `feats_complet` | | §5.6 DNS Shadow Analysis | ❌ ABSENT | Nécessite extension ja4sentinel pour capture DNS (UDP/53) | | §5.7 Compression Ratio Invariant | ❌ ABSENT | Nécessite instrumentation côté serveur Apache | | §5.8 Cross-Domain Session Linking | ✅ | `host_diversity`, `host_sweep_speed`, `host_coverage_uniformity` dans `view_thesis_features_1h` + `feats` | ### A8. Taxonomie 7 familles (Thèse §4) | Famille | Features attendues | Statut | |---------|-------------------|--------| | 1. Volume & Vitesse | hits, hit_velocity, max_keepalives | ✅ 3/3 | | 2. Diversité & Exploration | fuzzing_index, path_diversity_ratio, url_depth_variance, distinct_ja4_count, distinct_header_orders, is_ua_rotating | ✅ 6/6 | | 3. Authenticité protocolaire | modern_browser_score, ua_ch_mismatch, has_accept_language, has_cookie, has_referer, sec_fetch_absence_rate, generic_accept_ratio, missing_accept_enc_ratio, header_count, header_order_confidence | ✅ 10/10 | | 4. Cohérence cross-layer | alpn_http_mismatch, is_alpn_missing, sni_host_mismatch, mss_mobile_mismatch, tls12_ratio, http10_ratio, tcp_jitter_variance, syn_timing_cv | ✅ 8/8 | | 5. Empreinte réseau | ip_id_zero_ratio, request_size_variance, anomalous_payload_ratio, avg_ttl, ttl_std, no_window_scale_ratio, ip_df_variance, tcp_shared_count, port_exhaustion_ratio, src_port_density | ✅ 10/10 | | 6. Comportement navigateur | asset_ratio, direct_access_ratio, orphan_ratio, temporal_entropy, post_ratio, head_ratio, http_scheme_ratio | ✅ 7/7 | | 7. Intelligence contextuelle | ja4_asn_concentration, ja4_country_concentration, is_rare_ja4, header_order_shared_count, ja3_diversity_ratio, anubis_is_flagged, multiplexing_efficiency | ✅ 7/7 | **Total taxonomie : 51/51 features (100%)** --- ## Partie B — Bugs identifiés dans bot-detector ### B1. Bugs critiques (impact fonctionnel) | # | Sévérité | Description | Localisation | |---|----------|-------------|-------------| | B1.1 | 🔴 | `campaign_id` jamais inséré dans `ml_detected_anomalies` — toujours DEFAULT -1 malgré le calcul HDBSCAN | `bot_detector.py` cols ligne ~1624 | | B1.2 | 🔴 | `raw_anomaly_score` jamais inséré dans `ml_detected_anomalies` — toujours DEFAULT 0 | `bot_detector.py` cols ligne ~1624 | | B1.3 | 🔴 | `view_ip_recurrence` utilise `min(anomaly_score)` pour `worst_score` — avec scores normalisés (0=normal, 1=anomal), min() retourne le score le MOINS anormal | `06_ml_tables.sql` | | B1.4 | 🟠 | `log_decision('FEATURE_PRUNED', name, '', ...)` — `name` passé en `cycle_id` au lieu de `model` (argument order swap) | `bot_detector.py:596` | | B1.5 | 🟠 | `log_decision('MODEL_REJECTED', name, '', ...)` — même inversion d'arguments | `bot_detector.py:623` | | B1.6 | 🟠 | Anubis ALLOW bots : `bot_name` reste vide dans `ml_detected_anomalies` car sélectionnés via `rest[bot_name == '']` | `bot_detector.py:970-1140` | | B1.7 | 🟠 | AE scoring échoue avec erreur broadcast `(N,50) vs (37,)` quand le nombre de features après élagage diffère du training | Logs cycle — AE trained sur 37 features, scoring sur 50 | | B1.8 | 🟡 | `rec_df` peut être `None` → `TypeError` sur `dict(zip(rec_df['src_ip']...))` | `bot_detector.py:~1489` | | B1.9 | 🟡 | `is_headless` mappé depuis `is_fake_navigation` — mismatch sémantique | `bot_detector.py:1622` | ### B2. Bugs qualité code | # | Sévérité | Description | Localisation | |---|----------|-------------|-------------| | B2.1 | 🟡 | `warnings.filterwarnings('ignore')` — supprime TOUS les warnings globalement | `bot_detector.py:71` | | B2.2 | 🟡 | `pyyaml` dans requirements.txt mais jamais importé | `requirements.txt` | | B2.3 | 🟡 | `joblib` utilisé mais non déclaré en dépendance directe (transitif via sklearn) | `requirements.txt` | | B2.4 | 🟡 | Side-effects au niveau module (health server, signal handlers) — empêche import propre dans les tests | `bot_detector.py:232,252-259` | | B2.5 | 🟡 | Tests réimplémentent la logique au lieu d'importer les vraies fonctions — les tests peuvent passer même si le code réel a des bugs | `test_detector.py` | | B2.6 | 🟡 | Section header dupliquée "A5 — DÉDUPLICATION" | `bot_detector.py:1242,1280` | | B2.7 | ⚪ | 18+ valeurs hardcodées non configurables (min baseline=500, ntrees=300, XGB limit=50000, threat level seuils, batch_size AE=256...) | Dispersé | ### B3. Feature SQL non jointe (Thèse §5.4) `view_resource_cascade_1h` est définie dans `12_thesis_features.sql` mais **absente du JOIN final** dans `view_thesis_features_1h`. Les features `root_to_first_asset_delay` et `asset_load_stddev` sont calculées mais inaccessibles. ### B4. Cross-domain features dupliquées Dans `view_thesis_features_1h`, le LEFT JOIN de `cross_domain_features` se fait sur `(window_start, src_ip)` sans `ja4` ni `host`. Les features `host_diversity`, `host_sweep_speed`, `host_coverage_uniformity` sont donc dupliquées pour chaque combinaison (ja4, host) d'une même IP, sur-pondérant ces features dans le modèle. --- ## Partie C — Bugs identifiés dans dashboard ### C1. Bugs critiques (sécurité) | # | Sévérité | Description | Localisation | |---|----------|-------------|-------------| | C1.1 | 🔴 | **XSS** : `const IP = "{{ ip }}";` — injection JS via URL `/ip/";alert(1);//` | `ip_detail.html:72`, `pages.py:37` | | C1.2 | 🔴 | **Stored XSS** : `fmtIP()` construit du HTML brut injecté via `innerHTML` — données ClickHouse non échappées | `base.html:123`, tous les templates | | C1.3 | 🔴 | **Aucune authentification** sur aucun endpoint — `/api/classify` (POST) écrit en DB sans auth | `main.py`, `api.py:770` | | C1.4 | 🔴 | **Pas de CSRF** sur le POST `/api/classify` + CORS `allow_origins=["*"]` | `main.py:19-25` | ### C2. Bugs fonctionnels | # | Sévérité | Description | Localisation | |---|----------|-------------|-------------| | C2.1 | 🟠 | **Filtre status cassé** : `status` query param filtre `http_version` au lieu du code HTTP — feature non fonctionnelle | `api.py:335` | | C2.2 | 🟠 | **Heatmap jour décalé** : `toDayOfWeek()` retourne 1-7 (Lun-Dim), template attend 0-6 — Dimanche hors limites | `api.py:654`, `features.html:63` | | C2.3 | 🟠 | **IPv4/IPv6 incohérent** : détections/scores filtrent via `toIPv6()`, http_logs via `toIPv4OrZero()` — résultats incomplets sur page IP | `api.py:378-399` | | C2.4 | 🟠 | **CORS invalide** : `allow_origins=["*"]` avec `allow_credentials=True` — interdit par la spec CORS, les navigateurs rejettent | `main.py:19-25` | | C2.5 | 🟡 | Bouton filtre MEDIUM manquant sur la page scores | `scores.html:22` | | C2.6 | 🟡 | `models.html` — null safety manquante : `m.validation.val_anomaly_rate*100` crash si null | `models.html:51` | | C2.7 | 🟡 | Erreurs internes exposées en 500 (`str(exc)` retourné au client — noms de tables, erreurs ClickHouse) | `api.py:144,226,303,364,433,787` | | C2.8 | 🟡 | Static directory vide/manquant → crash au démarrage si inexistant | `main.py:28` | | C2.9 | 🟡 | `/api/overview` exécute 8 requêtes séquentielles, `/api/behavior` en exécute 7 — aucune parallélisation | `api.py` | | C2.10 | ⚪ | Aucun test unitaire ou d'intégration pour le dashboard | — | | C2.11 | ⚪ | Dockerfile : pas de `HEALTHCHECK`, exécution root, pas de `.dockerignore` | `Dockerfile` | --- ## Partie D — Synthèse quantitative ### D1. Conformité thèse | Section thèse | Éléments | Conformes | Partiels | Absents | Bugs | Score | |--------------|----------|-----------|----------|---------|------|-------| | §3 Architecture | 8 | 8 | 0 | 0 | 0 | 100% | | §3.2 L3 IP | 6 | 6 | 0 | 0 | 0 | 100% | | §3.3 L4 TCP | 9 | 7 | 2 | 0 | 0 | 89% | | §3.4 L5 TLS | 7 | 7 | 0 | 0 | 0 | 100% | | §3.5 L7 HTTP | 17 | 17 | 0 | 0 | 0 | 100% | | §4 Taxonomie 7 familles | 51 | 51 | 0 | 0 | 0 | 100% | | §2.4+§3.8 ML Pipeline | 16 | 13 | 2 | 0 | 1 | 84% | | §5 Techniques originales | 8 | 4 | 0 | 3 | 1 | 50% | | **TOTAL** | **122** | **113** | **4** | **3** | **2** | **93%** | ### D2. Évolution depuis le dernier audit (7 avril) | Métrique | 7 avril | 8 avril | Delta | |----------|---------|---------|-------| | §5 Techniques originales | 6% (0/8 + 1 partiel) | 50% (4/8) | **+44%** | | Feedback loop SOC | ❌ ABSENT | ✅ CONFORME | ✅ Résolu | | Browser classification | ❌ ABSENT | ✅ CONFORME | ✅ Résolu | | ASN classification PeeringDB | ⚠️ 86% unknown | ✅ 7 catégories | ✅ Résolu | | Score global pondéré | ~72% | ~93% | **+21%** | ### D3. Gaps restants (par priorité) | Priorité | Gap | Impact | Effort | |----------|-----|--------|--------| | P0 🔴 | `campaign_id` + `raw_anomaly_score` jamais insérés | Clustering HDBSCAN inutile, score brut perdu | 5 min — ajouter aux cols | | P0 🔴 | `worst_score` inversé dans `view_ip_recurrence` | Récurrence penalty basée sur mauvais score | 5 min — `max()` au lieu de `min()` | | P0 🔴 | XSS dans `ip_detail.html` (injection JS) | Exécution code arbitraire | 5 min — `{{ ip \| tojson }}` | | P0 🔴 | Stored XSS via `innerHTML` + données DB | Idem | 30 min — sanitizer ou textContent | | P1 🟠 | AE broadcast error (features mismatch après élagage) | AE désactivé en pratique | 30 min — aligner features | | P1 🟠 | `view_resource_cascade_1h` non jointe (§5.4) | Features thèse §5.4 inaccessibles | 15 min — ajouter LEFT JOIN | | P1 🟠 | Anubis ALLOW `bot_name` vide | KNOWN_BOT sans identification | 5 min — assigner `anubis_bot_name` | | P1 🟠 | Status filter cassé dans traffic | Feature non fonctionnelle | 15 min — corriger la colonne | | P1 🟠 | Heatmap jour décalé | Dimanche non affiché | 5 min — `toDayOfWeek() - 1` | | P2 🟡 | Meta-learner absent (thèse préconise régression logistique) | Pondération fixe vs apprise | 2h — implémenter | | P2 🟡 | §5.2 Bipartite JA4×ASN Graph | Technique originale manquante | 4h | | P2 🟡 | §5.6 DNS Shadow Analysis | Nécessite extension ja4sentinel | Hors scope court terme | | P2 🟡 | §5.7 Compression Ratio Invariant | Nécessite instrumentation Apache | Hors scope court terme | | P3 ⚪ | Authentification dashboard | Sécurité production | 4h | | P3 ⚪ | Tests dashboard (0% coverage) | Qualité | 8h | | P3 ⚪ | Tests bot-detector importent le vrai code | Qualité | 4h | --- ## Partie E — Conformité dashboard vs architecture thèse (§3.1) La thèse décrit le dashboard comme composant de "21 modules + clustering + outils SOC". État actuel : | Module thèse | Statut | Pages/Endpoints | |-------------|--------|-----------------| | Vue d'ensemble (overview) | ✅ | `/overview` — stats agrégées, top IPs, top JA4 | | Détections (anomalies) | ✅ | `/detections` — tri, filtres, pagination | | Scores ML (all_scores) | ✅ | `/scores` — toutes les sessions scorées | | Trafic brut | ⚠️ PARTIEL | `/traffic` — filtre status cassé (C2.1) | | Détail IP | ⚠️ PARTIEL | `/ip/` — XSS (C1.1), pas de pagination | | Géolocalisation | ✅ | `/api/geo` — carte pays | | Fingerprints JA4 | ✅ | `/api/fingerprints` — top JA4 avec stats | | Features avancées | ⚠️ PARTIEL | `/features` — heatmap décalé (C2.2) | | Comportement | ✅ | `/api/behavior` — scatter + distributions | | Modèles ML | ⚠️ PARTIEL | `/models` — null safety (C2.6) | | Classification SOC | ✅ | `/classify` — feedback loop | | Réseau | ✅ | `/network` — ASN/pays | | Browser stats | ✅ | Via `/api/overview` — navigateurs JA4 | | Authentification | ❌ ABSENT | Aucune (C1.3) | | CSRF protection | ❌ ABSENT | Aucune (C1.4) |