claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

feat(auto-blocker): Track novel vs known detections

Open pduggusa opened this issue 3 weeks ago • 0 comments

Summary

The auto-blocker catches IPs attacking our infrastructure in real-time, but we don't currently track whether each detection is novel (first-catch) or known (already in threat feeds).

This is a key metric for:

  1. Proving original observation (legal/ethical distinction from derivative data)
  2. Measuring first-catch rate
  3. Demonstrating value to feed consumers
  4. Bragging rights

Current Behavior

Auto-blocker catches IP → blocks → reports to AbuseIPDB → indexes

No tracking of whether the IP was already known elsewhere.

Proposed Enhancement

1. Pre-block Novelty Check

Before blocking, check if IP exists in:

  • [ ] AbuseIPDB (abuseScore > 0)
  • [ ] VirusTotal (malicious detections > 0)
  • [ ] Our IOCs index (already indexed)
  • [ ] OTX (exists in pulses)

2. New Fields on Block Record

```javascript { ip: "1.2.3.4", // ... existing fields ...

// NEW: Novelty tracking wasNovel: true, // true if first-catch noveltyScore: 4, // 0-4 (how many sources we beat) priorSources: [], // which sources already had it (if any) firstCatchBy: "auto-blocker", // detection source noveltyCheckedAt: "2025-12-24T23:00:00Z" } ```

3. Implementation

```javascript async function checkNovelty(ip) { const [abuseipdb, vt, ourIOCs, otx] = await Promise.all([ checkAbuseIPDB(ip), checkVirusTotal(ip), checkOurIndex(ip), checkOTX(ip) ]);

const isNovel = { abuseipdb: abuseipdb.abuseScore === 0, virustotal: vt.malicious === 0, ourIOCs: !ourIOCs.exists, otx: !otx.exists };

const noveltyScore = Object.values(isNovel).filter(v => v).length; const priorSources = Object.entries(isNovel) .filter(([k, v]) => !v) .map(([k]) => k);

return { wasNovel: noveltyScore === 4, noveltyScore, priorSources, firstCatchBy: noveltyScore === 4 ? 'auto-blocker' : null }; } ```

4. New API Endpoint

``` GET /api/v1/auto-blocker/novelty-stats

Response: { "total": 326, "novel": 287, "known": 39, "noveltyRate": "88%", "beatAbuseIPDB": 301, "beatVirusTotal": 312, "beatOTX": 298 } ```

5. Dashboard Integration

Add to Mirepoix:

  • Novel detection rate (%)
  • First-catch count (24h)
  • "Beat the feeds" leaderboard

Files to Modify

  • [ ] lib/auto-blocker.js - Add novelty check before blocking
  • [ ] routes/api/v1/behavioral.js - Add novelty stats endpoint
  • [ ] routes/api/v1/mirepoix.js - Include novelty metrics

Success Criteria

  • Every auto-blocker catch has wasNovel field
  • API endpoint returns novelty statistics
  • Can prove X% of detections are original observation

Context

Christmas Eve 2025: Auto-blocker caught 326 IPs in one hour during coordinated China Telecom/Huawei attack. No way to prove how many were first-catch.

That's the gap this fixes.


"They attacked us first. We wrote it down. Now we can prove it."

pduggusa avatar Dec 24 '25 18:12 pduggusa