Security

·5 min read·Updated

Secrets Management: Why Passwords and Keys Should Not Live in Code

Removing a key from a file is not enough. Follow revocation, replacement and the applications that may still be using an older value.

An email-service key accidentally reaches a repository. Someone removes it from the file and closes the ticket. The original key still works: it remains in history, build artifacts and possibly somebody else's copy. Removing the line changed the visible code, not the authority held by anyone who knows that value.

Secrets management starts with the ability to end that access. Storage is only part of it. The company needs an owner, a list of consumers, defined permissions and a replacement procedure. Here the subject is application and integration credentials, not a requirement to keep changing every employee's personal password.

Exposure requires a change in authority

Rewriting repository history cannot guarantee removal from other people's copies. GitHub therefore recommends revoking or rotating exposed credentials first. History cleanup may need separate coordination and should not postpone containment.

For the email integration, establish what the key allowed, which applications used it and whether suspicious sends occurred. Restore the application with replacement access and verify that the provider rejects the previous credential. Immediate revocation may require interrupting delivery; seamless rotation cannot be promised in every incident.

The application must retain messages it already committed to sending and avoid reporting an authorisation failure as successful delivery. Recovery then needs to resume that work safely. This is where credential security becomes an ordinary product-operations problem.

The key to the vault should not unlock everything

Moving secrets from source code to controlled storage still leaves a bootstrap question: how does the application establish its identity? Giving every service one permanent vault-administrator password creates a new shared exposure instead of fixing the old collection of files.

Where supported, an application can use a workload identity with narrowly assigned permissions. Azure managed identities, for example, provide access to supported resources without a password that developers must distribute themselves. That is a platform capability, not a guarantee that every external API supports the same arrangement.

Separate ordinary configuration from secrets too. An endpoint address is not its password. A public certificate and its private key have different confidentiality requirements. Keeping those distinctions clear avoids giving unnecessary access to sensitive material just to edit a harmless setting.

Rotation changes both sides of the connection

Writing a new password into storage is insufficient: the database or partner must accept it, and consumers must use it. Planned rotation needs preparation, validation and a controlled transition. A provider that supports two concurrent keys can allow a limited overlap. A provider that does not may require another sequence and some interruption.

The AWS Secrets Manager rotation workflow illustrates four distinct steps: create a value, set it on the target, test it and finish the transition. These steps do not prove that every consuming application has refreshed its configuration.

A process may load credentials only at startup. A database pool may keep using established connections. Test a fresh connection, restart a consumer and disable the former credential. Without the last check, a successful test may merely show that the old access remains valid.

Define failure handling in advance. Rolling the application back must not silently restore an exposed key. Rotation has operational state: what has been prepared, what the target accepts and which consumers have not completed the change.

A short lifetime needs effective expiry

Some systems issue separate temporary credentials instead of a shared permanent password. This improves attribution and limits their lifetime, but requires renewal or replacement and correct behaviour when time runs out. Vault's lease documentation describes that lifecycle for its supported dynamic credentials and tokens.

Do not assume every value placed in a vault gains those properties. Expiring our record of a static API key may change nothing at the partner accepting it. Test the authority at the receiving system, including whether established sessions survive revocation.

What works when the secrets service is down?

An existing application may continue with a value it already has while a replacement instance cannot start. Testing one long-running process therefore says little about the resilience of the whole arrangement. Include startup, refresh and rotation while the dependency is unavailable.

Local caching is a decision about lifetime and exposure. Keeping old credentials indefinitely is dangerous; fetching them for every operation may create an unnecessary dependency. The design should specify refresh, revocation and storage limits. Emergency access should not become a permanent bypass shared by the team.

The OWASP guidance treats issuance, auditing, replacement and retirement as parts of secrets management. Logs should explain who requested access and what happened, not record the secret itself. Masking one console output does not establish that another log or memory dump contains no copy.

Use one real integration as the acceptance test

Choose a credential with a clear owner and a known product impact. Identify production, test and recovery consumers, including infrequent jobs. Restrict access and rotate it while checking a fresh connection. Confirm that the former value no longer grants the capabilities it used to provide.

A small team may be adequately served by its existing platform rather than a custom universal vault. What remains necessary is a workable exposure, revocation and recovery procedure. The completed task is not “password moved”: it is a demonstrated ability to replace it without hunting down the integration's author or losing track of unfinished work.