Website Security
Secret Key Leak Scanner
Fetches your page's HTML and the JS bundles it links, then regex-scans them for 19 high-confidence credential types accidentally shipped to the browser — every finding masked.
What is Secret Key Leak Scanner?
A secret key leak is when a real credential — an AWS access key, a Stripe secret key, a GitHub token, a database password — ends up inside the HTML or JavaScript your site ships to every visitor's browser. It usually happens by accident: a key hardcoded during development, a server-side secret pulled into a frontend build, or a config object that includes more than it should. Because that code is public, anyone can open the page source or a JS bundle and read it. This scanner fetches your served HTML and the JavaScript it links, then checks that content for credential patterns — reading only what's already public, and masking anything it finds.
What Nandix checks
- Cloud provider keys — AWS access key IDs (AKIA/ASIA), Google OAuth client secrets
- Payment keys — Stripe secret/restricted (sk_live_/rk_live_); publishable (pk_live_) flagged as public-by-design
- Version control tokens — GitHub (ghp_/gho_/…, github_pat_), GitLab (glpat-)
- AI provider keys — OpenAI (sk-…/sk-proj-), Anthropic (sk-ant-)
- Messaging — Slack tokens (xox…) and incoming-webhook URLs
- Email/SMS — SendGrid (SG.), Twilio API key SIDs (SK…)
- Package/e-commerce — npm (npm_), Shopify (shpat_/…), Square (sq0atp-/sq0csp-)
- Private keys (PEM headers), database connection URIs with embedded passwords, and JWTs
Probes
19 checks
How it detects
Passive — fetch, read, regex. It fetches the target HTML, extracts the <script src> bundles the page links (it never guesses secret paths — that's the Exposed Files scanner's job), fetches those bundles under strict size, timeout, and count caps, and matches distinctive-prefix credential patterns. A Shannon-entropy check plus a placeholder wordlist suppress or downgrade docs samples (EXAMPLE/XXXX) so they never surface as CRITICAL. Public-by-design keys (Stripe pk_live_, Google AIza, JWTs) are reported as WARNINGs to verify restriction, not as leaks. Every finding is masked at detection time — the raw credential never enters the report, the shareable URL, or the PDF.
Why it's dangerous
A leaked secret is one of the fastest routes to a full breach because it skips every other defense — no exploit needed, the attacker just reads the key and uses it. A leaked cloud key can spin up servers on your bill or reach your data; a Stripe secret key can move money; a GitHub token can reach your private repositories. And these leaks are found fast: automated bots continuously scrape public JavaScript for credential patterns, so an exposed secret is often discovered within hours. Not every key in frontend code is a mistake, though — some (like Stripe publishable keys or Google Maps keys) are public by design, which is why this scanner separates true secrets from keys that are safe to expose when properly restricted.
Example finding
A live Stripe secret key (sk_live_••••••RtY9) was found in a served JavaScript bundle — an attacker who reads it could issue charges and access payment data. Rotate it immediately and move it server-side.
How to fix it
Get real secrets out of client-side code and rotate anything that leaked. Never put server-side secrets in frontend code — keep them on the server and expose only the results through your API. Use server-only environment variables (in Next.js, un-prefixed vars stay server-side; only NEXT_PUBLIC_ vars reach the browser — never prefix a real secret). Rotate any credential that was ever exposed and assume it's already compromised. For keys that legitimately belong in the frontend (publishable/maps keys), lock them down with domain, referrer, or IP restrictions so a copied key is useless elsewhere. Add secret scanning to your CI so a key can't be committed in the first place.
js
// BAD — real secret shipped to the browser
const stripe = new Stripe('sk_live_51H...'); // secret key in client code
// GOOD — secret stays server-side; client calls your API
// server route (never sent to browser):
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
// client — only the publishable key, which is public by design:
const stripe = Stripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);Severities & standards
Severities
CRITICAL · HIGH · MEDIUM · LOW
References
Frequently asked questions
Aren't some API keys supposed to be in frontend code?
Yes. Publishable keys (like Stripe pk_live_ or Google Maps AIza keys) are public by design and safe to expose when restricted by domain or referrer. Nandix flags those as informational warnings, not critical leaks — only true server-side secrets (secret keys, tokens, private keys, database URIs) are treated as critical.
Does Nandix show or store my leaked key?
No. Findings are masked — you see the credential type and a partial snippet (like sk_live_••••••RtY9), never the full key. The complete credential is never returned, stored, logged, or included in a shared report.
I found a leaked secret — is deleting it from the code enough?
No. Once a secret has been served publicly, assume it's already been captured. Remove it from the code AND rotate the credential (issue a new one, revoke the old). Then move the secret server-side so it can't leak again.
See how every check runs on the methodology page, or browse all scanners.
Scan your site for this →Free secret-leak scanner. Nandix scans your HTML and JavaScript bundles for accidentally exposed credentials — AWS keys, Stripe secret keys, GitHub tokens, private keys — with masked, precision-first findings.