potiuk opened a new pull request, #415:
URL: https://github.com/apache/airflow-steward/pull/415
## Summary
Adds a new `verify` check (**8d**) that audits the adopter's per-machine
permission allow-list (`<repo>/.claude/settings.json` and
`<repo>/.claude/settings.local.json`) and surfaces two kinds of finding:
- **✗ Forbidden entries** — broad wildcards that grant arbitrary code
execution. Per-entry proposal to remove. Examples already seen in
real adopter trees: `Bash(uv run *)`, `Bash(python3 *)`,
`Bash(npm run *)`, `Bash(bash *)`, `Bash(gh api *)`,
`Bash(docker run *)`, `Bash(sudo *)`.
- **⚠ Recommended entries** — narrow read-only patterns the framework's
`security` family invokes constantly. Family-scoped so the proposal
matches the adopter's opted-in skill set.
Because `verify` is chained from both `/setup-steward adopt` (Step 12
sanity check) and `/setup-steward upgrade` (Step 9 sanity check), every
adopt + upgrade pass now surfaces this audit automatically — no
separate skill invocation needed.
## Why
The user's own `airflow-s` allow-list had silently accumulated
`Bash(uv run *)` and `Bash(python3 *)` over time. Both are
arbitrary-code-execution holes; both stayed for months because no
periodic check flagged them. The verify chain is the right place for a
periodic capability-surface review — it already runs on every adopt +
upgrade, and proposing-rather-than-applying matches the framework's
golden rule that operator changes to capability surface stay under
operator control.
## What
`### 8d. Permission allow-list hygiene`:
- Reads both `.claude/settings.json` and `.claude/settings.local.json`.
- For each entry in `permissions.allow[]`:
- Buckets against a **forbidden list** (interpreters, shells, package
runners, task-runner wildcards, broad `gh api` / `docker run` /
`sudo` wildcards). ✗ per hit. List is explicitly *not* exhaustive
— the same-category rule extends to anything that can spawn an
arbitrary process.
- Buckets against a **family-scoped recommended list**:
- `security` family → 9 Gmail/PonyMail read-only MCPs +
`Bash(vulnogram-api-record-fetch *)`
- Any adopter shipping docs → `Bash(lychee *)`
- ⚠ per recommended entry missing.
- Reports the per-entry JSON-pointer path
(`.permissions.allow[<index>]`) so the operator can locate findings
instantly.
- **Read-only — proposes, never auto-writes.** Interactive apply via
`/setup-steward verify --apply-permission-audit` (atomic JSON
read → mutate → write so concurrent `setup-isolated-setup-install`
writes do not silently clobber; per-write sandbox-bypass
authorisation when the target file is at a `denyWithinAllow` path).
The recommended list is deliberately narrow — every entry is
verified against Claude Code's auto-allowed harness exclusions
(`READONLY_COMMANDS`, `GIT_READ_ONLY_COMMANDS`, `GH_READ_ONLY_COMMANDS`,
etc.) so the framework does not redundantly propose entries that never
prompt anyway.
## Test plan
- [ ] `/setup-steward verify` on a checkout whose
`.claude/settings.local.json` has `Bash(uv run *)` → ✗ on 8d with JSON-pointer
path, removal proposal printed
- [ ] On a checkout whose `.claude/settings.local.json` is missing
`mcp__claude_ai_Gmail__get_thread` and the adopter opted into the `security`
family → ⚠ on 8d, paste-ready string printed
- [ ] On a checkout whose `.claude/settings.local.json` is missing
`mcp__claude_ai_Gmail__get_thread` but the adopter did *not* opt into
`security` → no ⚠ (family-scoped)
- [ ] On a checkout with no `.claude/settings*.json` at all → ⚠ (soft
signal), suggests `/setup-isolated-setup-install`
- [ ] `/setup-steward adopt` and `/setup-steward upgrade` both chain through
verify and surface the 8d findings in their final report
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]