Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use AI and LLM-based reasoning to correlate findings across multiple OSINT sources—username enumeration, email lookups, social media profiles, domain records, breach databases, and dark-web mentions—into unified intelligence profiles with confidence scoring and link analysis.
.claude/skills/performing-ai-driven-osint-correlation/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 184% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 90% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 274% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 99% | 0% |
requests, json, and csv librariespip install sherlock-project)pip install theHarvester)bash mkdir -p /tmp/osint
bash sherlock "targetusername" --output /tmp/osint/sherlock-results.txt --csv
bash theHarvester -d targetdomain.com -b all -f /tmp/osint/harvester-results.json
bash curl -s http://localhost:5001/api/scan/start \ -d "scanname=target-recon&scantarget=targetdomain.com&usecase=passive" \ | jq '.scanid'
bash SCAN_ID="<scanid_from_step_3>" curl -s "http://localhost:5001/api/scan/${SCAN_ID}/results?type=all" \ -o /tmp/osint/spiderfoot-results.json
bash curl -s -H "hibp-api-key: ${HIBP_KEY}" \ -H "User-Agent: OSINT-Correlation-Skill" \ "https://haveibeenpwned.com/api/v3/breachedaccount/target@example.com" \ -o /tmp/osint/breach-results.json
bash cat > /tmp/osint/normalize.py << 'EOF' import json, csv, sys, os from datetime import datetime
findings = ]
# Normalize Sherlock CSV results sherlock_path = "/tmp/osint/sherlock-results.txt" if os.path.exists(sherlock_path): with open(sherlock_path) as f: for row in csv.DictReader(f): findings.append({ "source": "sherlock", "type": "social_profile", "platform": row.get("name", ""), "url": row.get("url_user", ""), "username": row.get("username", ""), "status": row.get("status", ""), "collected_at": datetime.utcnow().isoformat() })
# Normalize theHarvester JSON results harvester_path = "/tmp/osint/harvester-results.json" if os.path.exists(harvester_path): with open(harvester_path) as f: data = json.load(f) for email in data.get("emails", ]): findings.append({ "source": "theHarvester", "type": "email", "value": email, "collected_at": datetime.utcnow().isoformat() }) for host in data.get("hosts", ]): findings.append({ "source": "theHarvester", "type": "hostname", "value": host, "collected_at": datetime.utcnow().isoformat() })
# Normalize SpiderFoot results sf_path = "/tmp/osint/spiderfoot-results.json" if os.path.exists(sf_path): with open(sf_path) as f: for item in json.load(f): findings.append({ "source": "spiderfoot", "type": item.get("type", "unknown"), "value": item.get("data", ""), "module": item.get("module", ""), "collected_at": datetime.utcnow().isoformat() })
with open("/tmp/osint/normalized-findings.json", "w") as f: json.dump(findings, f, indent=2)
print(f"Normalized {len(findings)} findings from {len(set(f'source'] for f in findings))} sources") EOF python3 /tmp/osint/normalize.py
bash cat > /tmp/osint/correlate.py << 'PYEOF' import json, os from openai import OpenAI # or anthropic, ollama, etc.
client = OpenAI(api_key=os.environ"OPENAI_API_KEY"])
with open("/tmp/osint/normalized-findings.json") as f: findings = json.load(f)
correlation_prompt = f"""You are an OSINT analyst. Analyze these findings collected from multiple sources and produce a correlation report.
For each identity or entity you detect:
Raw findings: {json.dumps(findings:500], indent=2)} """
response = client.chat.completions.create( model="gpt-4o", messages= {"role": "system", "content": "You are an expert OSINT analyst specializing in identity correlation and link analysis."}, {"role": "user", "content": correlation_prompt} ], temperature=0.1, response_format={"type": "json_object"} )
report = json.loads(response.choices0].message.content)
with open("/tmp/osint/correlation-report.json", "w") as f: json.dump(report, f, indent=2)
print(json.dumps(report, indent=2)) PYEOF python3 /tmp/osint/correlate.py
bash cat > /tmp/osint/resolve.py << 'PYEOF' import json
with open("/tmp/osint/correlation-report.json") as f: report = json.load(f)
# Extract entities and build a link graph entities = report.get("entities", ]) print(f"Identified {len(entities)} distinct entities") for entity in entities: name = entity.get("identifier", "unknown") confidence = entity.get("confidence", 0) links = entity.get("linked_accounts", ]) risk = entity.get("risk_level", "unknown") print(f" {confidence:.0%}] {name} — {len(links)} linked accounts — risk: {risk}") PYEOF python3 /tmp/osint/resolve.py
bash cat > /tmp/osint/report.py << 'PYEOF' import json from datetime import datetime
with open("/tmp/osint/correlation-report.json") as f: report = json.load(f)
md = f"# OSINT Correlation Report\n\n" md += f"Generated: {datetime.utcnow().isoformat()}Z\n\n" md += "## Entity Profiles\n\n"
for entity in report.get("entities", ]): eid = entity.get("identifier", "Unknown") conf = entity.get("confidence", 0) md += f"### {eid} (Confidence: {conf:.0%})\n\n" md += "| Source | Platform | Evidence |\n|--------|----------|----------|\n" for link in entity.get("linked_accounts", ]): md += f"| {link.get('source','')} | {link.get('platform','')} | {link.get('evidence','')} |\n" md += f"\nRisk Level: {entity.get('risk_level', 'N/A')}\n\n" for flag in entity.get("flags", ]): md += f"- ⚠️ {flag}\n" md += "\n"
with open("/tmp/osint/intelligence-profile.md", "w") as f: f.write(md)
print("Report written to /tmp/osint/intelligence-profile.md") PYEOF python3 /tmp/osint/report.py
bash # Export entities as Maltego-compatible CSV for manual import cat > /tmp/osint/maltego_export.py << 'PYEOF' import json, csv
with open("/tmp/osint/correlation-report.json") as f: report = json.load(f)
with open("/tmp/osint/maltego-import.csv", "w", newline="") as f: writer = csv.writer(f) writer.writerow("Entity Type", "Value", "Linked To", "Link Label", "Confidence"]) for entity in report.get("entities", ]): for link in entity.get("linked_accounts", ]): writer.writerow( link.get("type", "Alias"), link.get("value", ""), entity.get("identifier", ""), link.get("evidence", ""), link.get("confidence", "") ])
print("Maltego CSV exported to /tmp/osint/maltego-import.csv") PYEOF python3 /tmp/osint/maltego_export.py
| Concept | Description | |---------|-------------| | Cross-Source Correlation | Matching identifiers (usernames, emails, IPs) across independent OSINT sources to establish entity linkage | | Confidence Scoring | Assigning probabilistic confidence (0.0–1.0) to each linkage based on evidence strength and corroboration | | Entity Resolution | Deduplicating and merging records that refer to the same real-world entity across fragmented datasets | | False Positive Detection | Using AI reasoning to identify coincidental matches versus genuine identity links | | Multi-Vector Intelligence | Combining findings from social media, DNS, breach data, and infrastructure into a single threat picture | | Link Analysis | Graph-based examination of relationships between entities, accounts, and infrastructure |
| Tool | Role in Workflow | |------|-----------------| | Sherlock | Username enumeration across 400+ social platforms | | theHarvester | Email, subdomain, and host discovery from public sources | | SpiderFoot | Automated OSINT collection across 200+ modules | | Maltego | Graph-based visualization of entity relationships | | LLM API (GPT-4, Claude, Ollama) | Cross-source reasoning, pattern detection, and confidence scoring | | HaveIBeenPwned | Breach exposure and credential leak detection |
The final output is a structured JSON correlation report and a Markdown intelligence profile containing:
json{ "meta": { "target": "targetdomain.com", "sources_used": ["sherlock", "theHarvester", "spiderfoot", "hibp"], "total_findings": 247, "generated_at": "2025-01-15T14:30:00Z" }, "entities": [ { "identifier": "john.target", "confidence": 0.92, "linked_accounts": [ { "source": "sherlock", "platform": "GitHub", "value": "john.target", "evidence": "Exact username match, bio references targetdomain.com", "confidence": 0.95 } ], "risk_level": "high", "flags": [ "Credentials exposed in 2 breaches (2022, 2023)", "Admin email for targetdomain.com found in public WHOIS" ] } ], "contradictions": [], "recommendations": [] }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 17,422 | 19,550 | +12% | 1 | 1 | 0% | 2,040 | 6,260 | +207% | 0 | 0 | — |
case-02 | fail→fail | 20,333 | 16,420 | -19% | 1 | 1 | 0% | 2,219 | 5,832 | +163% | 0 | 0 | — |
case-03 | fail→pass | 14,782 | 16,974 | +15% | 1 | 1 | 0% | 2,625 | 7,462 | +184% | 0 | 0 | — |
case-04 | fail→fail | 7,245 | 7,195 | -1% | 1 | 1 | 0% | 584 | 3,989 | +583% | 0 | 0 | — |
case-05 | fail→fail | 8,674 | 11,909 | +37% | 1 | 1 | 0% | 417 | 4,511 | +982% | 0 | 0 | — |
case-06 | fail→fail | 18,868 | 21,030 | +11% | 1 | 1 | 0% | 3,587 | 8,126 | +127% | 0 | 0 | — |
case-07 | fail→pass | 13,409 | 3,829 | -71% | 1 | 1 | 0% | 2,226 | 4,221 | +90% | 0 | 0 | — |
case-08 | fail→fail | 3,084 | 2,528 | -18% | 1 | 1 | 0% | 506 | 3,937 | +678% | 0 | 0 | — |
case-09 | fail→fail | 3,507 | 2,108 | -40% | 1 | 1 | 0% | 547 | 3,911 | +615% | 0 | 0 | — |
case-10 | fail→pass | 7,725 | 1,638 | -79% | 1 | 1 | 0% | 1,037 | 3,881 | +274% | 0 | 0 | — |
case-11 | fail→pass | 9,266 | 2,290 | -75% | 1 | 1 | 0% | 1,705 | 3,947 | +131% | 0 | 0 | — |
case-12 | fail→fail | 3,665 | 2,710 | -26% | 1 | 1 | 0% | 589 | 4,086 | +594% | 0 | 0 | — |
case-13 | fail→fail | 9,622 | 2,328 | -76% | 1 | 1 | 0% | 1,753 | 3,935 | +124% | 0 | 0 | — |
case-14 | fail→fail | 10,700 | 2,703 | -75% | 1 | 1 | 0% | 1,971 | 4,010 | +103% | 0 | 0 | — |
case-15 | fail→fail | 8,455 | 3,448 | -59% | 1 | 1 | 0% | 1,578 | 3,951 | +150% | 0 | 0 | — |
case-16 | pass→pass | 9,274 | 2,111 | -77% | 1 | 1 | 0% | 1,550 | 3,888 | +151% | 0 | 0 | — |
case-17 | fail→pass | 11,021 | 1,731 | -84% | 1 | 1 | 0% | 1,940 | 3,855 | +99% | 0 | 0 | — |
case-18 | fail→pass | 7,481 | 2,553 | -66% | 1 | 1 | 0% | 1,333 | 4,070 | +205% | 0 | 0 | — |
case-19 | fail→pass | 9,097 | 2,474 | -73% | 1 | 1 | 0% | 1,600 | 3,981 | +149% | 0 | 0 | — |
case-20 | fail→fail | 13,854 | 6,459 | -53% | 1 | 1 | 0% | 2,426 | 4,862 | +100% | 0 | 0 | — |
case-21 | fail→pass | 12,562 | 6,567 | -48% | 1 | 1 | 0% | 2,066 | 4,797 | +132% | 0 | 0 | — |
case-22 | fail→fail | 12,342 | 9,781 | -21% | 1 | 1 | 0% | 2,149 | 5,171 | +141% | 0 | 0 | — |
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. 22 cases were attempted. The headline lift of +36 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.