Unit 1: Secrets in code · Lesson 4 of 4 · 18 min

Stop the next secret at commit time

Install a pre-commit hook that blocks secrets, test it with a fake key and fix the ignore rule that let the password in.

mission

You are
You are the application security engineer at Quayside.
Situation
Cleaning up after leaks is slow and expensive. The team agrees to catch secrets before they ever reach a commit.
Goal
Add a local hook that refuses commits containing secrets, and fix the ignore rule for env files.
Hand in
A working hook and a corrected .gitignore.
01

Write the hook

Git runs .git/hooks/pre-commit before every commit and aborts if it exits with a non-zero status. gitleaks git --pre-commit --staged scans only the changes you are about to commit.

learner@dev-lab
printf '#!/bin/sh\ngitleaks git --pre-commit --staged -c ~/gitleaks.toml --no-banner --no-color --redact -v -l warn . || { echo "Commit blocked: remove the secret, then commit again."; exit 1; }\n' > .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit && cat .git/hooks/pre-commit
#!/bin/sh
gitleaks git --pre-commit --staged -c ~/gitleaks.toml --no-banner --no-color --redact -v -l warn . || { echo "Commit blocked: remove the secret, then commit again."; exit 1; }

you should see A two-line script that runs gitleaks on the staged changes.

printf
Prints formatted text. Built into Linux and macOS.
echo
Prints its arguments. Built into Linux and macOS.
chmod
Changes a file's permissions. Built into Linux and macOS.
cat
Prints the contents of one or more files. Built into Linux and macOS.
02

Test it with a fake key

learner@dev-lab
echo 'token = "qsk_live_AAAAbbbbCCCCddddEEEEffff"' > config/test-token.js && git add config/test-token.js && git commit -q -m 'Add test token'; echo "exit $?"
Finding:     REDACTED
Secret:      REDACTED
RuleID:      quay-live-key
Entropy:     3.529243
File:        config/test-token.js
Line:        1
Fingerprint: config/test-token.js:quay-live-key:1

6:16PM WRN leaks found: 1
Commit blocked: remove the secret, then commit again.
exit 1

you should see The hook finds the key, prints why and the commit is refused.

defender tip Local hooks are a seatbelt, not a guarantee: they are not cloned with the repository and anyone can skip them with --no-verify. Pair them with server-side push protection that the developer cannot turn off.

git
Tracks changes to code and shows its history. Install with sudo apt install git, or brew install git on a Mac.
03

Clean up the test

learner@dev-lab
git restore --staged config/test-token.js && rm config/test-token.js && git status --short

you should see Nothing staged and no test file left behind.

rm
Deletes files. Built into Linux and macOS.
04

Fix the ignore rule

git rm --cached stops tracking a file without deleting your local copy.

learner@dev-lab
echo 'docker/.env*' >> .gitignore && git rm --cached -q docker/.env.staging && git status --short
 M .gitignore
D  docker/.env.staging
git check-ignore -v docker/.env.staging
.gitignore:3:docker/.env*	docker/.env.staging

you should see docker/.env* now matches the staging file, and git will drop it in the next commit. The password still needs rotating.

Where to catch secrets

Only after the fact
nightly scan of main
  finds the key a day later
  key already pushed, cloned and cached

Every finding becomes an incident.

Layered
pre-commit hook on the laptop
push protection on the server
scan of history on a schedule
secrets manager so code never needs keys

Most secrets never leave the developer's machine.

What a defender takes away

  1. 1Block secrets before commit, and again at push on the server.
  2. 2Hooks can be skipped, so server-side checks are the real control.
  3. 3Untracking a file is not the same as rotating what was in it.

Questions

0 of 3 solved

Answer each one from what you find on your lab machine.

  1. Show hint

    Read the RuleID line in the hook output.

  2. Show hint

    The command prints it with `echo "exit $?"`.

  3. Show hint

    `git check-ignore -v docker/.env.staging`