On May 18, Krebs on Security reported that a CISA contractor had exposed AWS GovCloud keys, plaintext database passwords, and internal credentials in a public GitHub repository named "Private-CISA." The repo was taken down within hours. CISA told Krebs there was "no indication that any sensitive data was compromised."
We detected the live keys in the GitHub repository from our public monitoring. The AWS keys that Krebs and researcher Philippe Caturegli focused on were one part of the story. But buried in the Terraform configs was something worse:
A GitHub App Key With Write Access to CISA's Org
In the runners-caws-tf/environments/dso-us-east-1/ directory sat a file called github-app.key, a 2048-bit RSA private key for a GitHub App called arc-runners-dso (App ID 3464825, found in the terraform.tfvars in the same directory).
On May 20, two days after Krebs published, we constructed a JWT from this key and authenticated to the GitHub API. HTTP 200. The key was fully active.
The app was owned by the cisa enterprise account and installed on the cisa-it GitHub organization with access to all repositories. Its permissions:
An attacker with this key could register a malicious self-hosted runner in the cisa-it organization. Any GitHub Actions workflow configured to run on self-hosted runners would execute on the attacker's machine, giving them access to repository secrets, deployment credentials, and whatever else those workflows touch.
We reported the key to Brian Krebs who reported it to CISA.
When we rechecked on May 21, the GitHub App key returned 401. Someone had revoked it within 24 hours of our validation.
Other Credentials Still Live
The GitHub App key was the most critical finding, but it wasn't the only credential still active days after the Krebs report. We identified additional live tokens granting access to vendor-specific services. Lower impact than org-wide GitHub admin, but still unrevoked and still valid.
These were multi-layer encoded credentials embedded in Terraform configs that standard scanning tools either missed entirely or flagged as generic findings without verifying them. We've included the details in our disclosure to CISA.
What Else Was In There
Beyond the confirmed-active credentials, the repository contained dozens of additional secrets across multiple categories:
svc.artifactory, scattered across Dockerfiles, .npmrc, .credentials, and pip configs. Expiry dates range from Nov 2026 to Apr 2027.[Env][Service]1234^%$#. DSO Artifactory: DSOArt!factory1234^%$#. Production is guessable.sonarqube.dso.cisa.dhs.gov and sonarqube.sbx.cisa.dhs.gov. Internal CA, no CT logs, OCSP on internal DNS only.wizfedramp.azurecr.us. Auth returned 401, likely rotated.Why Three Days to Revoke a GitHub Key
The GitHub App key is instructive. It's a file called github-app.key sitting alongside dozens of other .pem files in a Terraform directory. Standard secret scanners flag it as a generic "PrivateKey" finding, the same classification as every other RSA key in the repo. To understand what it actually grants access to, you need to pair it with the App ID from a separate terraform.tfvars file, construct a JWT, and call the GitHub API. (TruffleHog will soon do this automatically end to end.)
Rotation isn't always easy or fast, and the first step is knowing what's still live. That's where TruffleHog helps.
CISA Is Not an Outlier
When we tracked 10,000 leaked secrets from public GitHub repositories over 31 days, 74% were still valid a month later. When keys were revoked, it almost always happened in the first three days, or not at all.
Deleting the repo doesn't even remove the data. As we documented in our research on Cross Fork Object References, anyone can access commit data from deleted and even private repositories on GitHub, as long as a single fork exists. GitHub's public events API and the GitHub Archive preserve commit hashes and content indefinitely. That is exactly how we reconstructed this repository after it was taken down.
github/github. When we scanned 400 terabytes of Common Crawl data, the dataset used to train LLMs like DeepSeek, we found 11,908 live API keys. They leak everywhere code is written, shared, or archived.
The CISA incident also highlights why scanning encoded and archived data matters. The CrowdStrike credential in this repo was base64-encoded inside a JSON blob, itself base64-encoded inside a Terraform string. GitHub's built-in secret scanning doesn't catch base64-encoded secrets. TruffleHog's recursive decoder does. It's the reason we found the credential in the first place.
The Bigger Picture
The Private-CISA repository also exposed a detailed map of CISA's GovCloud infrastructure that persists regardless of credential rotation:
- 14 AWS account IDs spanning dev, sandbox, DSO, test, staging, and production environments
- EKS cluster configurations with node group sizes, IAM roles, and VPC networking
- Complete Helm values for CrowdStrike Falcon, Wiz, Splunk, SonarQube, and Artifactory
- CI/CD pipeline definitions for Jenkins, GitHub Actions, and Argo CD
- Network topology including VPC CIDRs, subnet configurations, and security group rules
An attacker who archived the repository before it was taken down now has a comprehensive map of CISA's internal architecture. That doesn't expire.
Disclosure Timeline
Recommendations
Secret rotation runbooks need to cover all credential types, not just AWS keys. A leak like this touches half a dozen vendor systems, each with its own revocation process. GitHub Archive preserves public repository contents indefinitely. Taking down a repo does not undo the exposure. And predictable password patterns are equivalent to no password at all once any single instance is exposed.