Просмотр исходного кода

fix(ci): install rg+gitleaks; security-scan fails loud without rg

CI red (push-gate + security-ops suites): both secret scanners depend
on ripgrep (scan-secrets also on gitleaks), which the CI runner lacks —
so scan-secrets exited 5 (missing dep) and security-scan's
`rg ... 2>/dev/null` silently found 0 -> reported clean. Local passed
because this machine has both (classic 'local gates lie').

Two fixes:
1. validate.yml installs jq + ripgrep + gitleaks (release binary) so
   the security suites run for real on CI instead of erroring/skipping.
2. security-scan.sh now REFUSES (exit 5) when rg is absent instead of
   silently reporting a false clean — a security scanner that passes
   because its engine is missing is worse than useless. Regression test
   added (mirror /usr/bin minus rg -> assert exit 5; skip-guarded for
   hosts where the shim can't build).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0xDarkMatter 1 неделя назад
Родитель
Сommit
011bfd172b

+ 9 - 2
.github/workflows/validate.yml

@@ -12,8 +12,15 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v4
 
-      - name: Install jq
-        run: sudo apt-get update && sudo apt-get install -y jq
+      - name: Install jq + ripgrep + gitleaks (security suites need them)
+        run: |
+          sudo apt-get update && sudo apt-get install -y jq ripgrep
+          # gitleaks: fetch the release binary (not in apt) so push-gate's
+          # scan-secrets.sh and its suite run for real instead of skipping.
+          GL_VER=8.21.2
+          curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GL_VER}/gitleaks_${GL_VER}_linux_x64.tar.gz" \
+            | sudo tar -xz -C /usr/local/bin gitleaks
+          gitleaks version && rg --version | head -1
 
       - name: Install Claude Code (for authoritative plugin validation)
         run: npm install -g @anthropic-ai/claude-code

+ 8 - 0
skills/security-ops/scripts/security-scan.sh

@@ -43,6 +43,14 @@ fi
 
 DIR="${1:-.}"
 
+# rg is the scan engine. A security scanner that silently reports "clean"
+# because its engine is missing is worse than useless — refuse loudly (exit 5)
+# rather than let a rg-less environment produce a false all-clear.
+if ! command -v rg >/dev/null 2>&1; then
+    printf 'security-scan.sh: ripgrep (rg) not installed — cannot scan. Install rg; refusing to report a false clean.\n' >&2
+    exit 5
+fi
+
 RED='\033[0;31m'
 YELLOW='\033[1;33m'
 GREEN='\033[0;32m'

+ 23 - 0
skills/security-ops/tests/run.sh

@@ -65,6 +65,29 @@ expect_lacks 'removed eval trigger is no longer reported' 'eval_case.py' "$mutat
 expect_has 'mutation retains independent secret finding' 'hardcoded_secret.py' "$mutated_out"
 expect_has 'mutation retains independent pickle finding' 'unsafe_deserialization.py' "$mutated_out"
 
+printf '%s\n' '-- fail-loud when scan engine (rg) is absent --'
+# A security scanner that reports "clean" because rg is missing is a false
+# all-clear — it must refuse (exit 5), never exit 0. The scanner hits its
+# `command -v rg` guard before it needs any other tool, so a shim of the
+# standard bin dirs minus rg is enough to trip it. Skip-guarded: if the shim
+# can't be built (e.g. Windows symlink quirks) we don't fail the suite —
+# CI (Linux) builds it cleanly and runs the real assertion.
+RGSHIM="$SB/rgless"; mkdir -p "$RGSHIM"
+for _d in /usr/bin /bin /usr/local/bin; do
+  [ -d "$_d" ] || continue
+  for _f in "$_d"/*; do
+    _b="$(basename "$_f")"
+    [ "$_b" = "rg" ] && continue
+    [ -e "$RGSHIM/$_b" ] || ln -sf "$_f" "$RGSHIM/$_b" 2>/dev/null
+  done
+done
+if [ -x "$RGSHIM/bash" ] && ! PATH="$RGSHIM" command -v rg >/dev/null 2>&1; then
+  PATH="$RGSHIM" bash "$SCAN" "$BAD" >"$SB/norg.out" 2>/dev/null
+  expect_exit 'refuses (exit 5) when rg is absent — no false clean' "$?" 5
+else
+  printf '  SKIP  rg-absent shim unavailable on this host (CI runs it for real)\n'
+fi
+
 printf '\n=== %d passed, %d failed ===\n' "$PASS" "$FAIL"
 [[ "$FAIL" -eq 0 ]] || exit 1
 exit 0