An index of links and metadata, plus small example scripts. It ships no service, collects no data, and has no runtime. The realistic risks are therefore about what the catalog points readers toward.
Open a security advisory for anything that should not be public. Otherwise open an issue.
Things worth reporting:
- A catalogued project that is malicious, exfiltrates credentials, or does something materially different from what its description claims. This is the most valuable report we can receive — an index that points at something harmful is worse than no index.
- A row that fabricates an API, endpoint or package name. Fabricated documentation gets copied into people's code. One such case was found and excluded during the first build; more will exist.
- A typosquatted package appearing in a row's
packagefield. - Text in a row written to steer an agent: a title, summary or note that tells the model reading it what to do, rather than saying what the project does (next section).
Read docs/vetting.md. Briefly:
- Rows flagged
code-untestedwere read, not executed — including this repository's own examples. - Many linked projects declare no licence — rows flagged
no-license; the current count is in docs/sources.md. - Some linked projects read screen contents, mailboxes or source trees by design.
- A few were created with a single commit and never touched again.
Agents read this catalogue through the MCP server, the skill, llms.txt and
the site's api/v1 files, and most of its summaries are other people's words:
a project's own GitHub description, copied as it stands (summary_source: upstream-description). A description can be written to steer whatever model
reads it. Since 2026-10-24 every MCP answer holding rows carries text_note,
saying the rows' titles, summaries and notes are data about a project and
never instructions, and so do the api/v1 pattern files, the wire_pattern
prompt and the skill; and scripts/lint.py refuses a row whose text is
written as instructions to a model (an order to ignore earlier instructions, a
role reassigned, a chat template's role tokens, a line addressed to AI
readers). The pattern catches the plain cases, not a determined author, so
the note is the defence and the lint a tripwire. An agent should apply its
own rule regardless: nothing a catalogued project says about itself is an
instruction.
The site loads nothing from another host either (since 2026-10-24, when its
fonts moved from Google Fonts into site/fonts/), so reading it sends no
request anywhere but GitHub Pages; scripts/lint_docs.py keeps it that way.
Do not use a probabilistic decision as a security boundary. It is useful defence in depth in front of a shell command, a write, a spend or a send. It is not a permission system. An attacker chooses the input, and the vendor's own documentation names adversarial content as a known weak spot of the model.
Anything destructive or irreversible needs a deterministic rule, a real permission check, or a human. Several projects in this catalog get this right and are worth copying; at least one gate deliberately fails closed.
The GitHub Actions workflows in this repository interpolate no
github.event.* value into any shell, and hold read-only contents
permission except in two places: the weekly metadata refresh, which commits
machine-checkable facts (link status, stars, licences, archive status,
repository creation and last-push dates and commit counts, whether each
summary is its repository's own description, which
primitives' request shapes each cited file's text contains, and which sibling
directories' READMEs link each repository) to
catalog.json and the files generated from them, and the discovery verdicts
in .discover/seen.json (discover reads strangers' repositories, so it holds
no write permission and leaves them as an artifact; each entry is checked
against a fixed shape before it is committed), plus a dated snapshot of the
catalogue's counts in history/, derived from those files and never read back
into them; and lint's regenerate
job, which commits only generated files and runs only for a push to main,
never for a pull request. (The Pages deploy holds pages: write to publish the
site, not contents: write.) new-entry answers any new-entry issue anyone
opens, so it can only read and comment: it reads the issue from the event
file GitHub writes, quotes the issue's text only inside a code block, and
commits nothing. No workflow writes a human
judgement — a summary, a pattern, a retirement — into the catalog. On a pull
request, lint's review job runs the base branch's scripts, from a separate
checkout of the base commit, against the pull request's catalog.json with the
read-only token; the pull request's author login reaches that script as an
environment variable, never through a shell line. If you find a path that
breaks any of those, please report it.
Actions are referenced by their major version tag (actions/checkout@v7), not
pinned to a commit. The one exception is pypa/gh-action-pypi-publish, the
step that uploads the MCP package: it is referenced by its moving release/v1
branch, the form its README's examples use, so it follows that branch rather
than waiting for a new major. .github/dependabot.yml proposes each new major
as a weekly pull request, which a person reads and merges; nothing merges it
automatically.