Snitch security & threat model
What we collect, what we don't, what happens if our publish credentials get compromised, and what defenses are in place.
A security tool that ships its own malware to customers is the worst possible failure mode. The Checkmarx supply-chain compromise in April 2026 (poisoned KICS Docker images + VS Code extensions on customer dev machines + CI runners) is the canonical example. This page is Snitch's public threat model: what we hold, what we don't, what defenses are in place, and what to do if something goes wrong.
What Snitch sees
| Surface | What we receive | What we do NOT receive |
|---|---|---|
| Plugin (skill in your AI tool) | License-key validation hits snitchplugin.com once on install. | Source code. Findings. Anything from your AI session. |
CLI (snitch scan) | License-key validation, methodology download, per-scan metadata (file count, finding counts, duration, provider name). | Source code. Findings. Repo identity (no owner/name/PR sent). The AI inference happens locally (subprocess to Claude Code / Codex / Gemini) or against your provider with your own key. |
| GitHub Action | Same as CLI. Per-PR scan metadata is keyed by an opaque sha256 hash of {owner}/{repo}#{pr} so we can deduplicate scans without learning which repo/PR. | Source code. Findings. The AI provider sees the prompt (your code chunks); we never do. |
Your code never crosses our infra
Our servers do not have, and structurally cannot have:
- The contents of any file Snitch scanned
- The findings produced by any scan
- The repo / org / PR identifier of any scan (we hash it client-side)
- Your AI provider key (that's yours, never sent)
The only data persisted on snitchplugin.com is: per-customer scan counts (for quota enforcement), per-customer license entitlement, the global methodology bundle, and per-scan rows of operational metadata (file count, finding counts, duration, provider name, an opaque per-PR hash for deduplication). No file contents, no finding text, no repo / org / PR identifiers in plaintext.
Defenses against supply-chain compromise
The Bitwarden / Checkmarx incidents both spread by poisoning a security vendor's published artifacts (Docker images, VS Code extensions, npm packages) and using customer auto-updates to land malware on customer machines. We've structurally hardened against the equivalent attack on Snitch:
1. Runtime egress allowlist
Every release of the GitHub Action and CLI installs a runtime fetch interceptor at the very top of the scan flow. Any outbound HTTP request to a hostname that isn't explicitly on our allowlist (snitchplugin.com, api.osv.dev, GitHub APIs, your selected AI provider host) throws and surfaces as a ::error:: in the workflow log. A poisoned transitive dependency that tries to phone home to attacker.example.com cannot complete the request — you'll see it instantly.
The allowlist is in src/egress.ts of the public CLI mirror. Read it; it's about 100 lines.
2. Build-time URL audit
scripts/audit-dist-urls.sh runs before every Action publish. It greps the bundled dist/index.js for every URL it contains and fails the publish if any URL is on a hostname not in our allowlist. Catches a poisoned transitive dep at publish time, not at customer runtime.
3. SLSA build provenance
The Action mirror at snitchplugin/snitch-github-action runs a release workflow on every push to main + v1 tag move, which uses actions/attest-build-provenance to attach a Sigstore-signed claim that the dist/ was built from a specific source commit on a specific GitHub-hosted runner. Verify with:
gh attestation verify dist/index.js --owner snitchplugin
The npm CLI publishes with npm publish --provenance (when run from CI). Customers verify with npm audit signatures.
4. SHA pinning, recommended for security-sensitive repos
The dashboard YAML template recommends snitchplugin/snitch-github-action@v1 for the auto-update path. For security-sensitive or regulated environments, pin to a specific commit SHA instead:
- uses: snitchplugin/snitch-github-action@<40-char-sha> # vX.Y.Z
If our publish credentials get popped tomorrow, customers pinning a SHA continue to run the version they vetted. Customers on @v1 get the malicious push on their next CI run, but the runtime egress allowlist still catches the exfiltration attempt before any data leaves their runner.
5. Minimal Action permissions
Our action.yml requests:
contents: readpull-requests: writesecurity-events: writestatuses: writemodels: read
We do NOT request actions: write (can't modify your CI configs), id-token: write (can't mint OIDC tokens against AWS / GCP), packages: write (can't publish to your registry), or repository-projects: write. So even if our Action gets compromised, the maximum blast radius is what those five permissions allow — which is "comment on the PR, write a SARIF, set a check status." Not arbitrary code execution against your cloud accounts.
6. Provider keys never reach us
If you set openrouter-api-key, anthropic-api-key, etc. in your workflow, that key is consumed by the Action on your runner and used to call your provider's API directly. The key never touches snitchplugin.com. The runtime egress allowlist enforces this: a request to snitchplugin.com carrying your provider key would trip the request inspector during code review, but more directly — we don't have any code path that puts the key in a request to our own servers.
What happens if our publish credentials get compromised
Realistic worst case: an attacker with our npm token + GitHub publish credentials pushes a malicious version of the Action to the @v1 tag.
- Customers on
@v1get the malicious code on their next CI run. - The runtime egress allowlist catches any attempt to exfiltrate to an attacker host. Their CI run logs show
::error::[snitch-egress] Blocked outbound request to <host>. - The Action's permissions cap the damage: the worst the malicious code can do is comment on a PR or set a check status, not exfiltrate secrets to an attacker's server.
- SHA-pinned customers are completely unaffected.
- We rotate credentials, force-revert
@v1, post an incident notice on snitchplugin.com/changelog as soon as the revert is verified, and email every active customer.
Reporting a security issue
Email eric.waters@snitchplugin.com with subject [SECURITY]. Do not file a public GitHub issue. We aim to respond within 2 business days.
Audit trail
The runtime parts of Snitch that touch your machine are public:
- GitHub Action: https://github.com/snitchplugin/snitch-github-action
- CLI: https://github.com/snitchplugin/snitch-cli
The Plugin's skill bundles are distributed via R2 and ship inside the ZIP you download after purchase. Every file in that bundle is plain markdown / shell / yaml that you can read before installing.