Evidence ledger 26 sources Checked 20 Sep 2026

Evidence ledger

One row per claim in When the secret leaks: the hour after exposure: who published it, what grade it carries, when it was written, when the link was last checked, and the quote or figure it rests on. Nothing in the guide is cited from memory, so anything not in this table is not in the guide.

Guide: When the secret leaks: what four supply-chain incidents and three platforms' revocation machinery say about the hour after exposure Category: security-and-identity · Research date: 2026-09-20 · All links fetched 2026-09-20.

Corpus limit, stated up front. This session's network egress policy resolved github.com and raw.githubusercontent.com and no other host. Engineering blogs, conference sites, paper hosts, vendor incident pages (CircleCI, Cloudflare, Heroku) and even blog.pypi.org were refused by the proxy, and this skill does not permit citing from memory. So the corpus is the GitHub record: security advisories and their database entries, incident issue threads written while the incidents ran, the scanners' own repositories and rejected pull requests, Kubernetes enhancement proposals, the AWS quarantine policy as tracked by a third-party diff repository, platform documentation read from its source repository, and git history read from shallow clones. The well-known 2022–2023 credential-leak postmortems (Heroku, CircleCI, Cloudflare) could not be fetched and are therefore absent, not because they do not matter but because they were unreachable; the page says what that absence costs. No engineering-blog post, talk or paper is cited, because none could be fetched.

One row per claim. The right-hand column is copied text, not paraphrase.

