AI CodeOps

What to do when a secret is committed to Git

A step-by-step response to a credential committed to a Git repository: revoke and rotate it first, check for misuse, clean the history, prevent a repeat.

When a secret such as an API key, token, password or private key is committed to a Git repository, revoke and rotate it first, then work out what it could access and whether it was used, then remove it from the code and, if your policy requires it, from the history. Deleting the line in a new commit does not help on its own: Git keeps every earlier version, and every clone, fork and CI cache has a copy. Treat the credential as compromised from the moment it was pushed.

This page expands the secrets scanning section of How do you secure AI-generated code?.

Why deleting the line is not enough

A Git repository is a history, not a folder. Removing a secret in a new commit leaves it in the earlier commit, where anyone with access can read it with a single command. Copies also exist outside the repository:

  • every developer's clone and every fork;
  • CI systems that cloned the repository, and their caches and logs;
  • the Git host's own views of the commit and any pull request that contained it;
  • container images or build artifacts made from that commit;
  • backups and mirrors.

Public repositories are scanned continuously by automated tools looking for credentials, so for a public repository assume the secret was seen as soon as it was pushed. For private repositories the audience is smaller but not zero.

Step 1: revoke and rotate

Rotation is the only step that makes the leaked value useless. Do it first, before any clean-up.

  1. Issue a replacement credential at the provider.
  2. Deploy the replacement to everything that legitimately uses it.
  3. Revoke the leaked credential so it no longer works.

If the secret is high-impact and the exposure is public, revoke immediately and accept a short outage rather than leave a working credential exposed while you deploy the replacement. Some providers detect their own keys in public repositories and revoke them automatically; do not rely on it.

Step 2: understand the scope

Write down what the credential could do:

  • What it grants. Read-only access to one service, or administrative access to a cloud account?
  • Where else it is used. Shared credentials mean more systems to rotate.
  • When it was exposed. The commit time sets the start of the window to investigate.
  • Who could see it. Public, the whole organisation, or one team? Were there forks?

This determines how much investigation the incident needs, and who must be told.

Step 3: check for misuse

Look at the provider's audit or access logs for activity using the credential during the exposure window: unfamiliar IP addresses, unexpected regions, new resources, unusual data access or spikes in usage and billing. If you find misuse, this has become a security incident with its own response: contain, investigate what was accessed, and notify whoever your policies and obligations require.

Step 4: clean up the code and history

Remove the secret from the current code and replace it with a reference to where the value now lives: an environment variable, a secrets manager, or a configuration file that is not committed.

Whether to also rewrite history depends on your policy. If you do:

  • Use a tool built for it, such as git filter-repo or the BFG Repo-Cleaner. The Git project recommends git filter-repo over the older git filter-branch.
  • Coordinate with everyone who works on the repository. A rewrite changes commit hashes, so existing clones must be re-cloned or carefully reset.
  • Check what your Git host keeps. Pull request references and cached views may still show the old commits; host documentation explains how to have them removed.
  • Remember forks and clones are out of reach. That is why rotation came first.

Clean CI logs and rebuild any artifacts or images that contained the secret.

Step 5: fix the cause

Find out how the secret got into the repository, and close that path.

  • Keep secrets out of tracked files. Local configuration files such as .env belong in .gitignore, with a committed example file that has placeholder values.
  • Scan before commit. Pre-commit hooks running a secrets scanner, such as gitleaks, TruffleHog or detect-secrets, catch most mistakes on the developer's machine.
  • Scan on push. Some Git hosts offer push protection that rejects a push containing a recognised credential.
  • Scan history once. A one-off scan of the full history finds older leaks nobody noticed.
  • Inject credentials at build and run time. Build and deploy jobs receive secrets from a secrets manager or the CI system's secret store, scoped to the jobs that need them and masked in logs.
  • Prefer short-lived credentials. Where providers support it, workload identity or tokens that expire in minutes limit the damage of any leak.

Step 6: record what happened

Write a short record: what leaked, when, how long it was exposed, what it could access, whether it was used, what was rotated and what changed to prevent a repeat. It is useful for audits, and it is the best way to notice when the same kind of mistake keeps happening.

Secrets and AI coding agents

AI agents add new ways for secrets to leak. An agent that reads a .env file may copy a real key into code, a test fixture or a configuration example. An agent given a credential in its prompt or context can write it into output, logs or a request to a model provider. And provider-side logs of prompts may now contain the secret too, which means rotation, not deletion, is again the answer.

The most effective control is simple: agents that write code should never have production credentials in their context. Give secrets to the build or deploy job that needs them, not to the agent.

How AI CodeOps handles secrets

AI CodeOps does not scan your repositories for secrets; keep using a secrets scanner in your own pipeline. What it does is keep workspace secrets away from AI agents and record how they are managed.

  • Encrypted and masked. Workspace secrets are encrypted at rest with AES-256-GCM. After saving, the console only shows a mask.
  • Scoped and rotatable. A secret can be limited to specific workflows, given an expiry date, disabled, or rotated in place, with the rotation time and version recorded.
  • Kept from agents. Secrets reach build jobs as environment variables, and their values are removed from the build log. AI agents never receive them.
  • Audited. Creating, updating, toggling and deleting a secret are recorded in the audit log. The Secret Manager role can manage secrets without any other access.
  • Reviewed changes. The findings review of each AI change covers security, and the Security Auditor looks for exposed secrets in the workflows that include it. A policy rule can deny changes to paths such as config/secrets/**.

See Security and SBOM, the secrets scanning glossary entry, and Security and SBOM tracking for the overview.

Frequently asked questions

Is deleting the secret in a new commit enough?

No. The secret stays in the repository history, in every clone and fork, and possibly in CI logs and caches. Revoke and rotate it; deleting it from the code is a later clean-up step.

Should I rewrite Git history after leaking a secret?

Only after the secret has been revoked, and only if your policy requires it. A rewrite does not reach existing clones and forks, and it disrupts everyone working on the repository, so it is never a substitute for rotation.

What if the repository is private?

Still rotate. Everyone with access, every CI system that clones it, every fork and every backup now holds the secret. Private lowers the exposure; it does not remove it.

How do I stop secrets being committed in the first place?

Keep secrets out of files that get committed, scan before commit with a pre-commit hook, turn on push protection if your Git host offers it, and inject credentials into build jobs from a secrets manager instead of storing them in the repository.