API Reference

Get a Supply-Chain Incident

Fetch the full record for a single supply-chain incident, including the long-form description, impact and recommendation lists, references, attribution, and the list of affected packages.

GET
/v1/supply-chain/incidents/{id}

Cost: 1 credit per successful call

Path parameters

idstringrequired

The incident identifier, as returned by GET /v1/supply-chain/incidents. A slug-like token matching ^[A-Za-z0-9._-]{1,200}$ (letters, digits, dot, underscore, hyphen; 1 to 200 characters).

Request

curl https://api.precursorintelligence.com/functions/v1/supply-chain/incidents/npm-2026-06-17-mastra-easy-day-js \
  -H "Authorization: Bearer $PRECURSOR_API_KEY"

Response

200 OK
{
  "data": {
    "id": "npm-2026-06-17-mastra-easy-day-js",
    "title": "Mastra AI npm scope takeover via `easy-day-js` typosquat dropper",
    "summary": "A dormant contributor account, never revoked from the @mastra scope, was used to mass-publish ~144 trojanised @mastra/* releases, each declaring a new easy-day-js dependency whose postinstall hook drops a cross-platform crypto-wallet stealer / RAT.",
    "severity": "critical",
    "published": "2026-06-17",
    "last_updated": "2026-06-18",
    "reference": "https://socket.dev/blog/mastra-npm-packages-compromised",
    "impact": [
      "Cryptocurrency wallet theft: 160+ browser-extension wallets drained on install",
      "Cross-platform infostealer + RAT with Windows/macOS/Linux persistence",
      "CI/CD runner compromise: postinstall runs automatically during npm install"
    ],
    "recommendation": [
      "Run `npm ls easy-day-js` in every project and CI runner — any match indicates execution of the dropper",
      "Treat any host that installed an affected @mastra/* version on or after 2026-06-17 01:12 UTC as compromised; rebuild from a known-good image",
      "Rotate browser-extension wallet seed phrases, npm tokens, cloud credentials, and any SSH/Git keys accessible from the affected machine"
    ],
    "description": "Between 01:12 and 02:36 UTC on 2026-06-17, an attacker logged into the dormant npm account `ehindero` — a legitimate former Mastra contributor whose owner permissions on the @mastra scope had never been revoked — and mass-published trojanised versions of ~144 packages across the namespace...",
    "references_json": [
      {
        "url": "https://socket.dev/blog/mastra-npm-packages-compromised",
        "title": "140+ Mastra npm Packages Compromised in Coordinated Supply Chain Attack",
        "publisher": "Socket"
      },
      {
        "url": "https://research.jfrog.com/post/easy-day-js/",
        "title": "easy-day-js: Supply Chain Campaign Targets Mastra npm Packages",
        "publisher": "JFrog"
      }
    ],
    "tags": ["account-takeover", "typosquat", "infostealer", "crypto-wallet-drain"],
    "threat_actor": null,
    "aliases": ["easy-day-js campaign", "Mastra scope takeover"],
    "detected_by": ["Socket", "JFrog", "Snyk", "StepSecurity", "Mend"],
    "affected_packages": [
      {
        "ecosystem": "npm",
        "package_name": "@mastra/core",
        "affected_versions": ["1.41.0", "1.41.1"]
      },
      {
        "ecosystem": "npm",
        "package_name": "easy-day-js",
        "affected_versions": ["1.11.22"]
      }
    ]
  },
  "meta": {
    "request_id": "8b16efb8-9a6c-4ace-b817-11cbee626d08",
    "generated_at": "2026-05-18T10:24:31.118Z",
    "credits": { "charged": 1, "remaining": 9998 }
  }
}

Response fields

data.idstringoptional

The stable slug-like identifier for the incident.

data.titlestringoptional

Short human-readable incident title.

data.summarystringoptional

One-paragraph summary of the incident.

data.severitystringoptional

Incident severity: low, medium, high, or critical.

data.publishedstringoptional

ISO 8601 date (YYYY-MM-DD) the incident was first published.

data.last_updatedstring | nulloptional

ISO 8601 date of the most recent update, or null if never updated.

data.referencestringoptional

Primary reference URL for the incident.

data.impactarray | nulloptional

Bullet list of strings describing the impact of the incident. May be null.

data.recommendationarray | nulloptional

Bullet list of strings with recommended remediation actions. May be null.

data.descriptionstringoptional

Long-form description of the incident.

data.references_jsonarrayoptional

Structured reference list. Each element contains url, title, and publisher.

data.tagsarrayoptional

String tags categorising the incident.

data.threat_actorstring | nulloptional

Attributed threat actor, or null when unattributed.

data.aliasesarray | nulloptional

Alternative names the incident is tracked under, or null.

data.detected_byarray | nulloptional

Vendors and researchers that detected or disclosed the incident, or null.

data.affected_packagesarrayoptional

The packages affected by the incident. Each element contains ecosystem (e.g. npm, pypi, crates, docker, github-actions), package_name, and affected_versions (an array of version strings, which may be empty when specific versions were not enumerated).

Errors

StatuserrorWhen
400invalid_idThe path segment did not match ^[A-Za-z0-9._-]{1,200}$.
401invalid_authorizationThe Authorization header is missing or malformed.
401unauthorizedThe key is invalid, revoked, or the request IP is not on the allowlist.
402insufficient_creditsThe organisation's credit balance is below 1.
404not_foundThe identifier is valid but no incident with that id exists.
405method_not_allowedOnly GET and OPTIONS are accepted.
500internalAn unexpected server error occurred.

See Errors for the full error reference.