Test: Scan compose secrets by data shape
This commit is contained in:
@@ -24,36 +24,31 @@ note() { findings+=("$1"); }
|
||||
|
||||
[[ -d "$server_dir" ]] || { printf 'compose secrets contract: no server/ directory\n' >&2; exit 1; }
|
||||
|
||||
# ── 1. Tracked content is clean ──────────────────────────────────────────────
|
||||
#
|
||||
# Only tracked files: the live .env a cutover briefly leaves in a service
|
||||
# directory is exactly what the gitignore exists for, and flagging it here
|
||||
# would punish the ignore for working.
|
||||
# ── 1. Scanner fixtures and tracked content ──────────────────────────────────
|
||||
|
||||
while IFS= read -r file; do
|
||||
path="$repo_dir/$file"
|
||||
[[ -f "$path" ]] || continue
|
||||
scanner="$repo_dir/tests/server/scan-tracked-secrets.py"
|
||||
fixtures_dir="$repo_dir/tests/server/fixtures/secrets"
|
||||
|
||||
# A secret-bearing key with a literal value. ${VAR} interpolations, empty
|
||||
# values, the CHANGE_ME placeholder, and booleans (ALLOW_EMPTY_PASSWORD=yes
|
||||
# is a switch, not a credential) are the allowed shapes; anything else
|
||||
# after PASSWORD/SECRET/TOKEN/KEY is treated as a leak. Keys that merely
|
||||
# configure where a secret lives (a *_FILE path, a key NAME) are not
|
||||
# values.
|
||||
if ! python3 "$scanner" "$fixtures_dir/clean" compose.yml .env.example README.md; then
|
||||
note 'the clean secret-scanning fixture was rejected'
|
||||
fi
|
||||
|
||||
for fixture in compose.yml .env.example; do
|
||||
if output="$(python3 "$scanner" "$fixtures_dir/leaked" "$fixture" 2>&1)"; then
|
||||
note "the leaked $fixture fixture was accepted"
|
||||
elif [[ "$fixture" == compose.yml && "$output" != *'POSTGRES_PASSWORD'* ]]; then
|
||||
note 'the leaked compose fixture did not name POSTGRES_PASSWORD'
|
||||
elif [[ "$fixture" == .env.example && "$output" != *'API_TOKEN'* ]]; then
|
||||
note 'the leaked env fixture did not name API_TOKEN'
|
||||
fi
|
||||
done
|
||||
|
||||
mapfile -t tracked_server_files < <(git -C "$repo_dir" ls-files 'server/**' 'server/*')
|
||||
if ! output="$(python3 "$scanner" "$repo_dir" "${tracked_server_files[@]}" 2>&1)"; then
|
||||
while IFS= read -r hit; do
|
||||
note "$file looks like it carries a secret: ${hit%%[=:]*}"
|
||||
done < <(grep -inE '(password|secret|token|api_key|private_key|access_key)[a-z0-9_]*[[:space:]]*[:=]' "$path" 2>/dev/null \
|
||||
| grep -vE '[:=][[:space:]]*["'"'"']?(\$\{|CHANGE_ME|(true|false|yes|no|[01])["'"'"']?[[:space:]]*$|["'"'"']?[[:space:]]*$)' \
|
||||
| grep -viE '(_file|_path|_name|_key_name)[[:space:]]*[:=]' \
|
||||
| grep -vE '^[0-9]+:[[:space:]]*#')
|
||||
|
||||
if grep -qE 'BEGIN [A-Z ]*PRIVATE KEY' "$path" 2>/dev/null; then
|
||||
note "$file contains a private key"
|
||||
fi
|
||||
if grep -qE 'sk-ant-[A-Za-z0-9]|ghp_[A-Za-z0-9]{20}|xox[baprs]-[A-Za-z0-9]' "$path" 2>/dev/null; then
|
||||
note "$file contains something that looks like an API token"
|
||||
fi
|
||||
done < <(git -C "$repo_dir" ls-files 'server/')
|
||||
[[ -n "$hit" ]] && note "$hit"
|
||||
done <<< "$output"
|
||||
fi
|
||||
|
||||
# ── 2. The ignore still stands ───────────────────────────────────────────────
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user