diff --git a/app/docs/roadmap.yaml b/app/docs/roadmap.yaml index 84af7e3..21e9f3d 100644 --- a/app/docs/roadmap.yaml +++ b/app/docs/roadmap.yaml @@ -2,18 +2,6 @@ updated: "2025-08-22" roadmap: - - id: "p1-analysis-cloudflare" - priority: 1 - title: "Cloudflare Detection" - goal: "Detect Cloudflare usage and badge it, with explanation of dual-use (security vs. abuse)." - tags: ["analysis"] - milestone: null - details: - - "Detection signals: DNS (CNAME to Cloudflare, AS13335), HTTP headers (cf-ray, cf-cache-status), IP ranges, and challenge pages." - - "UI: add badge + tooltip with a short explainer about legitimate protection vs. abuse evasion." - - "Edge cases: 'grey-clouded' DNS entries, partial proxy (only some records), and CDN in front of non-HTTP services." - - "Acceptance: correctly identifies Cloudflare on known test hosts and avoids false positives on non-CF CDNs." - - id: "p1-analysis-total-score" priority: 1 title: "Total Score" @@ -26,15 +14,6 @@ roadmap: - "Explainability: always show a breakdown and contribution per component; include a 'Why?' link in the UI." - "Calibration: start with heuristic weights, then calibrate on a test set; store weights in settings.yaml." - - id: "p1-modal-close-fast" - priority: 1 - title: "Analyze modal closes too fast" - goal: "have it wait until page reload" - tags: ["ui"] - milestone: null - details: - - "UX: user sees modal removed too quickly and thinks something broke" - - id: "p2-ui-rules-lab" priority: 2 title: "Rules Lab" diff --git a/app/templates/partials/result_enrichment.html b/app/templates/partials/result_enrichment.html index 3f6fc64..6ce8eb4 100644 --- a/app/templates/partials/result_enrichment.html +++ b/app/templates/partials/result_enrichment.html @@ -37,6 +37,9 @@ {{ ip }} - {% if info.country %} {{ info.country }} {% endif %} - {% if info.isp %} {{ info.isp }} {% endif %} + {% if info.cloudflare %} + Cloudflare + {% endif %}
diff --git a/app/utils/enrichment.py b/app/utils/enrichment.py index ad57c67..bdbc71e 100644 --- a/app/utils/enrichment.py +++ b/app/utils/enrichment.py @@ -336,6 +336,9 @@ def enrich_whois(hostname: str) -> dict: def enrich_geoip(hostname: str) -> dict: """Resolve hostname to IPs and fetch info from ip-api.com.""" + + CLOUDFLARE_ASN = "AS13335 Cloudflare" + geo_info = {} ips = extract_ips_from_url(hostname) for ip in ips: @@ -352,6 +355,12 @@ def enrich_geoip(hostname: str) -> dict: resp = requests.get(f"http://ip-api.com/json/{ip_str}?fields=24313855", timeout=5) if resp.status_code == 200: geo_info[ip_str] = resp.json() + asname = geo_info[ip_str].get("as") + + # if behind cloudflare + if CLOUDFLARE_ASN in asname: + geo_info[ip_str].update({"cloudflare":True}) + else: geo_info[ip_str] = {"error": f"HTTP {resp.status_code}"} except Exception as e: