← All posts

Cybersecurity · February 20, 2026 · intSignal Security Team

Secrets Management: Getting Credentials Out of Your Code

The blast radius of a committed secret

A password in a config file feels harmless right up until the moment a repository is cloned by the wrong person. Then it is not a config value anymore — it is a working key to a database, a cloud account, or a payment processor, sitting in plaintext, replicated across every laptop and build server that ever pulled the code.

The problem is worse than most teams assume, for one structural reason: version control never forgets. Deleting a key in the next commit does nothing. The secret lives in the git history forever, retrievable with a single command, and it stays valid until someone rotates it — which, in practice, almost never happens until after an incident. Verizon's Data Breach Investigations Report has for years placed stolen and misused credentials among the most common paths into a breach, and secret-scanning services routinely flag millions of exposed keys across public repositories each year. A leaked cloud key does not wait for business hours; automated scrapers find fresh commits within minutes.

Getting credentials out of code is not a cleanup task. It is an architecture decision: applications should receive the secrets they need at runtime, scoped tightly, expiring quickly, and issued to a verified identity — never baked into an artifact that gets copied, cached, and archived.

Why secrets end up in code (and stay there)

It is worth naming the forces at work, because the fix has to address them:

  • It is the path of least resistance. Pasting a connection string into a file is faster than standing up a secrets store, and it works on the first try.
  • Local and production blur together. A key added for a quick local test gets committed and quietly promoted to production because nothing forced a separation.
  • Secrets sprawl beyond source code. They hide in CI/CD variables, container images, Terraform state, Kubernetes manifests, environment files, log lines, and the shell history of the engineer who ran a one-off script.
  • Nobody owns rotation. Static credentials have no expiry, so they accumulate. Years later no one remembers which service depends on a given key, so no one dares to change it.

Access lock guarding a runtime secret handed to a verified workload identity Figure: the goal is not to hide the key better — it is to issue a short-lived, tightly scoped credential to a verified identity at runtime.

Centralize in a vault, then stop distributing static keys

The first move is to give every secret a single authoritative home. A dedicated secrets manager — HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, Google Secret Manager — replaces the scatter of files and environment variables with one system that stores secrets encrypted, enforces access policy, and logs every read.

Centralizing buys three things immediately:

  1. An audit trail. You can answer "who read the production database password, and when" — a question that is unanswerable when the password lives in a file.
  2. Access control. Reads are gated by policy tied to identity, not by filesystem permissions on a server nobody patches.
  3. A rotation point. With one source of truth, changing a secret is a single operation instead of a hunt across a dozen systems.

But centralizing a static secret is only half the win. If the vault hands out the same long-lived database password to every application, a single compromised host still leaks a credential that works everywhere, forever. The larger gain comes from what a vault enables next: credentials that are generated on demand and die on their own.

Dynamic, short-lived credentials

The most effective way to shrink the value of a stolen secret is to make it expire before an attacker can use it. Instead of a permanent database password, the vault generates a unique username and password on request, valid for, say, 15 minutes or the life of the session, then automatically revokes it.

Dynamic secrets change the security math in several ways:

  • A leaked credential is usually already dead. By the time it appears in a log or an image, its short lease has expired.
  • Every consumer is distinct. Because each application instance gets its own credential, a leak is traceable to a single source and can be revoked without disrupting anyone else.
  • Rotation stops being a project. There is nothing to rotate on a schedule because nothing is long-lived in the first place.

This model applies well beyond databases — cloud API access, message queues, certificates, and SSH access can all be issued as short-lived grants. Treat the lease length as a security control: the shorter the time to live, the smaller the window of exposure.

Workload identity beats static keys

The hardest secret to manage is the one an application needs in order to fetch its other secrets — the bootstrap credential. Hand it a static vault token or a cloud access key and you are back where you started. Workload identity solves this by letting the platform vouch for the workload cryptographically, so no long-lived key is ever stored at all.

In practice this means:

  • Cloud IAM roles and managed identities. A virtual machine, container, or function assumes a role the cloud platform grants based on where it is running. Credentials are injected automatically and rotate behind the scenes, with no key in the code.
  • OIDC federation for CI/CD. A pipeline in GitHub Actions, GitLab, or a similar system exchanges a signed identity token for a short-lived cloud credential at run time — eliminating the long-lived deploy keys that are among the most dangerous secrets a team stores.
  • Service identity in Kubernetes. Workloads authenticate to the vault using a service account the cluster attests to, rather than a shared token baked into a manifest.

The principle is the same at every layer: prove who you are with an identity the platform already trusts, and receive a scoped, expiring credential in return. This is the same identity-first thinking behind a mature privileged access management program — access is brokered and time-bound rather than issued as a standing key.

Least-privilege scoping

A credential should be able to do exactly one job and nothing else. Too often a service is handed broad, account-wide permissions because narrowing them takes effort, which turns any single leak into a full-account compromise.

Scope aggressively:

  • Grant read-only where a service only reads; separate read and write paths.
  • Restrict each credential to the specific resources it touches — one database, one bucket, one queue — not the whole account.
  • Give each service its own identity so permissions and logs are attributable.
  • Review grants on a cadence and strip anything unused. Entitlements accumulate; someone has to prune them.

In cloud environments, over-permissioned identities are one of the most common and most exploited misconfigurations. Continuously mapping who and what can reach each resource is exactly the work of cloud security posture management, which flags the excess grants and public exposures that manual review misses.

Secret scanning in CI (and before the commit)

Even with a vault in place, someone will eventually paste a key into code. The control that catches it is automated scanning, positioned as early as possible:

  1. Pre-commit hooks run a scanner such as Gitleaks or TruffleHog on the developer's machine, blocking the secret before it ever reaches the remote.
  2. CI pipeline scans act as the backstop, failing the build when a secret slips past the local hook.
  3. Full-history and push-protection scanning checks not just the latest diff but the entire repository, and blocks a push that introduces a known key pattern.

When a scanner does fire, treat the finding as an exposed secret, not a false alarm to acknowledge. The response is not "delete the line" — it is rotate the credential immediately, because the moment a secret touches a shared history it must be considered compromised. Embedding these gates in the delivery pipeline is part of a broader application security practice that shifts detection left, where a leak costs minutes to fix instead of a breach to recover from.

A practical rollout checklist

  • Inventory where secrets live today: repos, CI variables, images, config files, Terraform state.
  • Scan full git history and rotate everything that turns up — assume all of it is burned.
  • Stand up a central vault and migrate secrets out of code and environment files.
  • Replace static database and API credentials with dynamic, short-lived grants.
  • Adopt workload identity — IAM roles, managed identities, OIDC federation — to kill bootstrap keys.
  • Scope every credential to least privilege and review grants regularly.
  • Wire secret scanning into pre-commit hooks and CI, with rotation as the standard response.

Closing

Secrets management is not about hiding keys more cleverly. It is about designing so that any single credential is short-lived, narrowly scoped, tied to a verified identity, and revocable in seconds. Reach that state and a leaked secret becomes a logged, contained event rather than the opening move of a breach. If you want a clear-eyed assessment of where your credentials are exposed today and a prioritized plan to close the gaps, talk to intSignal's security team.