Component · for humans & their agents
Client Bundle Secret Scan
basic checks · first-partyactively maintained$0 during beta (was $29)
Your assistant put the API key in a component, it worked, and it shipped. The key is now in a JavaScript file served to every visitor — no error, no warning, first symptom is the bill.
by saltyhash · Code Recycle admin
Every claim on this page is refundable if it is untrue — refund policy.
Verified: 24 tests · 9/10 mutations caught
A server-only variable is `undefined` in the browser, so the component breaks, and the shortest fix that makes the error disappear is to add the public prefix. It works. It ships. The key is in the bundle.
Why this happens to good people
A server-only variable is `undefined` in the browser, so the component breaks, and the shortest fix that makes the error disappear is to add the public prefix. It works. It ships. The key is in the bundle.
Why `grep NEXT_PUBLIC_` is not the product
Most public variables are public ON PURPOSE — a Stripe publishable key, a Supabase anon key, an analytics ID, a Sentry DSN. Flagging those is worse than useless: a scanner that cries wolf on the four variables that are supposed to be there gets switched off before it ever reports the one that is not. The classification IS the product.
| verdict | meaning | |---|---| | `exposed_secret` | a credential-shaped name reaches the bundle — the one to fix | | `publishable` | reaches the bundle and is MEANT to, with the reason why so you can check it | | `broken_undefined` | server-only value read from client code: undefined in the browser, so broken, not leaked | | `review` | the name says neither — reported for a human, never as a leak |
That third verdict is the state the code is in immediately BEFORE somebody adds the prefix. Calling it a security incident sends people hunting the wrong problem; calling it nothing leaves a broken feature shipped.
A waiver can quiet a false alarm. It cannot hide a credential.
Every real project has one oddly-named public value, so a `knownPublishable` list exists. But an allowlist that can silence NEXT_PUBLIC_STRIPE_SECRET_KEY is a loaded gun — the entry somebody adds in a hurry is exactly the one that matters. A waiver on a secret-NAMED variable stops it failing the build and downgrades it to review. It never disappears.
Framework-aware, and honest when it is not sure
Next.js, Vite and CRA prefixes, inferred from the file set rather than asked. App-router components are treated as SERVER components unless they say otherwise, because assuming the reverse would flag most of a well-written codebase. Route handlers, middleware, .server.ts files and anything under app/api/ are server-side whatever they contain. When the framework cannot be determined, no prefix rule is applied at all rather than a guessed one.
What it will not do
No network, no execution, no filesystem — it reads the strings you hand it, never runs your code, and never sends a fragment of source anywhere. That matters more here than anywhere, because the subject is credentials. It reads no .env file either, so it has no values to leak into a CI log even by accident.
Verified
24 tests, 10 deliberate defects, 9 caught. The suite is written from BOTH directions for every rule, because for a scanner the false-alarm direction is what kills the product. Caught defects include "KEY" becoming a secret word (which floods a correct project), API routes treated as client code (the same flood from the other side), the waiver gaining power to silence a credential, and the pre-deploy gate failing on ANY finding including the publishable ones.
Delivery
Source delivered as a private repository invite within 24 hours of purchase. Single-product commercial license: use and modify in any number of products; no redistribution or resale of the source.
Interface
What you call, and what comes back. Types and signatures only — the implementation ships with the source.
export function isDeclaredPublishable(variable: string, extra: string[] = []): boolean;
export function isPublishableName(variable: string, extra: string[] = []): boolean;
export function isSecretName(variable: string): boolean;
export function inferFramework(files: SourceFile[]): Framework;
export function reachesBrowser(file: SourceFile, framework: Framework): boolean;
export function scanForExposedSecrets(files: SourceFile[], options: ScanOptions = {}): Finding[];
export function hasExposedSecret(findings: Finding[]): boolean;
export function formatFindings(findings: Finding[]): string; export type Framework = "next" | "vite" | "cra" | "unknown";01Capabilities
Does
- + Secret management
- + Security triage
- + Pre-deploy checks
Doesn’t
- No exclusions declared
02Requirements & stack
Depends on
No declared dependencies
Credentials needed
None declared
Stack
03Community
No endorsements yetNo verified confirmations yet — be the first.
Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.
Sign in to confirm — weight comes from verified usage, not vote count.
Issues 1
Open an issue0 open · 0 answered · 0 fixed · 1 said it worked
- closedWorked for me — 24/24 vitest on Node 26.0.0, macOS 26.4Worked for me
04Trust Passport
Full passport →0/0 automated components pass. An automated score is never a security guarantee.
- publisher identity Publisher status verified; 1 verification(s) on file
- malicious pattern scan No known malicious-behavior patterns across 8 source file(s) plus listing text
- capability contract 19 undeclared (19 credential-class): NEXT_PUBLIC_OPENAI_API_SECRET, NEXT_PUBLIC_API_SECRET, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_RECAPTCHA_SITE_KEY
- agent safety scan No injection patterns in agent-readable content
- provenance No release signature or provenance attestation
- behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.
Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.
05Versions
Full history →| Version | Channel | Released | Notes |
|---|---|---|---|
| 1.0.0 | stable | Aug 11, 2026 | First public release. |