An open, source-linked dataset of real-world cyberattacks executed or orchestrated by AI agents, plus notable offensive/agentic-AI incidents. This repository is the data layer behind the Rogue Agent Watch tracker, published by MLSecOpsHub.
The product is trust: every factual field in every record is backed by a cited, resolvable source. Accuracy and provenance matter more than volume or speed.
Defenders, researchers, journalists, and policymakers who need a grounded, citable record of how AI agents are being used in real attacks — with honest grading of what is confirmed, reported, or lab-only.
| Path | What it is |
|---|---|
data/incidents/<id>.yml |
One record per incident — the source of truth |
schema/incident.schema.json |
Canonical JSON Schema (draft 2020-12) — authoritative |
taxonomy/*.yml |
Controlled vocabularies (categories, actor types, severities, …) |
dist/ |
Generated JSON artifacts — never hand-edited |
Each record carries a stable id (its permanent citation key), a lifecycle-level defensive summary, verification status (confirmed / reported / test-eval), sourcing confidence (primary / secondary / unverified), and at least one resolvable source.
Records also carry an analytical layer for defenders: an agentic autonomy_level, a guardrail_bypass classification (how safety controls were circumvented), an ai_role skepticism axis (how central AI actually was, independent of status), MITRE ATLAS / ATT&CK mappings (ATLAS techniques in mappings.mitre_atlas, checked against the ATLAS release in schema/mitre-atlas.json and chosen by the method in docs/atlas-mapping.md; ATLAS case studies that document the incident in mappings.mitre_atlas_case_studies), OWASP references, related[] links between records from the same report or campaign, and mitigations. dist/summary.json rolls these up (by category, severity, status, actor type, autonomy level, AI role, model family, and year) and publishes the dataset's headline honesty figure, evidence_split: how many records are both status: confirmed and ai_role: load-bearing. Consumers must read that figure rather than recompute it, so every surface quotes the same number.
Map points (geo.points[], schema 0.3.0). A record carries map points only where a cited source states a location. Every point has a role (origin / target), an explicit basis saying why it exists (sponsor-attribution, operator-location, actor-location, infrastructure, victim-location, stated-location; see taxonomy/geo-basis.yml), the publisher that stated it (attributed_by, always one of the record's sources), an ISO country, and illustrative: true for any centroid. A state sponsor is not an operator location, and targets.countries is never turned into points. Consumers must read geo.points[]; the pre-0.3.0 geo.target / geo.origin slots are gone.
npm ci
npm run build # writes the dist/ artifacts belownpm run build emits, deterministically:
| Artifact | Format |
|---|---|
dist/incidents.json |
full dataset (array) |
dist/incidents.ndjson |
newline-delimited JSON (streaming) |
dist/incidents.csv |
flattened columns for spreadsheets (map points as geo_points = role:basis:country; mitre_atlas_case_studies is the last column) |
dist/incidents/<id>.json |
one file per incident (stable per-record URL) |
dist/summary.json |
dataset_version + unreleased_changes (true when main is ahead of that tagged release) + counts + rollups (category, severity, status, actor type, autonomy level, AI role, model family, year) + archive_coverage + geo_coverage (points by role and basis) + evidence_split (records that are both confirmed and load-bearing, overall and by year, plus a status × AI-role crosstab; retracted/superseded excluded) |
dist/stix/bundle.json |
STIX 2.1 bundle (reports + ATLAS/ATT&CK attack-patterns + CVE vulnerabilities) for TIP/MISP ingestion |
dist/index.html |
landing page (served via GitHub Pages) |
Or consume dist/incidents.json directly. Data is licensed CC BY-SA 4.0; tooling is MIT. Cite via CITATION.cff; see CHANGELOG.md for dataset changes.
npm run validate # schema + taxonomy + id + editorial + map-point checks (no network)
npm run build # deterministic dist/ build
npm run linkcheck # verify every source URL resolves, falling back to archive_url (network)
npm run archive # propose Wayback snapshots for sources (add --write to save them)
npm test # validate + build — CI gate
npm run new:incident -- <id> "Name" # scaffold a record from the templateSource citations are protected against link rot: each source can carry an archive_url
(a Wayback snapshot, populated by npm run archive). linkcheck treats a source as
healthy when either its live URL or its archive snapshot resolves, and only fails when
both are unreachable.
See CONTRIBUTING.md. The short version: one incident per PR, every fact sourced, npm test green. No exploit code, payloads, or offensive how-tos — ever.
- Only already-public incidents are cataloged, linking the disclosing party.
- Victim organizations are named only when a first-party or public disclosure already named them.
Unknownis a valid actor; attribution never goes beyond what sources state.- Incidents are described at attack-lifecycle level. This is a defensive dataset.
- Code (schema, scripts, docs): MIT
- Data (
data/,taxonomy/,dist/): CC BY-SA 4.0