Skip to content
Secrets Management for Web Apps: Where Most Teams Leak Data
All articles
secrets managementweb application securityAPI keysDevSecOpsenvironment variables

Secrets Management for Web Apps: Where Most Teams Leak Data

Secrets management for web applications explained: where API keys and credentials leak, how to store them properly, and how to catch exposure early.

WebSentry TeamOctober 11, 20266 min read

Every web application has secrets: database credentials, API keys, OAuth tokens, signing keys, third-party service tokens. How those secrets are stored, accessed, and rotated determines whether a single leaked string turns into a minor inconvenience or a full breach disclosure. Most teams don't have a secrets problem because they're careless — they have one because secrets management was never designed, just accumulated.

This post walks through the real failure points in secrets handling and the concrete fixes, not the theoretical ones.

Where Secrets Actually Leak

Before fixing anything, it helps to know where leaks actually come from in production web apps. The usual suspects:

  • Committed to git — a .env file added by accident, a config file with hardcoded credentials, or a key pasted into a commit message during debugging.
  • Exposed in client-side JavaScript — API keys meant for server-side use get bundled into frontend code and shipped to every visitor's browser.
  • Logged in plaintext — error logs, request logs, or monitoring tools capture full request bodies or headers that contain tokens.
  • Shared over Slack or email — "here's the staging DB password" messages that never get rotated and sit in chat history indefinitely.
  • Left in CI/CD configuration — build scripts with inline credentials instead of referencing a secrets store.
  • Exposed via misconfigured CORS or open endpoints — an internal API that returns config data including keys because access control wasn't enforced.

The .env File Problem

Environment files are the single most common leak vector for small-to-mid sized web apps. They're convenient during development, which is exactly why they end up in production too. Three habits prevent most of the damage:

  1. Add .env and all variants (.env.local, .env.production) to .gitignore from day one, not after the first incident.
  2. Run a pre-commit hook (tools like gitleaks or truffleHog) that scans staged files for credential patterns before they ever reach a commit.
  3. Audit your git history, not just the current state. A secret removed from the latest commit is still sitting in history unless you've rewritten it with git filter-repo or BFG Repo-Cleaner.

Picking a Secrets Storage Approach

"Where do we put secrets" has a different answer depending on your scale and stack. Here's a realistic breakdown:

Small teams / single apps

  • Platform-native secret stores — Vercel environment variables, Netlify env vars, Render secrets, Fly.io secrets. These are encrypted at rest, scoped per environment, and good enough for most small production apps.
  • Doppler or Infisical — lightweight managed secrets platforms that sync into your deployment pipeline and give you audit logs without the operational overhead of running your own vault.

Larger teams / multiple services

  • HashiCorp Vault — the standard for dynamic secrets, short-lived credentials, and fine-grained access policies across many services.
  • Cloud-native options — AWS Secrets Manager, Google Secret Manager, Azure Key Vault. Use these if you're already deep in one cloud ecosystem; they integrate directly with IAM roles so you avoid distributing static credentials at all.

Whichever you choose, the same three rules apply:

  1. Secrets should never be baked into a Docker image or build artifact.
  2. Access should be scoped — a frontend build process doesn't need access to your database credentials.
  3. Every secret needs an owner and a rotation plan, not just a storage location.

Rotation: The Step Everyone Skips

Storing secrets securely solves half the problem. The other half is assuming any secret could be compromised and making rotation cheap enough that you actually do it.

  • Set rotation intervals — 90 days is a reasonable default for API keys and database credentials that don't support dynamic generation.
  • Automate it where possible — Vault and cloud secret managers support automatic rotation for supported services. Use it instead of relying on a calendar reminder.
  • Rotate immediately after any team member offboards
  • Keep a revocation path — know exactly how to invalidate a given API key or token within minutes, not days. If your provider doesn't support fast revocation, that's a vendor risk worth flagging.

Secrets in the Browser: A Different Problem Entirely

Client-side secrets management is really about accepting that nothing shipped to the browser is secret. Common mistakes:

  • Putting a "public" API key in frontend code that actually has write or billing permissions attached.
  • Assuming minification or obfuscation hides a key — it doesn't; it's trivially extracted from any bundled JS file.
  • Using the same API key for server-to-server calls and client-facing calls instead of issuing scoped, restricted keys for the browser.

The fix is architectural: anything requiring real privilege should go through a backend proxy endpoint, with the actual secret staying server-side. The browser only ever sees a session token or a narrowly scoped, rate-limited key.

Checking Your Exposure Surface

Secrets management isn't just about storage practice — it's also about verifying your production environment isn't already leaking something. A few checks worth running regularly:

  • Scan public repos (including forks) for your organization's domain or key prefixes using GitHub's secret scanning or third-party tools.
  • Check response headers and error pages for stack traces that might reveal environment variable names or internal paths.
  • Review CORS configuration — an overly permissive policy can let any origin query endpoints that return configuration data.
  • Confirm cookies carrying session tokens have Secure, HttpOnly, and appropriate SameSite attributes so tokens can't be lifted via XSS or exposed over plaintext HTTP.

This is exactly the kind of surface-level exposure that WebSentry is built to catch quickly. Running a scan at websentry.dev checks your SSL configuration, security headers, CSP, cookie attributes, DNS records, and CORS policy, and gives you an A–F grade showing where misconfigurations might be quietly exposing more than intended. For agencies managing multiple client sites, it's a fast way to confirm that headers and cookie settings that affect secret exposure are actually configured correctly, not just assumed.

A Practical Checklist to Start From

  1. Add .env files to .gitignore and scan git history for existing leaks.
  2. Move hardcoded credentials out of code and into a dedicated secrets manager.
  3. Separate client-facing keys from server-side keys, and scope each one tightly.
  4. Set a rotation schedule and automate it wherever your provider supports it.
  5. Audit logging output to ensure tokens and headers aren't captured in plaintext.
  6. Run a security scan to check headers, cookies, CORS, and CSP for exposure gaps that don't show up in a code review.

Secrets management isn't a one-time setup — it's a maintenance habit. The teams that avoid incidents aren't the ones with zero secrets; they're the ones who assume leaks happen and build storage, rotation, and monitoring around that assumption. Run a free scan at websentry.dev to see where your site's configuration might already be giving more away than it should.

Check your own site

Run a free security scan and see if your site has the issues covered in this article. Results in under 30 seconds.