A key committed once is committed forever

Deleting the line in a follow-up commit changes nothing. Git kept the first one.

A commit adds a key, and a later commit removes the line. Walking back through the history shows the earlier commit unchanged, with the key still in it and fully readable.

The commit is almost always accidental: a .env that was not in .gitignore yet, a config file with a real value left in for testing, a quick fix committed with git add -A at the end of a long day.

What makes it serious is the permanence. Removing the line in the next commit leaves the value fully readable in the previous one, and in every clone, every fork and every CI cache that fetched in between.

How it actually bites

  1. Scanners find public repositories in minutes

    Automated crawlers watch the public commit firehose for credential patterns. The window between pushing a key and it being tested against the provider is short enough that "I deleted it right away" is not a defence.

  2. Cleaning history is a team-wide event

    Actually removing a secret means rewriting history and force-pushing, which invalidates every open branch and every local clone. It is disruptive enough that people rotate instead — which is the correct call, and also means the value stays in history.

  3. Forks and clones keep their own copy

    You control your repository. You do not control the fork someone made last month, or the mirror in a CI cache, or the clone on a laptop that has been offline since.

  4. Private is not a control

    A private repository limits who can read it today. It does not limit who can read it after the repository is made public, transferred, or granted to a new integration.

What we do about it

  1. Keys are not in the project directory

    The vault lives in extension storage, outside your working tree entirely. There is no file for git to notice, so the most common accident cannot happen.

  2. Generated files are transient

    You produce a .env at the moment you need one and delete it afterwards. A file that exists for ten minutes is much harder to commit than one that has been sitting in the repo since the project started.

  3. Names sync, values do not

    Project structure syncs across your devices as an encrypted blob so the server can never read a project name, and key values are never uploaded in a form anyone but you can open.

  4. CI gets its own path

    The GitHub Actions and gcloud export targets emit the commands to set secrets in the platform’s own secret store, so the CI copy lives where CI secrets belong rather than in a committed file.

Try it against your own keys

The extension is free and works offline. Set a master password, import an existing .env, and see what the vault looks like before you decide to trust it with anything.