Supported versions
Sponson is pre-1.0. Only the latest minor release line receives security fixes; fixes are released as a new patch version of every affected package (sponson, @sponson/core, @sponson/adapters, @sponson/sim).
The GitHub Action (
action/) follows the version of the sponson package it runs (its version input).
Reporting a vulnerability
Never put vulnerability details in a public issue or pull request.- Open an issue with the Security contact request form (or titled “Security contact request”) and no details — only that you have something to report. A maintainer (MAINTAINERS.md) will reply with a private channel, normally within two working days.
- Send the details there.
- the Sponson version (
sponson --version) and Node.js version; - a minimal
release.plan.yamland the commands that reproduce the problem (againstpnpm simif possible — the fake cloud needs no real credentials); - what leaked or what was bypassed, and where (stdout, stderr,
--json, a receipt file, a receipts branch, a PR comment, MCP output, a provider request).
sk_test_PLACEHOLDER; the reproduction should show
the placeholder appearing where it must not.
What to expect:
We credit reporters in the advisory unless you ask us not to.
Scope
In scope
These break promises Sponson makes in its README and in the invariants inCONTRIBUTING.md; we treat them
as vulnerabilities, not ordinary bugs:
- Secret leakage. A resolved secret value, a provider credential (
VERCEL_TOKEN,NEON_API_KEY,CLERK_SECRET_KEY, …) or an output markedsensitiveappearing — in any encoding (plain, URL-encoded, base64, JSON-escaped, truncated) — in stdout, stderr,--jsonoutput, error messages, plan text, MCP responses, PR comments written by the Action, or log lines. (Invariant 1.) - Receipts. A secret value or a reversible hash of one written into a receipt or into the history of a
receipts branch (
sponson-receipts/<env>/<scope>, or the legacysponson/receipts); a receipt that can be made to claim ownership of resources Sponson did not create so thatapply --destroydeletes them; a receipt or lock that can be forged or tampered with to make Sponson modify resources it does not manage. (Invariants 5, 6, 8.) - Production approval bypass. Any way to make Sponson write to
production— directly, through a line whosewritesEnvironment()is production while--envis something else, through MCP, through the GitHub Action, or through plugin loading — without--approved-by/SPONSON_APPROVED_BY. (Invariant 7.) - Scope boundary violations. One scope (a PR, a branch) changing or destroying resources owned by another.
- Plan-time writes.
sponson planorstatusperforming any write to a provider. (Invariant 4.) - Code execution from untrusted input. A plan file, a receipt, or a provider response that causes code to be
loaded or executed (plugins are loaded only from
SPONSON_PLUGINS, which is trusted configuration). - The GitHub Action (
action/action.yml): script injection from PR titles, branch names or other attacker-controlled event fields; leakinggithub-tokenor provider secrets to forked-PR workflows.
Out of scope
- Vulnerabilities in the providers themselves (Vercel, Neon, Clerk, Doppler, 1Password) — report those to the provider.
- Anything requiring an attacker who already controls the machine, the CI runner, the environment variables,
SPONSON_PLUGINS, or write access to the repository’s default branch. A plugin is trusted code by design. - Secrets that the user writes as literals in places Sponson does not treat as secret-bearing, after Sponson’s
SECRET_LITERALcheck has been deliberately bypassed (please do report a value the check should have caught). @sponson/sim(the fake cloud) — it is a test tool, binds to127.0.0.1and accepts any token on purpose.- Denial of service through very large plans, or by holding a scope’s lock with legitimate credentials.
- Missing hardening with no demonstrated impact (e.g. headers, best-practice suggestions from scanners).
- Vulnerabilities in dependencies with no reachable path in Sponson — Dependabot handles those; open a normal PR.
Handling secrets as a contributor
- Tests and scenarios use placeholder values and the sim; never commit real tokens.
pnpm test:livereads credentials from your environment only. - New output paths must go through
Redactor, and JSON only throughserialize()inpackages/cli/src/output.ts. If you add an output channel, add it to the secrets journey (scenarios/journeys/secrets/).