Why hardcoding API keys and passwords is dangerous: a guide to secrets management
Writing an API key, a database password or an access token straight into your source code is one of the most common and most expensive mistakes in software development. The core problem is simple: once a secret lands in a repository, getting it back is almost impossible. According to GitGuardian's 2026 report, roughly 29 million new secrets were detected in public GitHub repositories in 2025 alone, a 34% jump over the year before. The fix is to stop treating secrets like a line of text and start managing them as a lifecycle: generated, distributed, and rotated on a schedule.
What actually counts as a secret
A secret is any credential that grants access to a system. API keys, database connection strings, cloud access keys such as an AWS access key, OAuth tokens, private encryption keys, SSH keys and third-party service passwords all qualify. What they share is that they authenticate on their own. Whoever holds the key walks through the door it opens without ever being asked for anything else.
Why a leaked secret can't be un-leaked
Developers often reason like this: I will delete the key from the code and the problem is gone. But Git is a version control system, and it remembers everything. Even if you remove the key and push a new commit, the old value stays in the history and lives on in every clone, every fork, every copy of the repo. The only real remedy is to revoke the credential itself and replace it with a new one. How often that step gets skipped is telling: 64% of the secrets that leaked in 2022 and were still valid had not been revoked as of 2026.
A real case: a key left exposed for five years
Toyota's incident makes the risk concrete. In December 2017 a subcontractor accidentally pushed part of the source code for the T-Connect app to a public GitHub repository. Inside that code sat a hardcoded key that granted access to a customer database. Nobody noticed until September 2022, roughly five years later. During that window the email addresses and customer numbers of about 296,000 people were exposed to risk. Toyota disclosed the incident in October 2022, invalidated the key and made the repository private, but it then had to comb through five years of access logs to find out whether the key had been abused.
Where secrets leak from
Public repositories are the obvious suspect, but the picture is wider. GitGuardian's data shows private repositories are about six times more likely to hold hardcoded secrets than public ones, because developers relax when they assume nobody outside can see the code. Secrets also escape through .env files committed by mistake, CI/CD configuration, log files, error screens, and even screenshots. AI has recently joined the list: leaks of AI-service credentials rose 81% in a single year, and AI-assisted coding appears to push the leak rate higher.
Are environment variables enough
Moving secrets out of the code and into environment variables, or a .env file excluded through .gitignore, is a big step up from hardcoding and a reasonable start for a development machine. It is not the whole answer. Environment variables are fairly easy to read across processes, they can spill into logs and crash dumps, and if a .env file gets committed by accident you are right back where you started. Production needs something more controlled.
The right approach: a secrets manager
OWASP's guidance is blunt: use a dedicated secrets manager. HashiCorp Vault, AWS Secrets Manager, Google Secret Manager and Azure Key Vault all do this job. These tools keep secrets in one place, log who accessed which secret, restrict access by permission, and inject secrets into the application at runtime. The secret never sits statically in the source or inside a container image; the application pulls it from the central store when it needs it.
Scan the code and the history
Keeping a secret out of the repo in the first place is far cheaper than cleaning it up afterward, so automated scanning is essential. Wire up a tool like gitleaks, TruffleHog or git-secrets as a pre-commit hook so a key is caught before it ever reaches the repo. GitHub's push protection blocks recognised key formats at push time. Add the same checks to your CI/CD pipeline, and scan your existing history once from top to bottom; it will almost certainly turn up a few forgotten secrets.
Rotation and least privilege
You cannot eliminate leaks entirely, but you can shrink their impact, and two principles decide how much. The first is rotation: change secrets on a regular schedule and immediately at the first hint of trouble, and use short-lived, auto-renewing credentials wherever you can. The second is least privilege: each service should reach only the secrets it needs, with only the permissions it needs. Even if a key leaks, a narrow door limits the damage. That logic sits at the heart of a zero trust architecture.
What to do when a secret leaks
Deleting the line from the code in a panic is the worst first move. The correct order is this: revoke the leaked credential and issue a new one first, because the risk lives in the still-valid key, not in the code. Then review your access logs to determine whether the key was misused, map out the systems and data that were exposed, and assess any breach-notification obligations you may have. Cleaning up the Git history comes last, and it is the lowest priority of all.
The steps are clear: scan your source and its history once, rotate every secret that turns up, move from environment variables to a proper secrets manager for production, and make pre-commit scanning mandatory. At Wedevit we scan your codebase and repositories for leaked secrets, set up a secrets-management foundation, and design it alongside your software supply chain security practices.
Need help with this topic?