guardrails: silence the intentional SC2016 in prod-guard
All checks were successful
PR build (required check) / changes (pull_request) Successful in 11s
secrets-guard / encrypted (pull_request) Successful in 10s
shell-lint / shellcheck (pull_request) Successful in 14s
PR build (required check) / build-backend (pull_request) Has been skipped
PR build (required check) / build-frontend (pull_request) Has been skipped
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / gate (pull_request) Successful in 3s
All checks were successful
PR build (required check) / changes (pull_request) Successful in 11s
secrets-guard / encrypted (pull_request) Successful in 10s
shell-lint / shellcheck (pull_request) Successful in 14s
PR build (required check) / build-backend (pull_request) Has been skipped
PR build (required check) / build-frontend (pull_request) Has been skipped
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / gate (pull_request) Successful in 3s
shell-lint flagged the literal `$(` / backtick patterns the read-only classifier searches for inside a command string. Expanding them is exactly what must not happen — the check exists to refuse commands containing command substitution, so the single quotes are the point. Same treatment and rationale as the existing disables in render-secrets.sh and verify-centralis-render.sh. Verified with the pinned shellcheck v0.11.0 (sha256 matching shell-lint.yml): all 34 scripts in the tree clean. Hook behaviour unchanged — the classifier test matrix still allows reads and asks on mutations and compound smuggling. Also documents that ~/.claude/hooks/ carries a mirror of prod-guard.sh so sessions started outside this repo are covered, and that the blanket ssh allow rules were removed from global settings so the hook cannot be out-ranked.
This commit is contained in:
parent
5418628989
commit
c184fd55ea
2 changed files with 25 additions and 3 deletions
|
|
@ -54,12 +54,31 @@ fails toward the prompt rather than toward silent execution.
|
||||||
|
|
||||||
## lint-after-edit needs shellcheck on PATH
|
## lint-after-edit needs shellcheck on PATH
|
||||||
|
|
||||||
It exits quietly when shellcheck is absent, so it is **inert until installed** — a
|
It exits quietly when shellcheck is absent — a missing local tool must not break
|
||||||
missing local tool must not break editing, and `shell-lint` CI is still the backstop.
|
editing, and `shell-lint` CI is still the backstop. v0.11.0 (the version CI pins) is
|
||||||
Install the same pinned version CI uses:
|
installed at `~/.local/bin/shellcheck`; if you move machines, reinstall it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
VER=v0.11.0
|
VER=v0.11.0
|
||||||
curl -fsSL "https://github.com/koalaman/shellcheck/releases/download/${VER}/shellcheck-${VER}.linux.x86_64.tar.xz" \
|
curl -fsSL "https://github.com/koalaman/shellcheck/releases/download/${VER}/shellcheck-${VER}.linux.x86_64.tar.xz" \
|
||||||
| tar -xJ --strip-components=1 -C ~/.local/bin "shellcheck-${VER}/shellcheck"
|
| tar -xJ --strip-components=1 -C ~/.local/bin "shellcheck-${VER}/shellcheck"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Keep it matched to `shell-lint.yml`'s pin. A drifted shellcheck grows *new* warnings
|
||||||
|
and fails CI on an unrelated push, which is why that workflow pins the version and
|
||||||
|
its sha256 rather than using `apt-get install`.
|
||||||
|
|
||||||
|
## The global copy
|
||||||
|
|
||||||
|
`~/.claude/settings.json` runs `prod-guard.sh` from `~/.claude/hooks/` as well, so a
|
||||||
|
session started **outside** this repo is covered too — otherwise the guard would be
|
||||||
|
trivially bypassed by working from `~/Code`. That copy is a mirror; this one is
|
||||||
|
canonical. If you change the classifier here, copy it over:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .claude/hooks/prod-guard.sh ~/.claude/hooks/prod-guard.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The blanket `Bash(ssh prod:*)` / `Bash(ssh beta:*)` allow rules were removed from
|
||||||
|
global settings at the same time, so the hook is the only thing granting live-host
|
||||||
|
access. If it is missing or broken, nothing allows the command and you get a prompt.
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,9 @@ is_readonly() {
|
||||||
case "$stripped" in *'>'*) return 1 ;; esac
|
case "$stripped" in *'>'*) return 1 ;; esac
|
||||||
|
|
||||||
# Command substitution can hide anything; refuse to reason about it.
|
# Command substitution can hide anything; refuse to reason about it.
|
||||||
|
# shellcheck disable=SC2016 # single quotes are the point: these are literal
|
||||||
|
# `$(` and backtick characters being searched for inside the command text, not
|
||||||
|
# expansions to perform. Expanding them here would defeat the check entirely.
|
||||||
case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
|
case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
|
||||||
|
|
||||||
while IFS= read -r seg; do
|
while IFS= read -r seg; do
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue