Zion Boggan
repos/Oversight/scripts/opsec-scan.sh
zionboggan.com ↗
80 lines · bash
History for this file →
1
 
2
set -euo pipefail
3
 
4
MODE="tree"
5
if [[ "${1:-}" == "--staged" ]]; then
6
    MODE="staged"
7
fi
8
 
9
PATTERNS=(
10
    "rfc1918-192-168:\\b192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}\\b"
11
    "rfc1918-10-dot:\\b10\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\b"
12
    "rfc1918-172-16:\\b172\\.(1[6-9]|2[0-9]|3[0-1])\\.[0-9]{1,3}\\.[0-9]{1,3}\\b"
13
    "workspace-path:/shared/projects(/|\\b)"
14
    "container-id:\\bCT [0-9]{3}\\b"
15
    "homelab-node:\\bpve-gpu\\b"
16
    "windows-desktop-path:\\bP:[/\\\\]"
17
    "github-pat:\\bghp_[A-Za-z0-9]{30,}\\b"
18
    "openai-key:\\bsk-[A-Za-z0-9]{20,}\\b"
19
    "slack-bot-token:\\bxoxb-[A-Za-z0-9-]{20,}\\b"
20
    "private-ssh-pem:-----BEGIN (OPENSSH|RSA|EC|DSA|PGP) PRIVATE KEY-----"
21
)
22
 
23
EXEMPT_PATHS=(
24
    "scripts/opsec-scan.sh"
25
    ".github/workflows/opsec.yml"
26
    "CHANGELOG.md"
27
    "docs/SIEM.md"
28
)
29
 
30
is_exempt() {
31
    local p="$1"
32
    for e in "${EXEMPT_PATHS[@]}"; do
33
        [[ "$p" == "$e" ]] && return 0
34
    done
35
    return 1
36
}
37
 
38
scan_blob() {
39
    local path="$1"
40
    local content="$2"
41
    local fail=0
42
    for entry in "${PATTERNS[@]}"; do
43
        local label="${entry%%:*}"
44
        local rx="${entry#*:}"
45
        local hits
46
        hits=$(printf '%s' "$content" | grep -nE -e "$rx" 2>/dev/null || true)
47
        if [[ -n "$hits" ]]; then
48
            echo "[opsec] $path: $label"
49
            echo "$hits" | sed 's/^/  /'
50
            fail=1
51
        fi
52
    done
53
    return $fail
54
}
55
 
56
overall=0
57
 
58
if [[ "$MODE" == "staged" ]]; then
59
    while IFS= read -r -d '' path; do
60
        is_exempt "$path" && continue
61
        [[ -f "$path" ]] || continue
62
        added=$(git diff --cached -U0 -- "$path" | grep -E '^\+' | grep -vE '^\+\+\+' || true)
63
        [[ -z "$added" ]] && continue
64
        if ! scan_blob "$path" "$added"; then overall=1; fi
65
    done < <(git diff --cached --name-only -z --diff-filter=AM)
66
else
67
    while IFS= read -r -d '' path; do
68
        is_exempt "$path" && continue
69
        if ! grep -Iq . "$path" 2>/dev/null; then continue; fi
70
        if ! scan_blob "$path" "$(cat "$path")"; then overall=1; fi
71
    done < <(git ls-files -z)
72
fi
73
 
74
if [[ $overall -ne 0 ]]; then
75
    echo ""
76
    echo "[opsec] one or more patterns matched. Redact and re-run."
77
    exit 1
78
fi
79
 
80
echo "[opsec] clean."