From 06db2ff68edf4c8f12bf5c7136516f335e76dc42 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sat, 4 Jul 2026 14:56:25 +0200 Subject: [PATCH] feat(toolbox): #ads dashboard surfaces detected candidates (#802) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ad_stats now returns total_candidates + top_candidates from ad_candidates (observed ad/tracker hosts awaiting autolearn promotion to active 204-blocking). The #ads tab gains a '🔎 Trackers/pubs dĂ©tectĂ©s' card so the dashboard reflects real detection even when total_blocked is 0 (nothing promoted yet) — was showing all-zeros + empty tables despite live detection. Deployed to gk2. --- packages/secubox-toolbox/secubox_toolbox/store.py | 14 +++++++++++++- packages/secubox-toolbox/www/toolbox/index.html | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/secubox-toolbox/secubox_toolbox/store.py b/packages/secubox-toolbox/secubox_toolbox/store.py index 580e963b..9ec17e3b 100644 --- a/packages/secubox-toolbox/secubox_toolbox/store.py +++ b/packages/secubox-toolbox/secubox_toolbox/store.py @@ -173,7 +173,7 @@ def ad_stats(hours: int = 24, top: int = 25) -> dict: cutoff = time.time() - hours * 3600 out = {"window_hours": hours, "total_blocked": 0, "total_bytes": 0, "by_action": {"block": 0, "silent": 0}, "top_hosts": [], "top_sites": [], - "top_visitors": []} + "top_visitors": [], "total_candidates": 0, "top_candidates": []} try: with _conn() as c: for action, hits in c.execute( @@ -194,6 +194,18 @@ def ad_stats(hours: int = 24, top: int = 25) -> dict: "SELECT mac_hash, SUM(hits) FROM ad_block_client_host " "WHERE last_seen>=? AND mac_hash<>'' GROUP BY mac_hash " "ORDER BY SUM(hits) DESC LIMIT ?", (cutoff, top))] + # #802 — DETECTED ad/tracker hosts (ad_candidates: observed, awaiting + # autolearn promotion to active 204-blocking). Surface them so the + # dashboard reflects real detection even when nothing is blocked yet. + try: + out["top_candidates"] = [{"host": h, "hits": int(n)} for h, n in c.execute( + "SELECT host, SUM(hits) FROM ad_candidates WHERE last_seen>=? " + "GROUP BY host ORDER BY SUM(hits) DESC LIMIT ?", (cutoff, top))] + r = c.execute("SELECT COUNT(DISTINCT host) FROM ad_candidates WHERE last_seen>=?", + (cutoff,)).fetchone() + out["total_candidates"] = int((r and r[0]) or 0) + except sqlite3.Error: + pass # #755 — trackers detected/poisoned by the MITM in the window: distinct # cross-site cookie-identifier hashes seen on social_edges. This is the # "Trackers" half of the card (the 204 ad-block is the "pubs" half). diff --git a/packages/secubox-toolbox/www/toolbox/index.html b/packages/secubox-toolbox/www/toolbox/index.html index c80d5b74..bad2b199 100644 --- a/packages/secubox-toolbox/www/toolbox/index.html +++ b/packages/secubox-toolbox/www/toolbox/index.html @@ -185,6 +185,10 @@

🎯 Top hĂŽtes publicitaires bloquĂ©s

loading

+
+

🔎 Trackers/pubs dĂ©tectĂ©s (candidats — observĂ©s, pas encore promus au blocage)

+
loading

+

🌐 Top sites visitĂ©s

loading

@@ -640,6 +644,11 @@ async function loadAds() { document.getElementById('ads-sites').innerHTML = siteRows ? ''+siteRows+'
Sitetrackers/pubs bloqués
' : ''; + // #802 — detected candidates (observed, awaiting promotion to active blocking) + const candRows = (d.top_candidates||[]).slice(0, 15).map(r=>`${esc(r.host)}${r.hits}`).join(''); + document.getElementById('ads-candidates').innerHTML = candRows + ? `
${d.total_candidates||0} hĂŽtes dĂ©tectĂ©s dans la fenĂȘtre
${candRows}
HÎte détectéobservations
` + : '
aucun tracker/pub dĂ©tectĂ© dans la fenĂȘtre
'; const visRows = (d.top_visitors||[]).slice(0, 5).map(r=>{ const mh = esc(r.mac_hash); return `${mh}${r.hits}`;