Spot a new incident? Find a fact wrong? Have a playbook to add? All welcome.

Fastest path: open an issue

If you saw something live and don't have time to write it up properly, just open an issue with: - Link(s) to the source(s). - Affected package / tool / MCP. - Approximate dates. - Severity guess.

Use the New advisory or Update advisory template — they show up in the issue list when you click "New issue."

To submit a full advisory PR

  1. Fork + clone.
  2. Copy the template below into advisories/YYYY-MM-<short-id>.md.
  3. Add an entry to advisories/README.md and ALERTS.md (latest on top).
  4. Open a PR. Include the sources you used in the PR body.

Advisory template

---
id: YYYY-MM-short-id
title: "Short human title (Month Year)"
date_disclosed: YYYY-MM-DD
last_updated: YYYY-MM-DD
severity: critical | high | medium
status: active | contained | patched | mitigated | ongoing | historical
ecosystems: [npm | pypi | mcp | cursor | claude-code | ...]
tools_affected: [list of tools/projects that should care]
tags: [supply-chain, credential-theft, prompt-injection, ...]
---

## TL;DR
Two sentences. A vibe coder should grok it in 5 seconds.

## What happened
Plain-language description. Cite sources inline as you go.

## Am I affected?
Concrete checks. Bash commands. Lockfile greps. Hashes. Whatever lets a reader answer "yes/no" in under 60 seconds.

## If you are affected
Link to relevant playbook(s).

## Prevention
Link to relevant prevention doc(s).

## Sources
- [Title](https://url) — what this source contributed.

Malicious-artifact advisories

Use this shape for anything a reader could install that is malicious or compromised: packages, extensions, MCP servers, skills, workflows and repositories, including worms, stealers and credential-theft campaigns that ship as one. The reader needs to know what not to install and what to do if they already did. How the code steals, spreads or hides is in the researcher's write-up. Link that write-up and do not restate it.

---
id: YYYY-MM-short-id
title: "Malicious <name> <ecosystem> packages: remove and rotate <credential category>"
kind: malicious-artifact
date_disclosed: YYYY-MM-DD
last_updated: YYYY-MM-DD
severity: critical | high | medium
status: active | contained | patched | mitigated | historical | unconfirmed
ecosystems: [npm | pypi | vscode | mcp | github-actions | ...]
tools_affected: [list of tools/projects that should care]
tags: [supply-chain, malicious-package, ...]
---

## TL;DR
Two sentences: what to remove or block, and what to rotate if it ran.

## Packages and versions

| Ecosystem | Name | Bad versions | Clean version or action | Registry state (date checked) | Record |
|---|---|---|---|---|---|
| npm | `example-pkg` | 1.2.3, 1.2.4 | remove; no clean release | removed (YYYY-MM-DD) | MAL-YYYY-NNNN |

## Am I affected?
Lockfile greps, installed-package checks, and the file paths the artifact leaves.

## If you are affected
Credential categories to rotate, files to delete, and the playbook link.

## Prevention
Link to relevant prevention doc(s).

## Sources

Use these sections and no others. The TL;DR does not describe behaviour. Never include payload code, encoded strings, or live download, C2, onion, IP or wallet addresses.

Playbook template

Use this for new entries in playbooks/. Pattern:

# If [scenario]

> Scope: one-line scope statement.

## Do this first (60 seconds)
Most-urgent action(s), as commands.

## Triage
What could the attacker have done? How to confirm the blast radius?

## Rotate
Step-by-step credential rotation, in priority order.

## Verify
Confirm the rotation took effect and look for residual compromise.

## Prevention going forward
Link to prevention doc.

Prevention doc template

# [Topic]

> One-line statement of the goal.

## Why this matters
The threat model. Concrete incidents that this would have prevented.

## What to do
Numbered list of concrete actions. Commands where possible.

## What this stops / doesn't stop
Honest list of the trade-offs.

Accuracy & citation standards

A wrong-but-confident advisory is worse than none — readers act on it. These are hard requirements, enforced in CI where possible:

  • Cite only what you actually opened. Every URL in ## Sources must be a page you read. Never guess an article slug, CVE/GHSA id, version, or download count — paste the real one. (Automated sweeps have shipped invented URLs and a malformed GHSA-langgraph-27794; don't.)
  • Identifiers must be canonical and well-formed: CVE-YYYY-NNNN (with the year, ≥4-digit sequence) and GHSA-xxxx-xxxx-xxxx (4-4-4). A malformed id is almost always fabricated. tests/test_advisory_ids.py fails the build on malformed ids.
  • Verify before you state. Confirm a CVE/GHSA on NVD or the GitHub Advisory Database; confirm a package/version resolves (npm view / pip index versions); take counts and blast-radius numbers from a primary source, not an aggregator's paraphrase.
  • Check your links before opening a PR: python tools/check-external-links.py advisories/<your-file>.md flags 404s and whether a Wayback snapshot exists. 404 + no snapshot = the URL never existed → fix or drop it. Never link a malware/IOC/C2 domain.
  • Internal links must point to docs that exist. Link only real files under playbooks/ and prevention/ (run ls to check). site/validate.py fails the build on broken internal links.

CVE evidence

For a CVE-to-finding table, use the CNA's exact finding reference and read the referenced revision. Do not infer identity from equal scores or similar descriptions. Attribute scores to their actual provider, and keep registry claims separate from demonstrated impact. NVD, GitHub and OSV mirrors are not independent confirmation. A reviewed affected endpoint is not a fix boundary.

ID-first F-<number> tables require saved registry snapshots and a manifest. Run python tools/validate_cve_evidence.py --live before publication, then the normal build gate. Review drift or fetch failures explicitly; never silently reuse old evidence as fresh. See the evidence workflow and its limits. Severity remains an editorial decision supported by evidence, not an automatic maximum of external scores.

Style notes

  • Date everything. Format: YYYY-MM-DD. Update last_updated in frontmatter when you touch an advisory. Stamp volatile facts (EPSS/KEV, "as of" counts) with their date.
  • Cite multiple sources when possible. At least two independent reporters before promoting to a full advisory; a single-source claim is status: unconfirmed.
  • Concrete > abstract. Always include a command, a path, or a config snippet when relevant.
  • Distinguish “downloaded” from “ran.” A package name, version or file checksum tells you what is present. A matching filename, running program or startup job may be unrelated. Explain how to compare findings with the publisher's specific evidence before saying harmful code ran. Missing leftover files do not rule out earlier activity. Tie cleanup advice to what the reader actually found.
  • Write for someone who is not a security specialist. Prefer “the harmful code ran” to “payload execution” and “changes that survive a restart” to “persistence.” Explain necessary terms on first use, such as “rotate credentials” (replace passwords, keys and login tokens). Keep exact package names and commands so readers and their agents can still check them.
  • No FUD. Severity claims need to be defensible. If only 1,000 people downloaded the package before takedown, say so.
  • Short. Vibe coders are panicking. Hit the bullet points and link out for depth.
  • Run the build before a PR: python site/build.py && python site/validate.py && python -m pytest tests/ — the same gate the deploy runs. A red gate blocks the deploy and freezes the live site.

Out-of-scope contributions

We're not the right home for: - General npm/PyPI CVE listings unrelated to AI coding tools. - Generic "how to do AppSec" content — there are 100 better resources. - Vendor marketing (please). - Speculation without sources. - Write-ups of attackers using AI tools against third parties that name nothing a reader could install.

When in doubt, open an issue and ask before doing the work.

License

By contributing, you agree your work is released under CC0 (effectively public domain). No attribution required.