Repository navigation
fix(cli): show allowlist grant scope in approvals get - #138386
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. Reviewed September 6, 2026, 4:11 PM ET / 20:11 UTC. ClawSweeper reviewWhat this changesAdds grant-scope labels to the approvals CLI table and shares their classification with Doctor while preserving existing cleanup behavior. Merge readiness✅ Ready for maintainer review This PR remains useful: current main and the latest release still omit grant scope from the allowlist table. Both earlier classification findings are resolved, and no new blocking defect was found. Priority: P2 Review scores
Verification
How this fits togetherThe approvals CLI reads local or remote execution rules and presents them to operators. The new scope labels explain each rule’s matching constraint; Doctor also uses the classifier to identify obsolete generated grants. flowchart TD
A[Stored approval rules] --> B[Approvals CLI]
B --> C[Grant scope classifier]
C --> D[Human-readable allowlist table]
A --> E[Doctor cleanup]
C --> E
E --> F[Remove obsolete generated grants]
B --> G[Unchanged JSON snapshot]
Before mergeNone. Agent review detailsSecurityNone. PR surfaceSource +26, Tests +116. Total +142 across 5 files. View PR surface stats
Review metricsNone. Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Technical reviewBest possible solution: Present matching constraints beside each allowlist rule while retaining existing authorization, JSON output, and Doctor ownership semantics. Do we have a high-confidence way to reproduce the issue? Yes: current main renders identical-pattern grants without their source or argument constraints, so otherwise identical broad, restricted, and inactive entries are indistinguishable. This was established from source; no local execution was performed. Is this the best way to solve the issue? Yes: the shared classifier repairs the human-readable view using existing matching semantics, and its generated-source guard preserves Doctor’s cleanup boundary. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 800ee0c0ed0a. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (7 earlier review cycles)
|
|
Applied the P2 in |
a4e3ce1 to
23d6eda
Compare
|
Dropped the @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
2c1b15e to
266794c
Compare
266794c to
200a5a3
Compare
`renderApprovalsSnapshot` built each Allowlist row from `pattern` and `lastUsedAt` only, dropping `source` and `argPattern` — the two fields `matchAllowlist` branches on. A cwd- and argv-bound `allow-always` grant, an `argPattern`-restricted rule, and an inactive legacy generated grant therefore rendered byte-identically to a broad path grant, so the CLI answered "what can this agent run" wrong in the permissive direction on the surface operators use for permissions audits. Record the scope fact at the authorization owner: `classifyExecAllowlistScope` in exec-command-resolution.ts derives what an entry actually authorizes from the same fields the matcher reads, and the Allowlist table renders it as a `Scope` column. `exec-approvals-generated-migration.ts` drops its duplicate inactive-grant predicate and reads the same classifier, so doctor and the audit table can no longer disagree about which grants are dead. Fixes openclaw#137452
`classifyExecAllowlistScope` labeled any pattern with a `=command:` or `=node-command:` prefix as `command text`, but only a grant carrying `source: "allow-always"` is ever honored as one: `hasExactCommandDurableExecApproval` and `hasNodeCommandAllowAlwaysMarker` both require that source, and `matchAllowlist` has no reserved-prefix branch at all. `approvals allowlist add` stores any nonempty pattern with no source, so a manual reserved-prefix entry was rendered as a narrow exact-command grant while the matcher treats it as an ordinary path-only glob. The audit table therefore understated its scope — the same collapse this branch fixes, in the other direction. Gate the branch on the source; a source-less pattern falls through to its real scope. Ordering is unchanged, so a generated exact-command grant is still classified before the `inactive` check and `doctor --fix` keeps skipping it.
…owned reference docs/cli/approvals.md is a CODEOWNERS path with security ownership, so the paragraph describing the Allowlist table's Scope column pulled a security-owner review gate onto a CLI output fix. Restore the page to its main version; the Scope column values and their meaning are described in the PR body instead. No code change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ants matchArgPattern rejects every legacy sha256:argv hash whatever its source, so a hand-written entry carrying one authorizes nothing. The Scope column showed it as a live "argv" restriction; it now reads "inactive" like the generated form. Doctor keeps its allow-always guard, so the newly inactive manual entries stay in place for the operator instead of being deleted. Regression: approvals get renders a manual legacy hash as inactive, and the Doctor migration retains a manual legacy hash while removing generated ones.
200a5a3 to
b3a14f4
Compare
Preserve contributor work, share grant classification with Doctor, and verify scope distinctions in narrow terminals without changing matching or JSON output.
|
Thanks @ylcn91 — landed in
Prompt requirements were checked through the published API; interactive prompt screens were not exercised. Matching, stored fields, JSON output, and Doctor deletion semantics remain unchanged. |
…rol-ui * origin/main: docs: remove the empty release-sections nav group (#140427) fix(tooling): omit Codex machine squash credit (#140420) chore(ui): refresh control ui locales (#140384) refactor(plugin-sdk): reuse native approval input contracts (#140415) fix: silent model WebSocket streams hang past the idle timeout (#140335) perf(ai): avoid unused text extraction for image results (#140409) fix(ui): distinguish failed GitHub status checks from disconnected accounts (#140333) refactor(cron): share runtime feedback schema fields (#140408) fix: avoid duplicate cloud worker teardown during recovery (#140377) fix(cli): show executable approval scope (#138386) refactor(ui): reuse shared requirement records (#140407) test(gateway): table-drive device token lifecycle checks (#140403) fix(chat): fence delayed history at terminal retirement (#140379) test(skills): compare large upload bytes natively (#140402) refactor(delivery): reuse the canonical rendered batch plan type (#140386) docs(start): repair the first-run path from landing page to first channel (#140390) # Conflicts: # docs/.i18n/glossary.zh-CN.json
Show each executable grant's matching scope in approvals get and reuse the classification in Doctor without changing authorization, stored fields, or JSON output. Preserve the contributor's reserved-marker and legacy-hash corrections. Cover narrow-terminal scope distinctions and verify the compiled CLI, evaluator, approval policy, grant persistence, and Doctor cleanup. Fixes openclaw#137452. Co-authored-by: Ayaan Zaidi <hi@obviy.us>
What Problem This Solves
openclaw approvals getdisplayed only the executable pattern and last-use time. A manual rule allowing any arguments, a directory-bound generated grant, and an inactive legacy grant therefore looked identical during a permissions audit.Fixes #137452.
Why This Change Was Made
Classify each grant beside the executable matcher and render that classification in a Scope column. Doctor uses the same classifier while retaining its generated-source ownership guard, so inactive manual rules remain untouched.
This preserves the contributor's repair and both earlier classification corrections. Matching, grant creation, stored fields, JSON output, prompts, and Doctor deletion behavior remain unchanged.
User Impact
any argsargvargv+cwdcommand textinactiveThe scope describes the rule's matching constraint; effective approval policy still applies. Narrow terminals wrap the executable pattern while retaining the scope distinction. Reserved command markers without generated source retain their ordinary manual-rule classification. Doctor does not delete manual legacy hashes.
Evidence
72c5ecef576ff6964b721d48c22a9244d4ae84cc: 13 synthetic grants at terminal widths 120, 80, 60, and 40; full JSON snapshots remained identical to baseline.doctor --fix --non-interactive: baseline and candidate removed the same three obsolete generated grants and retained the same ten entries, including manual legacy hashes and generated command markers.Earlier contributor corrections remain covered: generated source is required for command-text scope; source-less legacy hashes are inactive but remain outside Doctor deletion ownership.