Burn Confidence Scoring#
The BurnScorer sits alongside the binary BurnDetector and provides a continuous 0-100 confidence score per domain. Where the BurnDetector fires hard alerts at fixed thresholds, the scorer aggregates weighted signals so operators can see burn risk building up before it crosses the line.
Signals and Weights#
Six signal types feed into the score. Weights sum to 100.
| Signal | Weight | What triggers it |
|---|---|---|
ja3_change | 20 | 2+ unique JA3 fingerprints observed in the last hour |
volume_spike | 20 | Request rate exceeds 3x the baseline in a 5-minute window |
new_asn | 15 | 2+ previously unseen ASNs probing the domain in 10 minutes |
ct_log | 20 | CT log exposure events from the CTMonitor within 24 hours |
reputation_hit | 15 | Domain listed on URLhaus/OpenPhish/Safe Browsing within 24 hours |
failed_auth | 10 | 5+ failed API/dashboard auth attempts in the last hour |
Recommended Actions#
The score maps directly to an action:
| Score Range | Action | Meaning |
|---|---|---|
| 0 - 49 | monitor | Domain is probably clean. Keep watching. |
| 50 - 79 | rotate | Schedule infrastructure rotation and prepare replacement. |
| 80 - 100 | immediate_burn | Domain is compromised. Retire it now. |
API Endpoint#
# Get burn score for a specific domain
curl -H "Authorization: Bearer $TOKEN" \
https://ig:8080/api/burn/score/cdn.example.comResponse:
{
"domain": "cdn.example.com",
"score": 55,
"action": "rotate",
"signals": [
{
"signal_type": "volume_spike",
"description": "Request volume spike: 47 reqs in 300s (baseline ~12.3, multiplier 3.0x)",
"weight": 20
},
{
"signal_type": "new_asn",
"description": "3 new ASNs probing in 600s window: [13335, 16509, 32934]",
"weight": 15
},
{
"signal_type": "ja3_change",
"description": "4 unique JA3 fingerprints observed in 3600s window (threshold: 2)",
"weight": 20
}
],
"evaluated_at": 1711234567.0
}How Signals Are Recorded#
The scorer exposes recording methods that other components call as events happen:
scorer.record_ja3(domain, ja3_hash) # called by TLS filter
scorer.record_request(domain) # called by router on every request
scorer.record_asn(domain, asn_number) # called by IP intelligence
scorer.record_failed_auth(domain) # called by API auth middlewareCT log and reputation signals are pulled from the BurnDetector’s internal event list, so they don’t need separate recording.
Baseline ASNs#
To avoid false positives from legitimate CDN or hosting ASNs that regularly hit the redirector, operators can seed a baseline:
scorer.set_baseline_asns("cdn.example.com", {13335, 16509}) # Cloudflare, AWSOnly ASNs not in the baseline count toward the new_asn signal.
Integration with Rotation#
The burn score feeds into the RotationScheduler. An on_burn_detected rotation policy watches for scores crossing the threshold and triggers automatic infrastructure rotation when the score hits the configured level.