grep1-7 Exercise 2: A Two-Part Report on repo ============================================== (Run in a fresh copy of the practice data from the chapter. Make it first with the block at the top of the chapter.) EXC="--exclude-dir=.git --exclude-dir=node_modules --exclude-dir=dist" echo "TODO/FIXME/HACK notes per file:" grep -rcIE $EXC '\b(TODO|FIXME|HACK)\b' repo | grep -v ':0$' echo echo "probable secrets (file:line only):" { grep -rnIE $EXC 'AKIA[0-9A-Z]{16}' repo grep -rniIE $EXC '(password|secret_key)[[:space:]]*=[[:space:]]*["'"'"'][^"'"'"']+["'"'"']' repo } | cut -d: -f1,2 | sort -u echo echo "files with a private key header:" grep -rlI $EXC -e '-----BEGIN [A-Z ]*PRIVATE KEY-----' repo Output: TODO/FIXME/HACK notes per file: repo/src/app.js:2 repo/src/db.py:2 repo/src/util.js:1 repo/tests/test_db.py:1 probable secrets (file:line only): repo/config/settings.py:1 repo/src/app.js:2 repo/src/db.py:2 repo/tests/test_db.py:2 files with a private key header: repo/id_rsa.example WHY THIS WORKS AS AN ANSWER --------------------------- The first part uses -c with -r, which prints a count for EVERY file, so grep -v ':0$' keeps only files with at least one note (:0 at the end of the line is a zero count). $EXC is a shell variable holding the three exclude options so that the same list is used in every command: unquoted on purpose, so the shell splits it into three options. The second part groups two searches in braces so that one cut and one sort -u handle both outputs: cut -d: -f1,2 keeps only 'file:line' so no secret is ever printed, and sort -u removes a line listed twice. The third part uses -l and -e for the key header (which starts with dashes). Two of the candidates are probably not a problem: repo/tests/test_db.py:2 is in a TEST file, where a made-up password is normal; and repo/src/app.js:2 holds AWS's own documented EXAMPLE key id, which is published as a fake. Neither can be confirmed by grep: only a person reading the file around each hit can say, and a real project would check the key against the cloud account. repo/src/db.py:2 and repo/config/settings.py:1 are the ones to look at first. The minified bundle in dist was excluded because it is generated; if a secret in it came from a source file, fixing that file fixes the bundle.