SecurityHoneypotsResearch

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

Rahul Govind·July 20, 2026·5 min read

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

The canary workspace and the paths between its credentials.

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
Jul 17 21:27:59    iam:AttachUserPolicy               Quarantine policy attached
Jul 17 21:33:23    sts:GetCallerIdentity              Key accepted; TruffleHog user agent
Jul 17 21:35:00    secretsmanager:ListSecrets         Secret list returned; Boto3 user agent
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
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 User Agent / Identifier Activity
54.39.190.x, OVH (AS16276) GitGuardian in Postgres; python-requests/2.33.1 in AWS Checked the AWS identity and logged in to Postgres; ran no queries
104.250.131.x, GorillaServers (AS53850) TruffleHog, then Boto3 Enumerated AWS and fetched both Secrets Manager values
171.25.193.x, DFRI (AS198093), a listed Tor exit N/A Made one AWS identity call
185.14.97.x, Gigahost/Terrahost (AS56655) N/A 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 Ransomware, extortion and the cyber crime ecosystem.