Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Dark web monitoring involves systematically scanning Tor hidden services, underground forums, paste sites, and dark web marketplaces to identify threats targeting an organization, including leaked cre
.claude/skills/performing-dark-web-monitoring-for-threats/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-15 | ✗→✓ | ▲ Improved | — | — |
| case-11 | ✗→✓ | ▲ Improved | — | — |
| case-09 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-05 | ✓→✓ | = Same ✓ | — | — |
Dark web monitoring involves systematically scanning Tor hidden services, underground forums, paste sites, and dark web marketplaces to identify threats targeting an organization, including leaked credentials, data breaches, threat actor discussions, vulnerability exploitation tools, and planned attacks. This skill covers setting up monitoring infrastructure, using Tor-based collection tools, implementing automated alerting for brand mentions and credential leaks, and analyzing dark web intelligence for actionable threat indicators.
requests, stem, beautifulsoup4, stix2 librariespythonimport requests from requests.adapters import HTTPAdapter def create_tor_session(): """Create a requests session routed through Tor SOCKS5 proxy.""" session = requests.Session() session.proxies = { "http": "socks5h://127.0.0.1:9050", "https": "socks5h://127.0.0.1:9050", } session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0", }) return session def verify_tor_connection(session): """Verify that traffic is routed through Tor.""" try: resp = session.get("https://check.torproject.org/api/ip", timeout=30) data = resp.json() return { "is_tor": data.get("IsTor", False), "ip": data.get("IP", ""), } except Exception as e: return {"error": str(e)}
pythonimport re from datetime import datetime def monitor_paste_sites(session, organization_domains): """Monitor paste sites for leaked credentials matching organization domains.""" findings = [] # Check Have I Been Pwned API (clearnet) for domain in organization_domains: try: resp = requests.get( f"https://haveibeenpwned.com/api/v3/breaches", headers={"hibp-api-key": "YOUR_HIBP_KEY"}, timeout=30, ) if resp.status_code == 200: breaches = resp.json() for breach in breaches: if domain.lower() in breach.get("Domain", "").lower(): findings.append({ "source": "HIBP", "breach_name": breach["Name"], "breach_date": breach.get("BreachDate"), "data_classes": breach.get("DataClasses", []), "pwn_count": breach.get("PwnCount", 0), "domain": domain, }) except Exception as e: print(f"[-] HIBP error for {domain}: {e}") return findings def search_for_keywords(session, keywords, onion_paste_urls): """Search dark web paste sites for specific keywords.""" results = [] for paste_url in onion_paste_urls: try: resp = session.get(paste_url, timeout=60) if resp.status_code == 200: content = resp.text.lower() for keyword in keywords: if keyword.lower() in content: results.append({ "url": paste_url, "keyword": keyword, "timestamp": datetime.utcnow().isoformat(), "snippet": extract_context(content, keyword.lower()), }) except Exception as e: print(f"[-] Error fetching {paste_url}: {e}") return results def extract_context(text, keyword, context_chars=200): """Extract text context around a keyword match.""" idx = text.find(keyword) if idx == -1: return "" start = max(0, idx - context_chars) end = min(len(text), idx + len(keyword) + context_chars) return text[start:end]
pythondef check_ransomware_leak_sites(session, organization_name): """Check known ransomware group leak sites for organization mentions.""" # Use Ransomwatch API (clearnet aggregator of ransomware leak sites) try: resp = requests.get( "https://raw.githubusercontent.com/joshhighet/ransomwatch/main/posts.json", timeout=30, ) if resp.status_code == 200: posts = resp.json() matches = [] for post in posts: post_title = post.get("post_title", "").lower() if organization_name.lower() in post_title: matches.append({ "group": post.get("group_name", ""), "title": post.get("post_title", ""), "discovered": post.get("discovered", ""), "url": post.get("post_url", ""), }) return matches except Exception as e: print(f"[-] Ransomwatch error: {e}") return []
pythondef generate_dark_web_report(findings, organization): """Generate structured dark web intelligence report.""" report = { "organization": organization, "report_date": datetime.utcnow().isoformat(), "executive_summary": "", "credential_leaks": [], "ransomware_mentions": [], "dark_web_mentions": [], "recommendations": [], } for finding in findings: if finding.get("source") == "HIBP": report["credential_leaks"].append(finding) elif finding.get("group"): report["ransomware_mentions"].append(finding) else: report["dark_web_mentions"].append(finding) # Generate executive summary cred_count = len(report["credential_leaks"]) ransom_count = len(report["ransomware_mentions"]) report["executive_summary"] = ( f"Monitoring identified {cred_count} credential leak sources " f"and {ransom_count} ransomware group mentions for {organization}." ) if ransom_count > 0: report["recommendations"].append( "CRITICAL: Organization mentioned on ransomware leak site. " "Initiate incident response immediately." ) if cred_count > 0: report["recommendations"].append( "HIGH: Leaked credentials detected. Force password resets for " "affected accounts and enable MFA." ) return report
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-23 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.