feat(approvals): add plain-language plugin approvals#81864
feat(approvals): add plain-language plugin approvals#81864kennykankush wants to merge 119 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 30, 2026, 8:50 PM ET / 00:50 UTC. Summary Reproducibility: not applicable. as a feature PR. Current-main source shows only raw plugin approval text, while the PR body and PR-head source show the proposed opt-in simple rendering path. Review metrics: 2 noteworthy metrics.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land only a maintainer-approved, opt-in approval-language contract on a clean current-base branch, with unrelated refreshed-base churn split out if it keeps obscuring the approval change. Do we have a high-confidence way to reproduce the issue? Not applicable as a feature PR. Current-main source shows only raw plugin approval text, while the PR body and PR-head source show the proposed opt-in simple rendering path. Is this the best way to solve the issue? Unclear until maintainer decision. The default- AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 44b4a0ac0598. Label changesLabel justifications:
Evidence reviewedSecurity concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
…lain-plugin-approval-prompts-pr # Conflicts: # docs/.generated/config-baseline.sha256 # docs/.generated/plugin-sdk-api-baseline.sha256
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Follow-up CI repair pushed in What changed:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Merged current Status note:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Addressed the latest ClawSweeper review in Changes in this refresh:
Local verification:
Note: the prior @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Follow-up CI repair pushed in Changes:
Local verification:
I intentionally did not patch the remaining @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Follow-up CI repair pushed in What changed:
Why:
Verified locally:
Known remaining unrelated CI note from the prior run:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
P2 channel renderer follow-up pushed in What changed:
Verification run:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Follow-up pushed in Local verification for this extra fix:
The P2 channel-renderer fix remains in @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
P2 channel-language follow-up is pushed at What changed since the P2 review:
Local verification:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@stielemans quick maintainer-review ping now that the P2 follow-up is in. Current head: State from my side:
The remaining item appears to be maintainer/security acceptance of the opt-in |
|
Closing due to inactivity. |

Mission
Plugin approvals are a security boundary, but they are often delivered in chat where the old fallback text read like internal debug output. A normal approval could show a raw title, full command text, proposed exec policy, session key, tool/plugin IDs, expiry, and
/approve <id>syntax all at once.That raw format is useful for maintainers, but it is not easy for a Telegram/Matrix user to scan quickly. The goal of this PR is to make opt-in plugin approvals understandable at a glance while preserving the legacy raw behavior by default.
In short: keep the original technical approval prompt as the default, and add a plain-language approval mode for users who explicitly choose it.
What This Adds
This PR adds
approvals.plugin.languagewith three modes:original: existing raw technical plugin approval text. This remains the default.simple: a short plain-language prompt withAction,It will,Risk, and available choices.simple-technical: the plain-language prompt plus the raw technical fields below it.Example config:
{ "approvals": { "plugin": { "language": "simple" } } }The new renderer keeps interactive approval metadata intact so native Telegram/Matrix approval buttons can still be rendered. Text-only channels still get an actionable
/approve plugin:<id> allow-once|allow-always|denyfallback.Implementation
PluginApprovalLanguageconfig surface and validation.Command previewoutput for commands that are high risk or cannot be summarized completely.Safety Model
The important rule is: if
simplemode hides raw technical details, the summary must either explain the meaningful action or fail closed.Fail closed means the approval becomes higher risk and shows a redacted command preview instead of pretending the command is harmless.
The renderer now handles and tests common Codex app-server command shapes:
bash -lc,sh -c,zsh -c,env,timeout,set -a,source;&&,||,;, background&, conditionals, loops, and attached redirections likecat notes.txt>out.txt;cat,sed,find,rm,mkdir,touch,cp,mv, redirection writes;curlandwgetURL targets, upload operands, output operands, stdin upload via redirection, config/header/cookie/auth/netrc forms;git,docker, service managers, package managers, interpreters, logs/process inspection;ssh,scp, SSH remote commands, and SSH local-execution options such asProxyCommandandLocalCommand.Review And Hardening Trail
This PR went through a long approval-safety review loop because turning verbose technical prompts into plain language makes the summarizer security-sensitive.
Issues fixed during review:
cat -n .envdo not hide sensitive targets..envstyle local-file transfers.curl --data-binary @- ... < .env.printf ... > .env.sleep 1 & rm -rf /tmp/x.git -C repo reset --hardbefore classifying subcommands.findoutput-file predicates like-fprint,-fprint0,-fls, and-fprintfas writes.cat notes.txt>out.txt.ssh -o ProxyCommand=...andssh -o LocalCommand=....upstream/mainrepeatedly and regenerated the config baseline after conflicts.The latest ClawSweeper review no longer reports a concrete repair item. It now asks for human maintainer review of the opt-in approval-safety boundary and branch scope.
Current Status
91d6303a0e.Real behavior proofis successful.Verification
Local verification after the latest SSH hardening and main refresh:
pnpm config:docs:checknode scripts/run-vitest.mjs run --config test/vitest/vitest.unit-fast.config.ts src/plugin-sdk/approval-renderers.test.tsnode scripts/run-vitest.mjs run --config test/vitest/vitest.infra.config.ts src/infra/plugin-approval-forwarder.test.tsnode scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfopnpm check:test-typespnpm lint --threads=8Earlier focused verification also covered config schema/help quality, plugin SDK API baseline, gateway/channel state, and live renderer output.
Real behavior proof
approvals.plugin.languageis set tosimple. The old raw format remains the default throughoriginal./home/hadi/src/openclaw), the PR worktree, and Telegram channel status in polling mode.buildPluginApprovalRequestMessage(..., { language: "simple" }).pnpm build, restartedopenclaw-gateway.service, and checked gateway/Telegram channel state.Pipeline and unknown-stage proof:
Live channel state checked during proof:
Observed result after fix:
simplemode no longer includes the raw technical details block.Escaped shell separators such as
&&are decoded before parsing.Shell conditionals no longer surface as fake
run if/run thenactions.Non-shell pipeline stages are visible or fail closed with a high-risk preview.
Sensitive command previews are redacted before being shown in chat.
SSH local-execution options now fail closed with a high-risk preview.
What was not tested:
The Mantis Telegram Desktop GIF run skipped instead of producing before/after GIFs. This PR still has terminal renderer proof, live gateway/channel state proof, earlier Telegram screenshot proof, and a successful
Real behavior proofcheck.