Skip to content
subcloakdocs

What Watch checks

Keys in git history

New in 1.2.0 Requires Cloak Watch 1.2.0 or later.

How Cloak Watch finds keys and tokens left in your projects' git history, what each card shows, the opt-in public-leak check, and how to rotate and remove them.

A key deleted from a project’s files is still in its git history, and anyone with a copy of the repository can read it. Cloak Watch reads the history of every project in your code folders for keys and tokens, and raises one SEC-4 card per repository. It’s free and on by default.

  • Watch reads each project’s .git folder directly, on every branch, tag and the stash, newest commits first. It never runs git, hooks or anything in the repository.
  • It matches about 220 key and token patterns derived from Gitleaks (MIT License). Gitleaks’ generic “API key” rule is left out because it’s too noisy across every project on a Mac.
  • Lockfiles, vendored code, node_modules, images, fonts, binaries and files over 1 MB are skipped, as in Gitleaks. So are submodules and symbolic links.
  • Scans are spread out: a full scan spends about 20 seconds on history, and a repository is read again only when its branches move. Big repositories are read newest first, and the card says if older history wasn’t reached.
  • Repositories that use SHA-256 object names aren’t read yet.

To turn it off, switch off Look for keys in git history in Settings › Privacy, under Secrets.

The card is titled, for example, 2 keys in the git history of shopapp, at Review. For each key:

  • what kind of key it is, the file and line, and the commit (with its date);
  • whether the key is in the current files or only in history;
  • the key, masked.

When Watch read only part of a long history, the card says “Watch read the newest N commits; older history wasn’t read.”

Watch never shows, logs, stores or exports a key in full.

  • A mask shows a key’s first 4 and last 2 characters and its length, for example ghp_…Q2 (40 chars).
  • Values under 24 characters, and passwords, show only their length: •••• (16 chars).
  • To tell whether two findings are the same key, Watch keeps a fingerprint made with HMAC-SHA256 and a random key that only this Mac has (kept in the Keychain, or in a file only you can read where the Keychain isn’t available). A short key can’t be worked out from its mask and fingerprint.
  • Results are kept in files only you can read.

GitHub tokens (ghp_, gho_, ghu_, ghs_ and ghr_) and npm tokens (npm_) end in a checksum. Watch checks it on your Mac and adds “GitHub’s checksum matches” to the key’s line, or “fails GitHub’s checksum, may be a test value”. A key that fails isn’t hidden or lowered: check it yourself.

On a SEC-4 card, and on a SEC-1 card for keys in plain-text files, Is this key public? lists the keys with Check…. It asks GitGuardian’s HasMySecretLeaked whether the key appears in public code. It’s opt-in, one key at a time.

  1. Click Check… next to a key.

  2. Watch asks Check this key with HasMySecretLeaked? and shows exactly what it will send: the first 5 characters of the key’s scrypt hash. GitGuardian also sees your IP address. Click Check.

  3. The answer is decrypted on your Mac: Not in public leaks, or Found in public code (with how many times, and Where when GitGuardian says where).

The 5 characters are shared by about a million other keys, so GitGuardian can’t tell which key you checked. Your Mac sends them directly, never through a proxy or a redirect, and never sends the key, its full hash or where it is. GitGuardian allows 5 free checks a day per network; after that, Watch says to try again tomorrow.

  1. Rotate first. Make a new key, put it where you use it, and delete the old one at the service that issued it. The card’s steps link to the right page, for example Open github.com. Rotating is what protects you: history keeps the old value.

  2. Then remove the key from the files where it’s still in the current files.

  3. Removing a key from history means rewriting the repository’s history (for example with git filter-repo) and asking everyone with a clone to re-clone. Do it only after rotating: every existing clone, fork and CI cache keeps the old history.