Playbook·check repo_secrets

One API key, two repositories, one transcript

A Gemini key shared by two projects surfaced in a coding-agent transcript of the other one. Why sharing multiplies exposure, and the three-step fix.

SK Semih Kavaklıoğlu·8 Sept 2026·3 min read Share

The checkup on a three-day-old repository found a secret that the repository had never leaked. Its Gemini API key was the same string another of our projects used, and that other project's coding session had logged it into a transcript three weeks earlier. One key, two codebases, one exposure, two incidents.

What does this check detect?

Answer. Secret values from the repository's .env files that appear anywhere they should not: git history, tracked source, and the local transcript folders of coding assistants, including transcripts of other projects on the same machine.

The agent reads the current .env values locally, never printing them, and searches for those exact strings across git history, tracked files and the transcript folders. A hit is reported as type, file and the last four characters. In this case the hit was in another project's session file, in a Gemini request URL that carried the key as a query parameter.

Why is a shared key worse than a leaked one?

Answer. Because the blast radius is every project that uses it, and the leak can come from any of them.

One key per repositorychosen
  • a leak exposes one project
  • rotation touches one .env and one host
  • usage logs tell you which app spent what
One key everywhere
  • a leak in any project exposes all of them
  • rotation is a coordinated change across hosts
  • one bill, no idea which app made the calls

The key was leaked by a project the checkup was not even looking at. Nothing in the three-day-old repository was wrong. It inherited the exposure through sharing.

What is the fix?

Answer. Rotate, split, and stop passing keys in URLs.

  1. Rotate the key with the provider. The old value is public until you do; check the provider's usage for the window since the leak (14 August in this case).
  2. Create one key per repository and name it after the project, so the usage dashboard and the next rotation are per app.
  3. Send the key in a header, not the URL. Gemini and most APIs accept x-goog-api-key or Authorization: Bearer; a query string ends up in request logs, proxies and transcripts, and that is exactly where this one was found.

Then read the key from the environment on the host, keep it out of any file the agent might print, and move values with a pipe (grep KEY .env | cut -d= -f2- | vercel env add KEY production) rather than by typing them.

How do you verify it?

Answer. Re-run the checkup after rotation; the old value should appear nowhere, and the new value should appear only in the host's environment.

The checkup compares current values against history and transcripts. After rotation the old string is inert and the new string has not been anywhere yet. If the provider shows requests from the old key after rotation, the leak was in use; that is the number to act on.

FAQ

The key was only in a transcript on my own machine. Is that a leak?

Hosted assistants send the conversation to the vendor to produce each answer and keep a local copy; treat both as outside your control. A key that has been in a transcript should be rotated.

Should every service get its own key per repository?

Yes, where the provider allows it. Where a provider allows one key per account, isolate by account or accept the shared radius knowingly.

How often should the checkup run?

After any change to authentication or integrations, and monthly. Moonleap's project settings let you set the cadence and the overview reminds the agent when it is due.

Sources

  1. Repo security checkup on one of our own sites, 8 September 2026 (key masked; value never stored)
  2. The same checkup's transcript scan: the key appeared in a request-log line of another project's session on 14 August 2026
  3. Google AI Studio, API key management https://aistudio.google.com/app/apikey

Share the number

2

repositories exposed by one shared key when one of them leaked it into a transcript

moonleap.io · 8 Sept 2026Post

Related