Add infra artifact secret-scan guardrail

This commit is contained in:
Doris
2026-05-22 21:13:16 +00:00
parent c2c71cfe57
commit 0b528cbb5f
4 changed files with 134 additions and 0 deletions

5
.githooks/pre-commit Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(git rev-parse --show-toplevel)"
exec "$repo_root/scripts/scan-secret-bearing-artifacts.sh" --staged

View File

@@ -239,6 +239,37 @@ See:
- `docs/operations/INCIDENT_2026-05-22_UNIFI_BASELINE_SECRET_LEAK.md`
- `home/doris-dashboard/docs/baselines/README.md`
### Pre-commit guardrail for infra artifacts
The repo now includes a narrow pre-commit scanner aimed specifically at catching secret-bearing controller/export artifacts before push.
Files:
- `scripts/scan-secret-bearing-artifacts.sh`
- `.githooks/pre-commit`
Enable it once per clone:
```bash
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit scripts/scan-secret-bearing-artifacts.sh
```
Run it manually on staged changes:
```bash
scripts/scan-secret-bearing-artifacts.sh --staged
```
What it is for:
- raw baselines
- exports
- snapshots
- dumps
- similar machine-generated infra artifacts
What it is not:
- a full replacement for GitHub/GitGuardian or a generic secret scanner for every file type
## Security Reminders
- **Key backup**: `C:\Users\Fizzlepoof\Downloads\.git-crypt-secrets.key` — also store in password manager

View File

@@ -29,3 +29,8 @@ See:
2. Inspect them for secret-bearing fields.
3. Commit only a markdown summary or an explicitly redacted artifact.
4. Prefer human-readable summaries over raw appliance dumps.
5. Enable the repo guardrail in each clone:
```bash
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit scripts/scan-secret-bearing-artifacts.sh
```

View File

@@ -0,0 +1,93 @@
#!/usr/bin/env bash
set -euo pipefail
mode="${1:---staged}"
repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"
if [[ "$mode" != "--staged" && "$mode" != "--files" ]]; then
echo "usage: $0 [--staged|--files <path> ...]" >&2
exit 2
fi
artifact_path_regex='(^|/)(docs/baselines/|baselines/|snapshots?/|exports?/|dumps?/|backups?/|diagnostics?/|artifacts?/|tmp/|temp/)|(^|/).*(baseline|snapshot|export|dump|diagnostic).*(\.json|\.ya?ml|\.txt|\.conf)?$'
placeholder_regex='(REDACTED|CHANGE_ME|<redacted>|example|placeholder|your[_ -]?token|your[_ -]?key)'
declare -a files=()
if [[ "$mode" == "--staged" ]]; then
while IFS= read -r f; do
[[ -n "$f" ]] && files+=("$f")
done < <(git diff --cached --name-only --diff-filter=ACMR)
else
shift
for f in "$@"; do
files+=("$f")
done
fi
if [[ ${#files[@]} -eq 0 ]]; then
exit 0
fi
failures=0
scan_file() {
local file="$1"
[[ -f "$file" ]] || return 0
[[ "$file" =~ $artifact_path_regex ]] || return 0
python3 - "$file" "$placeholder_regex" <<'PY'
from pathlib import Path
import re, sys
path = Path(sys.argv[1])
placeholder = re.compile(sys.argv[2], re.I)
text = path.read_text(errors='ignore')
lines = text.splitlines()
patterns = [
(re.compile(r'"x_wireguard_private_key"\s*:\s*"([^"]+)"', re.I), 'embedded WireGuard private key'),
(re.compile(r'"wireguard_client_configuration_file"\s*:\s*"([^"\\]|\\.)*PrivateKey = [A-Za-z0-9+/=]{20,}', re.I), 'embedded WireGuard client config with private key'),
(re.compile(r'PrivateKey\s*=\s*([A-Za-z0-9+/=]{20,})'), 'WireGuard private key line'),
(re.compile(r'Authorization\s*[:=]\s*(Bearer\s+)?[A-Za-z0-9._~+/=-]{16,}', re.I), 'authorization header/token material'),
(re.compile(r'"(token|api[_-]?key|client[_-]?secret|password|secret|cookie)"\s*:\s*"([^"]{12,})"', re.I), 'suspicious secret-like JSON field'),
]
for idx, line in enumerate(lines, start=1):
for regex, label in patterns:
m = regex.search(line)
if not m:
continue
if placeholder.search(line):
continue
print(f'{path}:{idx}: {label}')
print(f' {line[:220]}')
sys.exit(1)
sys.exit(0)
PY
}
for file in "${files[@]}"; do
if ! scan_file "$file"; then
failures=1
fi
done
if [[ "$failures" -ne 0 ]]; then
cat >&2 <<'EOF'
Secret-bearing artifact scan failed.
This guardrail is intentionally narrow: it is meant to stop raw controller/export/baseline artifacts
from being committed with embedded keys or tokens.
Fix options:
- remove the raw artifact from the commit
- replace it with a sanitized markdown summary
- explicitly redact the secret-bearing fields
If raw retention is required, store it outside the main repo or in the encrypted secrets repo.
EOF
exit 1
fi