DEV Community

shyn
shyn

Posted on

I Built a Threat Intelligence Tool That Maps Malicious IPs in Real Time

What I Built

The Breadcrumb Engine is a Python tool that takes a list of IP addresses and plots them on an interactive dark-mode map, enriched with real-time threat intelligence from VirusTotal. Each IP is colour-coded by risk level and the full dataset is exportable as CSV.

🟢 Green → 0–4% (Clean)
🟠 Orange → 5–14% (Suspicious)
🔴 Red → 15%+ (Malicious)

The Stack

  • Streamlit — web UI with zero frontend code
  • Folium — interactive map rendering on a CartoDB dark basemap
  • VirusTotal API — aggregates 90+ security vendor votes per IP
  • ipinfo.io — HTTPS geolocation
  • pandas — data handling and CSV export

What I Learned

1. Never hardcode API keys

This seems obvious but it's easy to slip up when prototyping. The fix is simple — use environment variables:

VT_API_KEY = os.environ.get("VT_API_KEY")
Enter fullscreen mode Exit fullscreen mode

And on Mac, make it permanent:

echo 'export VT_API_KEY="your_key_here"' >> ~/.zshrc
source ~/.zshrc
Enter fullscreen mode Exit fullscreen mode

2. HTTP geolocation is a MITM risk

The original version used http://ip-api.com — plain HTTP. On a cloud server, that traffic is unencrypted and could be intercepted and spoofed. I switched to https://ipinfo.io which supports HTTPS on the free tier.

3. Rate limiting matters

VirusTotal's free tier allows 500 requests/day. With a thread pool and a 1.4s delay between requests, the app stays well within limits without blocking the UI.

RATE_LIMIT_DELAY = 1.4
MAX_WORKERS = 2
Enter fullscreen mode Exit fullscreen mode

4. Input validation before hitting any API

Users can paste anything into a text box. A simple regex check protects all downstream API calls:

def is_valid_ip(ip: str) -> bool:
    pattern = r"^(\d{1,3}\.){3}\d{1,3}$"
    if not re.match(pattern, ip):
        return False
    return all(0 <= int(octet) <= 255 for octet in ip.split("."))
Enter fullscreen mode Exit fullscreen mode

5. VirusTotal scores differently to AbuseIPDB

AbuseIPDB gives a single confidence score out of 100. VirusTotal gives votes from 90+ vendors. To convert to a 0–100 scale I calculate the percentage of vendors that flagged it:

stats = resp.json()["data"]["attributes"]["last_analysis_stats"]
malicious  = stats.get("malicious", 0)
suspicious = stats.get("suspicious", 0)
total      = sum(stats.values())
return round(((malicious + suspicious) / total) * 100)
Enter fullscreen mode Exit fullscreen mode

Try It Yourself

The full source code is on GitHub: [YOUR GITHUB LINK]

Clone it, set your VirusTotal API key and run:

git clone git clone https://github.com/shynsec/breadcrumb-engine.git
cd breadcrumb-engine
pip install -r requirements.txt
export VT_API_KEY="your_key_here"
streamlit run app.py
Enter fullscreen mode Exit fullscreen mode

Feedback and contributions welcome. What features would you add next?

Top comments (0)