# Org Title Tier Published Checked URL Claim taken from it Supporting quote or figure
1 GitHub Advisory Database CVE-2025-30066 / GHSA-mrrh-fwg8-r2c3 (tj-actions/changed-files) postmortem 2025-03-15, modified 2025-10-22 2026-09-20 https://github.com/advisories/GHSA-mrrh-fwg8-r2c3 One compromised action exposed the CI secrets of tens of thousands of repositories in a one-day window. "A supply chain attack compromised the tj-actions/changed-files GitHub Action, impacting over 23,000 repositories"; "The vulnerability existed between March 14 and March 15, 2025".
2 GitHub Advisory Database GHSA-mrrh-fwg8-r2c3, mechanism section postmortem 2025-03-15 2026-09-20 https://github.com/advisories/GHSA-mrrh-fwg8-r2c3 The payload harvested secrets from runner memory and published them in build logs rather than exfiltrating to an attacker host. "This script extracted secrets from the Runner Worker process memory and printed them in GitHub Actions logs, making them publicly accessible in repositories with public workflow logs."
3 GitHub Advisory Database GHSA-mrrh-fwg8-r2c3, IoC section postmortem 2025-03-15 2026-09-20 https://github.com/advisories/GHSA-mrrh-fwg8-r2c3 The attacker rewrote existing version tags rather than shipping a new version, so no consumer action was needed to become vulnerable. "Retroactively updated tags pointing to the malicious commit: v1.0.0 … v35.7.7-sec … v44.5.1", all pointing at commit 0e58ed8671d6b60d0890c21b07f8835ace038e67.
4 tj-actions community Issue #2463, "Multiple tags in this action are compromised" postmortem 2025-03-14 2026-09-20 https://github.com/tj-actions/changed-files/issues/2463 Detection came from an outside monitoring vendor noticing a tag move, not from the maintainer or the platform. Opening report by varunsh-coder: "this tag was just updated 3 hours back and is potentially exfiltrating credentials … Reported the issue via the email address provided in the security.md file and also reported it via private vulnerability disclosure to generate a CVE."
5 tj-actions community Issue #2463, comment by AdnaneKhan, 2025-03-15 00:01 UTC postmortem 2025-03-15 2026-09-20 https://github.com/tj-actions/changed-files/issues/2463 Commit-SHA pinning, the recommended defence, was actively undone by dependency-update automation during the incident. "We even see some repositories using the backdoored commit by hash after updates by Renovate".
6 tj-actions community Issue #2463, comments by ElijahLynn, 2025-03-15 postmortem 2025-03-15 2026-09-20 https://github.com/tj-actions/changed-files/issues/2463 The leak route was public logs, and the encoding was enough to defeat the platform's secret masking. "I've just confirmed that it is printing double base64 encoded secrets in runner job logs … double base64 --decode that output and boom, there is a github_token." Also: "Every tag got pointed to this malicious commit".
7 tj-actions community Issue #2464, first responses postmortem 2025-03-14 2026-09-20 https://github.com/tj-actions/changed-files/issues/2464 The project's first responder to its own compromise report was a marketing bot. Report title: "Pretty sure this repo got hacked and if you use this it will send your secrets to a hacker"; first reply, from tj-actions-bot, 38 seconds later: "Thanks for reporting this issue, don't forget to star this project if you haven't already to help us reach a wider audience."
8 GitHub Advisory Database CVE-2025-30154 / GHSA-qmg3-hpqr-gqvc (reviewdog/action-setup) postmortem 2025-03-19 2026-09-20 https://github.com/advisories/GHSA-qmg3-hpqr-gqvc The reviewdog compromise window was under two hours, three days before tj-actions, and pinning downstream actions did not help. "reviewdog/action-setup@v1 was compromised March 11, 2025, between 18:42 and 20:31 UTC, with malicious code added that dumps exposed secrets to Github Actions Workflow Logs"; five downstream actions "would also be compromised, regardless of version or pinning method".
9 reviewdog Issue #2079, maintainer security advisory by haya14busa postmortem 2025-03-18, updated 2025-03-23 2026-09-20 https://github.com/reviewdog/reviewdog/issues/2079 Write access had been granted automatically to a large contributor pool, which is the surface the attacker used. "Contributors who submitted to reviewdog/action-* repositories were automatically invited to the @reviewdog/actions-maintainer team, which had write access to these repositories. The team consisted of 118 members at the time of writing."
10 reviewdog Issue #2079, update of 2025-03-23 postmortem 2025-03-23 2026-09-20 https://github.com/reviewdog/reviewdog/issues/2079 The credential that opened this incident was stolen in a different, earlier incident; leaks chain. "We have identified the contributor whose Personal Access Token (PAT) was compromised and subsequently used by attackers to overwrite the reviewdog tags. … The compromised PAT originated from an attack on another repository." Remediation: "most members of the reviewdog organization, including the contributor in question, no longer have write permissions."
11 Nx (nrwl) GHSA-cxm3-wv7p-598c, "s1ngularity" advisory postmortem 2025-08-27, modified 2026-07-28 2026-09-20 https://github.com/nrwl/nx/security/advisories/GHSA-cxm3-wv7p-598c The npm publishing token was stolen through a PR-title bash injection combined with pull_request_target. "Validate PR title … echo \"Validating PR title: ${{ github.event.pull_request.title }}\""; "the PR validation workflows triggered a run of the publish.yml with this malicious commit and sent our npm token to an unfamiliar webhook. We believe this is how the user got a hold of the NPM token".
12 Nx (nrwl) GHSA-cxm3-wv7p-598c, timeline postmortem 2025-08-27 2026-09-20 https://github.com/nrwl/nx/security/advisories/GHSA-cxm3-wv7p-598c From first malicious publish to full token revocation took about five and a half hours, and the durable fix was to stop having publish tokens at all. Timeline (EDT, Aug 26–27 2025): malicious versions published from 6:32 PM; team noticed 9:58 PM; npm removed versions 10:44 PM; "11:57 PM - All NPM tokens with permissions for publishing were revoked"; next day, "All NPM packages have also been changed to use the new Trusted Publisher mechanism which does not utilize npm tokens".
13 Nx (nrwl) GHSA-cxm3-wv7p-598c, malware behaviour postmortem 2025-08-27 2026-09-20 https://github.com/nrwl/nx/security/advisories/GHSA-cxm3-wv7p-598c The malware's output was more leaked credentials, published as GitHub repositories under victims' own accounts; the platform then deleted some of that evidence. "a postinstall script that scanned user's file system for text files, collected paths, and credentials … posted as an encoded string to a github repo under the user's Gi[thub account]"; "Unfortunately, Github may have proactively deleted the repo for you."
14 Ultralytics community Issue #18027, "Discrepancy between what's in GitHub and what's been published to PyPI for v8.3.41" postmortem 2024-12-05 2026-09-20 https://github.com/ultralytics/ultralytics/issues/18027 The compromise was detected by a user diffing the published wheel against the repository, not by the maintainer or either platform. "Code in the published wheel 8.3.41 is not what's in GitHub and appears to invoke mining. Users of ultralytics who install 8.3.41 will unknowingly execute an xmrig miner." (metrizable, 2024-12-05 06:34 UTC).
15 Ultralytics community Issue #18027, automated first response postmortem 2024-12-05 2026-09-20 https://github.com/ultralytics/ultralytics/issues/18027 The project's triage bot advised installing the compromised package while the report sat unread. UltralyticsAssistant, 35 seconds after the report: "we recommend upgrading to the latest ultralytics version … pip install -U ultralytics". Human confirmation came 94 minutes later (Skillnoob, 08:08 UTC: "the package on PyPi is compromised … v8.3.40 is safe to use").
16 Ultralytics Commit 68c63a7e5, "8.3.43 PyPI publishing security fix" (PR #18052) source 2024-12-05 2026-09-20 https://github.com/ultralytics/ultralytics/commit/68c63a7e5603f34069107e3bf60039eec071e620 The day-one fix replaced a stored personal access token with the runner's ephemeral token and removed pull_request_target title handling from the publish workflow. Diff removes GH_TOKEN: ${{ secrets._GITHUB_TOKEN }} in favour of GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}, and deletes the branch reading github.event.pull_request / pull_request_target PR titles into shell variables.
17 Ultralytics Commits bf6317011 and e0f8eda36 (PRs #18095, #18111) source 2024-12-07 / 2024-12-08 2026-09-20 https://github.com/ultralytics/ultralytics/commit/e0f8eda366c7cf08a1c311a17eaaaf87914f8012 Remediation arrived in stages over four days: cache disabled on Dec 7, publish pipeline split for security on Dec 8, three and four days after the first "fix". Commit log: 2024-12-07 "Update publish.yml with --no-cache (#18095)", 2024-12-07 "Add CI cache pruning (#17664)", 2024-12-08 "ultralytics 8.3.48 split PyPI publish jobs for security (#18111)".
18 Ultralytics Repository tag record source checked live 2026-09-20 https://github.com/ultralytics/ultralytics/tags Versions 8.3.45 and 8.3.46 exist only on the registry, not in the repository: they were published with the stolen registry token after the repository-side fix. Inference from the tag record; the second wave itself is corroborated by the versions' absence and by press coverage this session could not fetch. Shallow clone of the full tag list, 2026-09-20: v8.3.43 (2024-12-05) and v8.3.44 (2024-12-06) exist; git log v8.3.45 and v8.3.46 return "unknown revision"; v8.3.41 and v8.3.42 tags have been deleted.
19 GitHub (actions/runner) Issue #475, "usage of add-mask still echoes the value to the log" source 2020-05-11, still open 2026-09-20 https://github.com/actions/runner/issues/475 Log masking is literal string matching registered before output; anything transformed, or printed before registration, is not masked. This is the mechanism the 2025 attacks' double-base64 encoding exploited. "The mask needs to be added before the output is registered. … The output is streaming, so too late if value is already printed." (ericsciple, runner maintainer, 2020-05-28). Issue open with 75 comments as of 2026-09-20.
20 GitHub Docs token-expiration-and-revocation.md vendor current, checked from source repo 2026-09-20 https://github.com/github/docs/blob/main/content/authentication/keeping-your-account-and-data-secure/token-expiration-and-revocation.md For its own tokens, GitHub revokes automatically on public exposure, with no owner in the loop. "If a valid OAuth token, GitHub App token, or personal access token is pushed to a public repository or public gist, the token will be automatically revoked."
21 GitHub Docs secret-scanning-for-partners.md vendor current 2026-09-20 https://github.com/github/docs/blob/main/content/code-security/concepts/secret-security/secret-scanning-for-partners.md For partners' tokens, the same scanner only notifies; the issuing provider decides whether to revoke. "The service provider validates the string and then decides whether they should revoke the secret, issue a new secret, or contact you directly. Their action will depend on the associated risks to you or them."
22 GitHub Docs secret-scanning.md vendor current 2026-09-20 https://github.com/github/docs/blob/main/content/code-security/concepts/secret-security/secret-scanning.md The platform's own remediation guidance is revocation first; history rewriting is optional. "When you receive an alert, rotate the affected credential immediately to prevent unauthorized access. While you can also remove secrets from your Git history, this is time-intensive and often unnecessary if you've already revoked the credential."
23 GitHub Docs push-protection.md vendor current 2026-09-20 https://github.com/github/docs/blob/main/content/code-security/concepts/secret-security/push-protection.md The platform's newest control moves detection before the leak instead of after it. "Rather than alerting you to credential leaks after the fact, push protection blocks pushes that contain secrets before they reach your repository."
24 GitHub Docs validity-checks.md vendor current 2026-09-20 https://github.com/github/docs/blob/main/content/code-security/concepts/secret-security/validity-checks.md The platform now tests found secrets against the issuer's API to triage them, the same design the gitleaks maintainer declined. "{GitHub} will periodically check the validity of a detected credential by sending the secret to the issuer and testing it against APIs provided by that service."
25 GitHub Docs what-is-scanned.md (reusable) vendor current 2026-09-20 https://github.com/github/docs/blob/main/data/reusables/secret-scanning/what-is-scanned.md The leak surface the scanner covers goes far beyond code. Scanned: "Descriptions and comments in issues … Titles, descriptions, and comments in pull requests … Wikis … Secret gists".
26 PyPI (pypa/warehouse) warehouse/integrations/secrets/config.py source current 2026-09-20 https://github.com/pypa/warehouse/blob/main/warehouse/integrations/secrets/config.py PyPI receives leak disclosures from two scanning origins, GitHub and Google's Deps.dev. _github_origin = utils.DisclosureOrigin(name="GitHub", … verification_url="https://api.github.com/meta/public_keys/token_scanning"); _depsdev_origin = utils.DisclosureOrigin(name="Deps.dev", …).
27 PyPI (pypa/warehouse) warehouse/integrations/secrets/utils.py source current 2026-09-20 https://github.com/pypa/warehouse/blob/main/warehouse/integrations/secrets/utils.py On a verified disclosure PyPI deletes the token first and emails the owner second; no human is in the loop. _analyze_disclosure sequence: verify_signature_only(raw_macaroon=disclosure.token) then macaroon_service.delete_macaroon(macaroon_id=…) then send_token_compromised_email_leak(…).
28 AWS via z0ph/MAMIP policies/AWSCompromisedKeyQuarantineV3 source tracked 2024-08-21 → 2026-03-16 2026-09-20 https://github.com/z0ph/MAMIP/blob/master/policies/AWSCompromisedKeyQuarantineV3 AWS's automated response to a leaked key is a deny-list fence, not revocation: the key keeps working except for 98 enumerated actions. Policy is a single "Effect": "Deny" statement over 98 actions (count from the fetched JSON, 2026-09-20) including iam:CreateUser, ec2:RunInstances, lambda:CreateFunction, cloudtrail:LookupEvents.
29 AWS via z0ph/MAMIP Quarantine policy family change history source 2020-08-11 → 2026-03-16 2026-09-20 https://github.com/z0ph/MAMIP/commits/master/policies/AWSCompromisedKeyQuarantineV3 The deny list has grown for six years and across three policy generations: 28 actions (V1) to 89 (V2) to 98 (V3). MAMIP git history (cloned 2026-09-20): V1 first tracked 2020-08-11; V2 first tracked 2021-04-22; V3 first appears 2024-08-21, last updated 2026-03-16 ("Policy Version v3"). Action counts computed from the three policy JSONs.
30 Kubernetes SIG Auth KEP-1205, Bound Service Account Tokens adr created 2019-08-06, stable v1.22 2026-09-20 https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/1205-bound-service-account-tokens/README.md The project's own statement of why long-lived, unscoped tokens are unacceptable. "JWTs are not audience bound. Any recipient of a JWT can masquerade as the presenter to anyone else. … JWTs are not time bound. A JWT compromised via 1 or 2, is valid for as long as the service account exists."
31 Kubernetes SIG Auth KEP-2799, Reduction of Secret-based Service Account Tokens adr created 2021-06-25, stable v1.30 2026-09-20 https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/2799-reduction-of-secret-based-service-account-token/README.md Removing the legacy long-lived token took three feature gates and reached stable only in v1.30 (2024), eleven years after the original design. kep.yaml: "creation-date: 2021-06-25 … stage: stable … latest-milestone: v1.30"; feature gates LegacyServiceAccountTokenNoAutoGeneration, LegacyServiceAccountTokenTracking, LegacyServiceAccountTokenCleanUp.
32 Truffle Security trufflehog README source current 2026-09-20 https://github.com/trufflesecurity/trufflehog The verification-first design: the scanner logs in with what it finds. "TruffleHog classifies over 800 secret types … For every secret TruffleHog can classify, it can also log in to confirm if that secret is live or not. This step is critical to know if there's an active present danger or not."
33 Gitleaks gitleaks README source current 2026-09-20 https://github.com/gitleaks/gitleaks The other camp: detection only, and the project is now feature-frozen. "Gitleaks is a tool for detecting secrets"; README warning: "Gitleaks is feature complete. I'm not merging new features into Gitleaks. Future releases will be security patches only. I'm shifting my focus to Betterleaks."
34 Gitleaks PR #1515 "Verify feature" (also #1519) source opened 2024-09-21, closed unmerged 2026-09-20 https://github.com/gitleaks/gitleaks/pull/1515 The maintainer himself built verification for gitleaks, 43 commits, and closed it without merging; the reason is not recorded on the PR. PR header: "Verify feature #1515 · zricethezav wants to merge 43 commits … Closed"; body: "experimental verify feature"; commit messages include "feat(verify): add opt-in — This feature is a preview."
35 Betterleaks betterleaks README source current 2026-09-20 https://github.com/betterleaks/betterleaks In the successor tool, verification shipped as a headline feature; the rejected design won. "Secrets Validation: Validate if a detected secret is active by making asynchronous HTTP requests directly from within the rule definition". "It is maintained by the folks who made Gitleaks, including the original author."
36 AWS aws-actions/configure-aws-credentials README vendor current 2026-09-20 https://github.com/aws-actions/configure-aws-credentials The cloud vendor's recommended CI credential is one that does not exist until the job runs. "Quick Start (OIDC, recommended)"; "Use temporary credentials when possible. OIDC is recommended because it provides temporary credentials and it's easy to set up."
37 GitHub Docs openid-connect.md (Actions concepts) vendor current 2026-09-20 https://github.com/github/docs/blob/main/content/actions/concepts/security/openid-connect.md The structural alternative to storing secrets: per-job tokens that expire on their own. "your cloud provider issues a short-lived access token that is only valid for a single job, and then automatically expires"; benefit listed first: "No cloud secrets."
38 OpenSSF scorecard docs/checks.md, Token-Permissions adr current 2026-09-20 https://github.com/ossf/scorecard/blob/main/docs/checks.md The ecosystem's measurable proxy for this whole failure class is workflow token scope. "Token-Permissions — Risk: High (vulnerable to malicious code additions) … attackers may use a compromised token with write access to, for example, push malicious code into the project."
39 Thinkst canarytokens README source current 2026-09-20 https://github.com/thinkst/canarytokens Deliberately planted credentials as tripwires are an open-source, self-hostable technique. "Canarytokens help track activity and actions on your network." Repository is the self-hostable server behind canarytokens.org.