Treat a committed credential as potentially compromised. Notify the credential owner and disable or revoke exposed authority promptly; map its permissions, consumers and exposure window in parallel. Replace access where legitimate workloads need it, then review historical activity. An issuer check can show that a credential is already inactive, but cannot establish that nobody copied or used it earlier. Remove the value from current code and decide separately whether Git history needs coordinated cleanup. Deleting a line or force-pushing a rewritten branch does not disable a token that someone already copied. GitHub's leaked-secret response guide makes revocation the central containment step.
The order changes when disabling the credential immediately would stop a critical service. The owner may need a short, controlled replacement window, with incident leadership accepting the continued exposure and setting a deadline. A public, active production credential should receive a faster response than a confirmed nonfunctional sample in a private test file. “Private repository” still means accessible to collaborators, automations and copies outside your direct control; it is not proof the secret stayed private.
A safe illustrative case
Illustrative incident, not a customer event or evidence of unauthorized use: Northstar Billing's deployment repository contains an AWS IAM access key in an old workflow configuration. The repository is private today, but the team does not yet know whether it was previously public or cloned outside the company. The value appears at commit OLD_REV. The key's name suggests it deploys the invoice service, but naming is not evidence of its effective permissions. A developer spots it during a review on Monday morning.
The platform engineer's first useful artifact is a restricted incident record, with no secret value pasted into tickets or chat:
| Question | Initial answer | How to check |
|---|---|---|
| Which credential? | AWS access key ID ending in a recorded four-character suffix; secret value withheld | IAM owner record and the code location in a restricted view |
| First possible exposure? | At or before OLD_REV; exact clone history unknown |
Commit and repository visibility history |
| Still active? | Unknown at discovery | IAM credential status at the issuer |
| What could it reach? | Deployment role suspected | Attached policies, role trust, resource policies, permission boundaries and account controls |
| Who needs it? | Release job suspected | Workflow references, secret store, deploy logs and service owner |
| Was it used unexpectedly? | Unknown | CloudTrail and other available provider logs over the exposure window |
| Immediate decision | Treat as potentially live; assign IAM owner and incident lead | Time-stamped response record |
GitHub's secret scanning alert guidance describes provider validity checks for supported patterns, but the issuer is the most reliable source of credential status. An alert is a prompt to investigate; absence of an alert is not a clearance decision. Do not paste the full secret into a search query, issue, screenshot or support chat to discover its owner.
1. Establish the exposure without spreading it
Input: the alert or code location, repository and commit IDs, credential type, and a restricted owner directory. Owner: platform engineer with security or incident lead. Output: a bounded exposure record. Check: the record contains an identifier sufficient to ask the issuer about the credential, but not the usable secret.
Find the first known commit and the current branches or tags that reference it. Check whether the value also reached pull requests, CI logs, build artifacts, documentation, package releases or a second repository. GitHub recommends checking code, issues and pull requests during leak remediation. Keep an explicit “not checked” list: a quick repository search does not inspect every fork, local clone, artifact or external cache.
Classify the credential by issuer and authority, not filename. An AWS access key, GitHub token, database password and signing key need different revocation controls and evidence. If you cannot identify the issuer, first contain the systems the credential might reach and escalate to the relevant owner. Avoid trial logins with the exposed value. They can create activity that obscures the incident and may violate the credential owner's process.
2. Contain the old authority at its issuer
Ask the issuer owner to revoke or deactivate the credential at the issuer, not merely remove its copy from Git. For an AWS IAM access key, AWS allows the owner to make a key inactive before deletion (AWS access-key update guide). If immediate deactivation would stop a critical workload, the incident lead must decide how long the old authority can remain active, who accepts that exposure and what compensating restriction applies. Record that decision with an expiration time.
Containment may need more than one button. A long-lived key might have obtained temporary credentials before it was disabled; AWS says those credentials may remain valid until expiry unless their permissions are separately changed or revoked (temporary credential controls). Ask the issuer owner to identify any surviving authority and take the appropriate containment action. The detailed acceptance record belongs in secret rotation verification.
For Northstar, the IAM owner disables the exposed key. The release owner pauses deployments until a replacement path is available. Security records “old key disabled; derived-session check pending” rather than declaring the whole incident resolved.
3. Hand service recovery to the owner
The platform engineer's job is to make the outage and access tradeoff explicit. Name the affected service, its owner, the old authority now unavailable and the earliest required operation. Have that owner use an approved secret delivery path for replacement access; never commit the new value, print it to CI logs or paste it into the incident ticket. Whether every consumer actually moved is a separate verification job, covered in the next guide.
Northstar's decision becomes harder when the release is an urgent billing correction. In this synthetic continuation, the repository owner also finds a 40-minute public-visibility interval before discovery. The incident lead keeps the old key inactive and uses an already approved operator release route with separate, scoped authority. If no such route existed, delivery would remain paused until a replacement was reviewed; the urgent release would not make the exposed key private again.
The source-free authority map is:
OLD_KEY -> deployment IAM user -> AssumeRole -> release-role session S1
approved operator identity -> separate controlled release route
Deactivating OLD_KEY closes new authentication with that key. It does not by itself prove S1 has lost authority. The IAM owner records S1's role, issue/expiry evidence and applicable permission or revocation action; the incident lead considers disruption to other sessions before a role-wide response. AWS's temporary-credential controls explain why permissions and surviving sessions need separate handling.
The 10:00 handoff is precise: “Old key inactive; ordinary deployment job paused; urgent correction assigned to the approved operator route; derived release-role session containment still being verified. Repository was briefly public, so external copying cannot be excluded.” A successful operator release restores one business operation without closing the exposure investigation or the remaining consumers' migration.
4. Investigate what happened during the exposure window
Start the review at the earliest time the credential might have been available, not the day a scanner found it. Compare expected workload activity with actual provider events: principal, key or token ID, source, time, action, target and region where recorded. For AWS, the CloudTrail userIdentity reference describes the access key ID field; temporary credentials can have their own key ID, so connect session creation to later activity when possible.
Look for actions that exceed the workload's normal job: new identities or keys, privilege changes, unfamiliar role assumptions, data reads or exports, unusual regions and persistence changes. Ask the service owner whether the same actions could result from a scheduled release or recovery job. Save a source-free timeline and protected log references. Preserve relevant logs under the incident retention process before their normal expiry; do not add sensitive log extracts to a public issue.
Uncertainty matters: incomplete CloudTrail coverage, missing data events, provider retention limits or shared credentials can make attribution impossible. “No unusual events found in logs available from Tuesday onward” is a defensible statement. “The key was never abused” is not. If evidence suggests unauthorized activity, widen incident response to the affected accounts, data and customers under the organization's incident plan. This guide is an initial response method, not an exhaustive forensic playbook.
The Northstar timeline can stay compact and source-free:
| Time | Observation or decision | Evidence and owner |
|---|---|---|
| Monday 09:10 | Developer reports the old Git commit; current key state unknown | Commit ID and private alert reference; platform engineer |
| Monday 09:25 | IAM owner confirms key active and disables it | Issuer status and change event; IAM owner |
| Monday 09:35 | Release job is paused; replacement owner named | Release decision record; incident lead |
| Monday 10:20 | Available audit review begins at the earliest known commit | Log range and gaps; security reviewer |
| Pending | Derived-session check, history decision and consumer migration | Named owners and deadlines, not assumed complete |
These times are invented to show the shape of a handoff. In a real case, capture actual UTC timestamps, an immutable evidence reference and any clock or log-ingestion delay. A copied key might have been exposed before the first commit you can find.
5. Remove the value from code, then decide on history cleanup
Remove the literal value from the current file, update code to read from the approved secret path, and review the change so the replacement is not exposed. The old Git commit will still exist after a normal deletion or revert. GitHub's history removal guide says revocation or rotation comes first and may be sufficient for a credential. History rewriting changes commit IDs and can affect signatures, branches, pull requests, clones and forks. It also creates a recontamination risk when collaborators push old history back.
Decide whether to rewrite only after the incident lead, repository owner and affected collaborators understand those costs. A nonrotatable private key, personal data, contractual requirement or public cached copy may make removal more urgent than for an already revoked API token. Coordinate branch freezes, contributor instructions and any GitHub Support request; follow the provider's current procedure. Do not force-push history as an unreviewed solo fix. You cannot recall copies someone already downloaded, and a clean repository history is not proof of physical erasure from every cache or backup.
Make two different history decisions
The same commit contains a replaceable deployment token and a confidential architecture attachment. Revoking the token addresses its authority. The attachment has no issuer that can revoke what a reader learned.
| Material | Immediate security action | Git decision in this synthetic case |
|---|---|---|
| Exposed deployment token | Disable old authority; address derived sessions and consumers | Remove current literal; repository owner records whether coordinated rewrite adds enough value after revocation |
| Confidential architecture attachment | Restrict further access and assess recipients/copies | Coordinate removal from reachable history and provider-supported cached views where possible; track known copies separately |
The incident lead chooses coordinated history cleanup for the attachment, preserving restricted evidence first and giving collaborators instructions to avoid restoring old history. That decision is not a claim of universal erasure. GitHub's removal guide describes rewrite effects and limits involving clones, forks and cached views.
The final first-response record has four independently named states: old credential containment, release recovery, historical exposure investigation and repository cleanup. Here containment is pending S1 verification, the urgent release has an approved route, historical copying is unknown, and cleanup has an owner and coordinated plan. None becomes complete merely because the secret-scanning alert is closed.
An incident can be contained while investigation remains open. Close those states separately. The first-response note should say what was confirmed, what remains unknown, which authority was disabled and who owns the next check. A secret-scanning alert marked “resolved” is not by itself evidence that the provider revoked the secret or that all consumers migrated.
For one exposed credential, record its issuer, containment time, service-recovery owner and next unresolved check without copying its value. For the next decision, use how to verify a secret is fully rotated after exposure. If the credential came from a deployment workflow, review CI credential and token scopes before issuing its replacement.