policy: cover gateway node commands#99121
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 4, 2026, 6:01 PM ET / 22:01 UTC. Summary PR surface: Source +157, Tests +154, Docs +32, Other +8. Total +351 across 12 files. Reproducibility: not applicable. as a bug reproduction; this is a feature PR. The PR body includes after-fix source-harness output showing the missing config-deny finding and the satisfied config-deny clean case. Review metrics: 1 noteworthy metric.
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:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this as a detect-only Policy plugin rule only after maintainer approval of the exact, case-sensitive deny-superset semantics and a green head check set, while keeping runtime gateway command enforcement unchanged. Do we have a high-confidence way to reproduce the issue? Not applicable as a bug reproduction; this is a feature PR. The PR body includes after-fix source-harness output showing the missing config-deny finding and the satisfied config-deny clean case. Is this the best way to solve the issue? Yes, with maintainer approval: the Policy plugin is the right owner because it observes the existing AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 27d6c8816721. Label changesLabel justifications:
Evidence reviewedPR surface: Source +157, Tests +154, Docs +32, Other +8. Total +351 across 12 files. View PR surface stats
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
Review history (6 earlier review cycles)
|
5d963e8 to
529fd4d
Compare
|
Added real behavior proof to the PR body for both missing and satisfied gateway.nodes.denyCommands cases. @clawsweeper re-review |
|
Maintainer confirmation: this PR's intended managed-policy contract is correct. policy.jsonc gateway.nodes.denyCommands should require OpenClaw config gateway.nodes.denyCommands to cover the policy denylist with exact, case-sensitive command IDs. Deployments that intentionally allow a privileged node command should update policy after review rather than silently relying on an allowCommands widening. |
|
Added policy docs for the new gateway.nodes.denyCommands policy rule and updated validation. @clawsweeper re-review |
|
CI stabilization update pushed: What changed:
Validation run locally from
|
|
Codex review of the Gateway Node Policy PR. Findings:
Best-fix verdict: close, but not quite the best fix until the inventory tracks Evidence checked: |
|
Addressed Omar's finding in |
|
@clawsweeper re-review Reviewer-requested fixes are pushed on this updated head. Fresh local proof before push: focused policy/core/CLI/tooling Vitest passed, |
|
🦞🧹 I asked ClawSweeper to review this item again. |
8b97698 to
21347f2
Compare
|
Merged via rebase.
|
Summary - add policy evidence for
gateway.nodes.allowCommandsandgateway.nodes.denyCommandsentries - addgateway.nodes.denyCommandspolicy metadata and shape validation - reportpolicy/gateway-node-command-deniedwhen policy-denied node commands are not denied by OpenClaw config - document the new policy rule in the Policy CLI and plugin reference docs - classifygateway.nodes.allowCommands.*in policy config coverage ## Policy syntax / evidence / finding contract Policy syntax added by this PR:jsonc { "gateway": { "nodes": { "denyCommands": ["system.run"] } } }gateway.nodes.denyCommandsis an exact, case-sensitive deny-superset rule. An equal-or-stricter policy must include every command required by the baseline deny list. Empty or missingdenyCommandsmeans this rule is not active. OpenClaw config evidence collected by policy doctor:jsonc { "gateway": { "nodes": { "allowCommands": ["mcp.help", "mcp.invoke", "system.run"], "denyCommands": ["system.run"] } } }The evidence scanner records concrete config entries as:text kind=nodeAllowCommand command=system.run source=oc://openclaw.config/gateway/nodes/allowCommands/#2 kind=nodeDenyCommand command=system.run source=oc://openclaw.config/gateway/nodes/denyCommands/#0Finding emitted when policy requires a deny but config does not provide it:json { "checkId": "policy/gateway-node-command-denied", "severity": "error", "message": "Gateway node command 'system.run' is denied by policy but not denied by OpenClaw config.", "path": "openclaw config", "ocPath": "oc://openclaw.config/gateway/nodes/denyCommands", "target": "oc://openclaw.config/gateway/nodes/denyCommands", "requirement": "oc://policy.jsonc/gateway/nodes/denyCommands", "fixHint": "Add 'system.run' to gateway.nodes.denyCommands or update policy after review." }The finding clears when the config deny list contains the required exact command id.allowCommandsevidence is collected for coverage and context; this PR only enforces the policy deny-superset contract. ## Real behavior proof Behavior or issue addressed: Managed policy can now require privileged gateway node commands such assystem.runto be denied in OpenClaw config viagateway.nodes.denyCommands. The policy doctor reports the missing config deny and clears once the config denylist covers the policy denylist. Real environment tested: Windows 11 PowerShell,C:\src\openclaw-forkcheckout at PR headcfe901e17963d9fe1833266a2758f125d7a51762, source-harness invocation of the real policy doctor health checks throughrunDoctorLintChecks. The harness wrote real temporaryopenclaw.jsoncandpolicy.jsoncfiles under%TEMP%; no cloud gateway or Lobster deployment was involved. Exact steps or command run after this patch: 1. Ran a Node/tsx source harness from the repo root that importedregisterPolicyDoctorChecksandrunDoctorLintChecks. 2. Casemissing-config-deny: wrotepolicy.jsoncwithgateway.nodes.denyCommands: ["system.run"]andopenclaw.jsoncwithgateway.nodes.allowCommands: ["mcp.help", "mcp.invoke", "system.run"]and no configdenyCommands. 3. Casesatisfied-config-deny: wrote the same policy plusopenclaw.jsoncwithgateway.nodes.denyCommands: ["system.run"]. Evidence after fix:text CASE missing-config-deny workspace: C:\Users\giodl\AppData\Local\Temp\oc-policy-missing-config-deny-Xk9xXX openclaw.jsonc gateway.nodes: {"allowCommands":["mcp.help","mcp.invoke","system.run"]} policy.jsonc gateway.nodes.denyCommands: ["system.run"] finding.checkId: policy/gateway-node-command-denied finding.severity: error finding.message: Gateway node command 'system.run' is denied by policy but not denied by OpenClaw config. finding.ocPath: oc://openclaw.config/gateway/nodes/denyCommands finding.target: oc://openclaw.config/gateway/nodes/denyCommands finding.requirement: oc://policy.jsonc/gateway/nodes/denyCommands finding.fixHint: Add 'system.run' to gateway.nodes.denyCommands or update policy after review. CASE satisfied-config-deny workspace: C:\Users\giodl\AppData\Local\Temp\oc-policy-satisfied-config-deny-jngRgn openclaw.jsonc gateway.nodes: {"allowCommands":["mcp.help","mcp.invoke","system.run"],"denyCommands":["system.run"]} policy.jsonc gateway.nodes.denyCommands: ["system.run"] policy/gateway-node-command-denied findings: noneObserved result after fix: The missing config-deny case emits exactly onepolicy/gateway-node-command-deniederror targeted atoc://openclaw.config/gateway/nodes/denyCommands. The satisfied config-deny case emits no finding for that check. What was not tested: This was source-harness policy doctor proof, not a live Lobster/cloud gateway run. Cloud gateway rollout behavior forsystem.runallowlisting remains a separate Lobster deployment concern. ## Validation -node scripts/run-vitest.mjs run extensions/policy/src/doctor/register.test.ts extensions/policy/src/doctor/strictness.test.ts --reporter=dot-node --import tsx scripts/check-policy-config-coverage.ts --check --json-./node_modules/oxfmt/bin/oxfmt --check extensions/policy/src/doctor/metadata.ts extensions/policy/src/doctor/scopes/gateway.ts extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts extensions/policy/src/doctor/strictness.test.ts extensions/policy/src/policy-state.ts scripts/lib/policy-config-coverage.jsonc-./node_modules/oxlint/bin/oxlint extensions/policy/src/doctor/metadata.ts extensions/policy/src/doctor/scopes/gateway.ts extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts extensions/policy/src/doctor/strictness.test.ts extensions/policy/src/policy-state.ts-./node_modules/.bin/oxfmt.cmd --check docs/cli/policy.md docs/plugins/reference/policy.md extensions/policy/src/doctor/metadata.ts extensions/policy/src/doctor/scopes/gateway.ts extensions/policy/src/doctor/register.ts extensions/policy/src/doctor/register.test.ts extensions/policy/src/doctor/strictness.test.ts extensions/policy/src/policy-state.ts scripts/lib/policy-config-coverage.jsonc-node scripts/check-docs-mdx.mjs docs README.md-git diff --check-pnpm tsgo:test:extensions-codex review --base upstream/main## Notes This gives managed policy a way to require privileged gateway node commands such assystem.runto be present ingateway.nodes.denyCommandsunless a deployment intentionally relaxes policy. The rule uses the existingdenylist-supersetstrictness pattern and keeps node command IDs case-sensitive.## Real behavior proofBehavior or issue addressed:Gateway node command policy coverage stays intact after restacking onto currentupstream/main; the stack also resolves theplugin-sdk-surface-report.test.tsmerge conflict by preserving CI budget-env isolation.Real environment tested:Windows PowerShell inC:\src\openclaw-forkon the restacked policy series, top head7aebf26a24with the foundation branch head8b97698d63. This is a source-harness proof; it does not start a packaged OpenClaw binary or make live LLM calls.Exact steps or command run after this patch:1.node scripts/run-vitest.mjs extensions/policy/src/doctor/metadata.test.ts extensions/policy/src/doctor/register.test.ts extensions/policy/src/doctor/strictness.test.ts src/flows/doctor-repair-flow.test.ts --reporter=dot2.node scripts/run-vitest.mjs test/scripts/plugin-sdk-surface-report.test.ts --reporter=dot3.pnpm tsgo:extensions4.pnpm lint:extensions5.git diff --checknode --import tsx scripts/check-policy-config-coverage.ts --check --jsonEvidence after fix:The focused policy/core/CLI/tooling Vitest run passed 10 core repair-flow tests, 7 SDK surface tooling tests, 13 policy CLI tests, and 334 policy doctor/doctor-lint tests.tsgo:extensions,lint:extensions,git diff --check, andnode --import tsx scripts/check-policy-config-coverage.ts --check --jsonall exited 0.Observed result after fix:Gateway node command policy coverage remains green, and the restacked branch no longer has the generated SDK surface test conflict against currentmain.What was not tested:No packaged CLI smoke, live provider run, or live LLM call was run for this restack proof.