What happened after we pushed our .env to a public repo

rahulgovind5171 pts0 comments

What happened after we pushed our .env to a public repo | Tachyon Blog

TL;DR

We published monitored AWS, Anthropic, and Postgres credentials in public GitHub repos. GitHub found them within seconds and AWS partially quarantined its key, but outside clients still tried the credentials and reached Secrets Manager. The two keys stored there were fetched but not used during our observation window.

If an API key reaches a public repo, how long do you have before someone uses it? We wanted to find out, so we intentionally committed .env files containing canary credentials to public GitHub repos.

The setup

Using Tripwire, we built a canary environment with:

An Anthropic account.

An AWS account with access to:

AWS Secrets Manager.

A Postgres database containing fake records.

A build server.

We ran the experiment twice with fresh canaries. The first .env held AWS, Anthropic, and Postgres credentials. The second held AWS and Postgres credentials; its AWS key could also read an Anthropic key and the build server's SSH private key from Secrets Manager.

We logged AWS calls, Anthropic requests, Postgres queries, and SSH sessions. Then we asked Claude to push the repos.1

What we saw

GitHub flagged the credentials within seconds but sent no email. Fifteen seconds after one push, AWS attached AWSCompromisedKeyQuarantineV3 to the exposed IAM user. AWS emailed us less than two minutes later. The key still worked.

The policy blocks selected high-cost actions, but it neither revokes the key nor blocks ListSecrets or GetSecretValue.

Each public credential was tried within about five minutes. The AWS key was used to identify the account, the same source logged in to Postgres without querying it, and Anthropic received a rate-limited request against its zero-credit key.

Seven minutes after the push, the source that had checked the AWS key with TruffleHog switched to Boto3, listed the secrets, and fetched both values. We saw no outside use of either credential through July 21.

TIME (UTC) EVENT RESULT<br>Jul 17 21:27:59 iam:AttachUserPolicy Quarantine policy attached<br>Jul 17 21:33:23 sts:GetCallerIdentity Key accepted; TruffleHog user agent<br>Jul 17 21:35:00 secretsmanager:ListSecrets Secret list returned; Boto3 user agent<br>Jul 17 21:35:00 secretsmanager:GetSecretValue 2 values returned; Boto3 user agent

CloudTrail event summary

A database restart forced us to publish a new URL. Six minutes later, an unidentified client used it to log in and query both fake tables.

2026-07-18 01:32:49 UTC statement: SELECT * FROM "employees" LIMIT 300<br>2026-07-18 01:32:49 UTC statement: SELECT * FROM "customers" LIMIT 300

Postgres statement log

Who came knocking

We could identify some networks and client software, but not the people behind them. Some traffic may have been defensive.

Source<br>User Agent / Identifier<br>Activity

54.39.190.x, OVH (AS16276)<br>GitGuardian in Postgres; python-requests/2.33.1 in AWS<br>Checked the AWS identity and logged in to Postgres; ran no queries

104.250.131.x, GorillaServers (AS53850)<br>TruffleHog, then Boto3<br>Enumerated AWS and fetched both Secrets Manager values

171.25.193.x, DFRI (AS198093), a listed Tor exit<br>N/A<br>Made one AWS identity call

185.14.97.x, Gigahost/Terrahost (AS56655)<br>N/A<br>Logged in to Postgres and read both fake tables

Why this is both surprising and not

Scanning public repos for common credential formats has been automated for years, so the first few minutes were not surprising. What surprised us was where it stopped. One client followed the AWS key into Secrets Manager, fetched two more credentials, and did nothing else we could see.

LLMs make the next step easier because they can inspect an unfamiliar repo and work out what each credential unlocks. We expected more of that here. Our logs cannot tell whether an LLM was involved. The pause may reflect a handoff between collectors and operators,2 or it may simply have been defensive scanning.

The takeaway

The obvious defense is to scan before every push. Add TruffleHog as a pre-commit hook and run it again in CI. GitHub's scanner helped, but it acted after the credentials were public.

The less obvious defense is to plant credentials that should never be used. Any request against one is a high-confidence alert that someone reached your secrets. Tripwire can generate a similar monitored repository with tripwire bundle download.

There is no single answer to how long you have. The part you can control is how quickly you find out.

1. Claude initially refused because publishing secrets was unsafe. We explained that the keys were canaries in isolated systems, and it agreed. It then made the opposite argument: the experiment would teach us little because GitHub would immediately detect and revoke the keys, citing GitHub blog posts. Half right. Detection was immediate; revocation was not. ↩

2. The UK National Cyber Security Centre and National Crime Agency describe how different actors gather, validate, broker, and exploit access in...

postgres credentials public secrets github anthropic

Related Articles