All articles

Scan frontend for exposed secrets before launch safely

7 min read

Free security scan

Is your Next.js app secure? Find out in 30 seconds.

Paste your URL and get a full vulnerability report — exposed keys, missing headers, open databases. Free, non-invasive.

No code access requiredSafe to run on productionActionable report in 30

If you need to scan frontend for exposed secrets, check the built assets, not only the source repo. Anything shipped to the browser can be downloaded, searched, cached, and reused by attackers. Start with your production build, deployed domain, source maps, and public files. The goal is simple: find leaked credentials before users, bots, or search indexes do.

How to scan frontend for exposed secrets?

A frontend review should inspect built JavaScript output, static files, deployment artifacts, and browser-visible configuration. Source code scanning helps, but it misses values injected during build, preview deployments, or platform configuration.

Start with these high-signal checks:

  • Search compiled bundles for secret-like strings, provider key prefixes, tokens, and private URLs.
  • Confirm whether any key is a live key, not just a public identifier.
  • Review source maps, because source maps often reveal original variable names and comments.
  • Check robots, sitemap, well-known paths, and public asset folders.
  • Open the deployed site in DevTools and inspect network requests, local storage, and script responses.

A quick local check is useful before using a more complete scanner. Run it against the final build directory, not just src.

bash
npm run build
for dir in dist build .next/static public; do
  [ -d $dir ] || continue
  grep -RInE '(sk_live_|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35})' $dir || true
  grep -RInE '(secret|token|password|private_key|client_secret)' $dir || true
done
find dist build .next public -name '*.map' -print 2>/dev/null

This example is intentionally narrow. Real scanning should use more detectors, entropy checks, allowlists, context review, and validation. Otherwise, you will either miss dangerous leaks or drown in false alarms.

For a focused bundle workflow, see this JavaScript bundle scan. If your app is already deployed, pair it with a public website secrets review so you catch leaks created by hosting configuration, cached files, or public routes.

The most common mistake is treating frontend code like a private backend. Browser-delivered code is public by design. Minification only slows reading. Obfuscation does not protect credentials. If a secret is needed to call a protected service, the call belongs behind your server, edge function, or backend API.

What leaks from frontend code?

Most frontend findings are not dramatic at first glance. They look like normal config names, analytics setup, SDK initialization, or copied examples. The risk depends on what the value can actually do.

A publishable analytics ID is usually low risk. A payment secret, cloud access key, database URL, private webhook secret, or admin API token is high risk. A map key may be acceptable if it is restricted by domain and quota, but dangerous if it can call paid APIs from any origin.

Common leak sources include client-side config files, .env values with frontend prefixes, generated runtime config, and copied SDK snippets. Many frameworks intentionally expose variables with names like public, client, or browser prefixes. That is safe only for values designed to be public.

You should also check for public .env files. Misconfigured static hosting can expose .env, .env.local, backup files, old build folders, or logs. A single forgotten file can disclose database credentials even when the bundle is clean. This public .env check explains the specific paths attackers commonly test.

Another pattern is accidental exposure through error payloads. A frontend may call an API that returns stack traces, internal hostnames, bearer tokens, or signed upload URLs. That is not technically a bundle leak, but it is still browser-visible data and should be handled in the same review.

Source maps deserve special attention. They may reveal original source, comments, test credentials, hidden route names, and feature flags. Source maps are useful for debugging, but production access should be deliberate. If you need them, restrict access or upload them to your error tracker instead of serving them publicly.

Fix and verify findings

Treat every finding as untrusted until you know what the value can do. Then classify it by impact, exposure, and whether it was deployed. A string that only appears in a local build may not require rotation. A key that reached production, CDN cache, or a public repository should be considered compromised.

