Skip to content

Commit 556f841

Browse files
hyperpolymathclaude
andcommitted
fix(scripts): default to the NON-WIDENING route (selected + populated allowlist)
Converges this fixer with a parallel remediation effort (llm-coding-configs/claude-code/notification-storm-remediation/FINDINGS.md) rather than letting two incompatible fixes race on the same 98 repos. #362's decision of record was `allowed_actions=all`. That works, but it is a security-posture change: it removes the owner allowlist and leaves mandatory SHA-pinning as the only control. The parallel effort established a strictly safer route reaching the same outcome: keep allowed_actions=selected, keep sha_pinning_required=true, and simply POPULATE the empty patterns_allowed. Its natural experiment over 426 repos: allowed_actions=all 286 repos -> wrappers run selected + `hyperpolymath/*` present 42 repos -> wrappers run selected + patterns_allowed=[] 98 repos -> ALL startup_failure So the breakage is the list being EMPTY, not the list existing. Populating it restores CI *and* keeps the allowlist as a real control. `--mode all` remains available as an explicit fallback; it is no longer the default. Changes: * MODE now defaults to `selected` (was `all`) * new `--allowlist FILE` to supply a curated patterns_allowed document * refuse an allowlist whose patterns_allowed is EMPTY — that is precisely the fault being repaired, and applying it would be a silent no-op * `[ x = y ] && rm` replaced with a total `if` — under `set -e` the bare `&&` form returns 1 when the test is false and would abort the sweep Verified: shellcheck clean; bash -n clean; empty-allowlist guard exercised; `--list` still classifies correctly (trope-checker, now populated with 87 patterns, reports `selected true 87 ok` — it was `selected true 0 BROKEN-M1`). Target lists reconcile exactly: this tool's 95 (--source, non-archived) is a subset of the parallel effort's 98; the 3 extra are forks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 00ddf89 commit 556f841

1 file changed

Lines changed: 38 additions & 12 deletions

File tree

scripts/fix-actions-policy.sh

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,24 @@
2929
# * every PUT is GET-verified, and the sweep ABORTS if sha_pinning was
3030
# silently reset (never trade pinning away for permissiveness)
3131
#
32-
# ── Target posture (decision of record, #362) ────────────────────────────
33-
# allowed_actions = all + sha_pinning_required = true
34-
# Rationale: an empty allowlist protects nothing — it blocks everything —
35-
# while a pinned SHA cannot be moved under you. `--mode selected` remains
36-
# available for a high-sensitivity tier, populating patterns_allowed from
37-
# hyperpolymath/standards rather than leaving it empty.
32+
# ── Target posture ───────────────────────────────────────────────────────
33+
# #362's decision of record was `allowed_actions=all` + sha_pinning. A
34+
# parallel remediation (llm-coding-configs/claude-code/notification-storm-
35+
# remediation/FINDINGS.md, 2026-07-21) established a STRICTLY SAFER route
36+
# that fixes the same 98 repos WITHOUT widening anything:
37+
#
38+
# keep allowed_actions=selected, keep sha_pinning_required=true,
39+
# and simply POPULATE the empty patterns_allowed list.
40+
#
41+
# Its evidence is a natural experiment over 426 repos:
42+
# allowed_actions=all 286 repos -> wrappers run
43+
# selected + `hyperpolymath/*` present 42 repos -> wrappers run
44+
# selected + patterns_allowed=[] 98 repos -> ALL startup_failure
45+
# i.e. the breakage is caused by the list being EMPTY, not by it existing.
46+
# Populating it therefore restores CI while KEEPING the owner allowlist as a
47+
# real control — so `selected` is the default here, and `--mode all` is the
48+
# opt-in fallback rather than the target.
49+
#
3850
# NEVER disable sha_pinning_required.
3951
#
4052
# Idempotent: healthy repos are reported `ok` and skipped.
@@ -50,7 +62,8 @@ set -euo pipefail
5062

5163
OWNER=""
5264
ACTION="list" # list | apply (report-by-default)
53-
MODE="all" # all | selected
65+
MODE="selected" # selected (default, non-widening) | all (opt-in fallback)
66+
ALLOWLIST="" # curated patterns_allowed JSON; defaults to standards'
5467
LIMIT=500
5568
JSONL=""
5669
ONE_REPO=""
@@ -64,6 +77,7 @@ while [ $# -gt 0 ]; do
6477
--list) ACTION="list" ;;
6578
--apply) ACTION="apply" ;;
6679
--mode) MODE="${2:-}"; shift ;;
80+
--allowlist) ALLOWLIST="${2:-}"; shift ;;
6781
--limit) LIMIT="${2:-}"; shift ;;
6882
--jsonl) JSONL="${2:-}"; shift ;;
6983
--repo) ONE_REPO="${2:-}"; shift ;;
@@ -202,11 +216,23 @@ for R in $REPOS; do
202216
gh api --method PUT "repos/${FULL}/actions/permissions" \
203217
-f enabled=true -f allowed_actions=all -F sha_pinning_required=true >/dev/null
204218
else
205-
gh api "repos/${STD_REPO}/actions/permissions/selected-actions" > /tmp/allow.$$.json 2>/dev/null \
206-
|| die "cannot read the standards allowlist to seed --mode selected"
207-
gh api --method PUT "repos/${FULL}/actions/permissions/selected-actions" \
208-
--input /tmp/allow.$$.json >/dev/null
209-
rm -f /tmp/allow.$$.json
219+
# Non-widening path: leave allowed_actions/sha_pinning untouched and only
220+
# populate the empty patterns_allowed. Prefer an explicitly curated list
221+
# (--allowlist); otherwise mirror hyperpolymath/standards, which is itself
222+
# a healthy `selected` repo.
223+
SRC="$ALLOWLIST"
224+
if [ -z "$SRC" ]; then
225+
gh api "repos/${STD_REPO}/actions/permissions/selected-actions" > "/tmp/allow.$$.json" 2>/dev/null \
226+
|| die "cannot read the standards allowlist; pass --allowlist FILE instead"
227+
SRC="/tmp/allow.$$.json"
228+
fi
229+
[ -s "$SRC" ] || die "allowlist '$SRC' is missing or empty"
230+
jq -e '(.patterns_allowed|length) > 0' "$SRC" >/dev/null 2>&1 \
231+
|| die "allowlist '$SRC' has an EMPTY patterns_allowed — that is the very fault being fixed"
232+
gh api --method PUT "repos/${FULL}/actions/permissions/selected-actions" --input "$SRC" >/dev/null
233+
# `&& rm` alone would return 1 when the test is false and, under `set -e`,
234+
# abort the sweep on the --allowlist path. Keep the guard total.
235+
if [ "$SRC" = "/tmp/allow.$$.json" ]; then rm -f "/tmp/allow.$$.json"; fi
210236
fi
211237

212238
# GET-verify. Trading sha_pinning away for permissiveness is never acceptable,

0 commit comments

Comments
 (0)