Hardcoded Secrets in Code: How to Find Them and Get Them Out

A hardcoded secret is any credential written directly into source code: a database password in a config class, an API key in a JavaScript file, a token pasted into a test. It feels harmless while the repo is private — until the repo is forked, cloned onto a laptop that is lost, mirrored to a vendor, or made public. This guide explains why hardcoded credentials are so risky, how to find them across a codebase, what to do the moment you find one, and how to stop new ones from landing in your main branch.

Video explainer (1:16) · Watch with transcript

What counts as a hardcoded secret?

Anything that grants access and is stored as a literal in code or committed config. The obvious cases are passwords and API keys, but the category is wider than most teams expect.

  • Database connection strings with embedded username and password
  • Cloud provider access keys and service-account JSON files
  • Third-party API keys (payments, email, SMS, maps, AI providers)
  • OAuth client secrets and long-lived personal access tokens
  • JWT signing keys and encryption keys
  • Webhook signing secrets and internal service tokens

Why deleting the line is not enough

Git keeps history. Once a secret is committed, removing it in a later commit only hides it from the latest version of the file — anyone with clone access can still read it from older commits, forks, and pull request diffs.

That is why the first response to a leaked secret is always rotation: revoke the credential at the provider and issue a new one. Rewriting history is optional clean-up; rotation is the actual fix.

Before: secrets living in source

These patterns appear in every language. They usually start as “just for local testing” and survive into production.

public class ReportDb {
    private static final String USER = "report_svc";
    private static final String PASSWORD = "Sup3rS3cret!2026";
}
const apiKey = "live_9f2c1b7e4a";
export const client = createPaymentsClient({ apiKey });

After: load secrets at runtime

Read credentials from environment variables or a secret store (cloud secret managers, Vault, Kubernetes secrets) and fail fast at startup if a required value is missing. Commit an example file with placeholder values so new developers know which variables to set.

public class ReportDb {
    private final String password = requireEnv("REPORT_DB_PASSWORD");

    private static String requireEnv(String name) {
        String value = System.getenv(name);
        if (value == null || value.isBlank()) {
            throw new IllegalStateException(name + " is not set");
        }
        return value;
    }
}
const apiKey = process.env.PAYMENTS_API_KEY;
if (!apiKey) throw new Error("PAYMENTS_API_KEY is not set");
export const client = createPaymentsClient({ apiKey });

How to find hardcoded secrets in an existing codebase

Pattern-based static analysis is the fastest first pass because it covers every file in one run. Expect some false positives (sample values, test placeholders) — triage is quick, and a missed live key is far more expensive than a minute spent dismissing a fake one.

  1. Scan the whole repository, not only changed files — old modules are where secrets hide
  2. Search for assignment patterns: password, pwd, secret, token, and api_key followed by a quoted literal
  3. Review config files, test fixtures, scripts, and Docker or CI files as carefully as application code
  4. Check history for secrets that were “removed” in later commits
  5. Rotate every confirmed secret, then replace it with a runtime lookup

Prevent new secrets from reaching main

  • Add secret patterns to your pull request checks so a finding blocks the merge
  • Keep a committed .env.example and add .env to .gitignore
  • Use short-lived credentials and scoped tokens wherever the provider supports them
  • Never put server secrets in browser code — anything shipped to the client is public
  • Make rotation a documented, rehearsed procedure rather than an emergency improvisation

How CodeInspector flags hardcoded credentials

CodeInspector checks C#, Java, JavaScript, TypeScript, and C++ files for credential-like assignments — names such as password, pwd, secret, token, or api_key set to a quoted literal — and reports them as Critical severity with the file and line number. Each finding recommends moving the value to environment variables or a secret store, and the PDF report gives you a checklist to work through during rotation.

Connect a GitHub repository (public URL or private repo through GitHub OAuth) and run a scan at https://codeinspector.app — new accounts get starter credits.

Frequently asked questions

Is a hardcoded secret in a private repo still a problem? Yes. Private repos are cloned to many machines, shared with contractors and tools, and sometimes made public later. Treat any committed live credential as exposed.

Should I rewrite git history after a leak? Rotate first. History rewriting helps reduce future exposure but cannot recall copies that already exist.

Are test credentials okay to commit? Fake values that grant no real access are fine. Credentials for a real shared test environment should be handled like production secrets.

Related