Use this practical response order:

  1. Confirm the value by identifying the provider, permission level, and environment.
  2. Rotate the credential if it reached any public asset, cache, log, or deployed page.
  3. Move privileged calls to a backend, serverless function, or edge route.
  4. Replace browser credentials with a least-privilege token when public access is unavoidable.
  5. Add domain, origin, IP, quota, and method restrictions where the provider supports them.
  6. Remove source maps or restrict them if they expose sensitive implementation details.
  7. Rebuild, redeploy, purge CDN caches, and scan again.

Do not stop after deleting the string from code. If the key was live, attackers may already have copied it. Rotation matters because browser assets are cacheable, mirrored, and often stored by crawlers. CDN purge helps, but it cannot recall files already downloaded.

Be careful with false positives too. Security teams waste time when every UUID, public key, or placeholder blocks a release. A good workflow records why a value is safe, such as public SDK ID, test fixture, documented client token, or restricted browser key. Keep allowlists specific. Avoid broad ignores like API_KEY or token across the whole repo.

For higher confidence, use an automated security scan before launch and a deeper authenticated review when the app has private flows. A deep scan is useful when secrets may appear after login, during checkout, inside dashboards, or through user-specific API responses.

The best fix is architectural. Frontend code should request actions from your backend, not hold the authority to perform those actions directly. For example, the browser can ask your API to create an upload session. The API checks the user, creates a scoped signed URL, and returns only what the browser needs.

Prelaunch checklist

Add a build-time guard so leaks are caught before deployment. This should run after environment injection and bundling. Scanning only pull requests can miss secrets added by CI variables, preview settings, or platform build configuration.

Use this checklist before every production push:

  • Scan the final build directory and deployed URL.
  • Inspect network responses for tokens, signed URLs, and verbose errors.
  • Check public files, source maps, backup files, and hidden config paths.
  • Verify that frontend-prefixed environment variables are intentionally public.
  • Confirm browser keys have origin restrictions and quotas.
  • Rotate anything privileged that was exposed outside the server.
  • Re-scan after CDN purge and redeploy.

A reliable process is better than a one-time audit. Create a repeatable gate in CI, then run an external scan against the live preview or staging URL. If a high-confidence secret appears, block release until the value is removed, rotated, and verified clean.

Keep the scope realistic. For a small SaaS app, the first pass usually includes the homepage, login, signup, pricing, checkout start, dashboard shell, and public API documentation. For an AI-built app, add generated admin routes, debug pages, temporary upload endpoints, and any test integrations the assistant may have scaffolded.

Secrets are not always named clearly. Generated code may call them serviceKey, adminClient, privateConfig, or serverToken. AI-generated examples also tend to mix frontend and backend snippets. Review any pasted provider setup with suspicion, especially if it initializes privileged SDK access in browser code.

A safe frontend has no privileged credentials, no public debug artifacts, and no accidental files that reveal deployment internals. The habit is simple: scan the build, scan the deployed site, fix the architecture, rotate exposed values, and make the check automatic before launch.

Faq

Can a frontend ever contain API keys?

Yes, but only keys designed for browser exposure. Examples include restricted publishable keys, public analytics IDs, or SDK identifiers. They should have origin restrictions, low privileges, and quotas. Never ship server secrets, database URLs, admin tokens, webhook secrets, or cloud credentials in browser code.

Is minified JavaScript safe from secret leaks?

No. Minified JavaScript is still downloadable text. Attackers can search it with scripts, beautify it, inspect source maps, and monitor network calls. Minification reduces file size, not exposure. If a credential is inside a shipped bundle, treat it as public.

Should i rotate keys after removing them?

Rotate any key that reached a deployed frontend, public file, CDN cache, source map, or browser response. Deleting the value prevents future exposure, but it does not invalidate copies already collected. After rotation, redeploy, purge caches, and scan again to confirm removal.

If you want a fast prelaunch check, run AISHIPSAFE against your public app and fix any browser-visible secrets before you ship.

Free security scan

Is your Next.js app secure? Find out in 30 seconds.

Paste your URL and get a full vulnerability report — exposed keys, missing headers, open databases. Free, non-invasive.

No code access requiredSafe to run on productionActionable report in 30