Skip to content

fix: harden safe-bin argument validation [AI]#80999

Merged
pgondhi987 merged 9 commits into
openclaw:mainfrom
pgondhi987:fix/fix-624
May 12, 2026
Merged

fix: harden safe-bin argument validation [AI]#80999
pgondhi987 merged 9 commits into
openclaw:mainfrom
pgondhi987:fix/fix-624

Conversation

@pgondhi987

Copy link
Copy Markdown
Contributor

Summary

  • Problem: safe-bin allowlist checks accepted shell-expanded argument forms as literal value tokens.
  • Why it matters: argument validation should fail closed when shell transport can rewrite token boundaries before execution.
  • What changed: safe-bin validation now rejects POSIX-style parameter expansion tokens, with regression coverage in policy and node-host system.run paths.
  • What did NOT change (scope boundary): no default safe-bin list, config schema, permissions, or network behavior changed.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Related: N/A
  • This PR fixes a bug or regression

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: safe-bin allowlist argument validation rejects shell-expanded token carriers before dispatch.
  • Real environment tested: Not run in this metadata drafting step.
  • Exact steps or command run after this patch: N/A
  • Evidence after fix: N/A
  • Observed result after fix: N/A
  • What was not tested: full OpenClaw runtime pairing flow and repository test wrapper.
  • Before evidence: N/A

Root Cause (if applicable)

  • Root cause: safe-bin literal-token validation blocked paths and globbing but did not reject shell parameter-expansion forms that can alter argv boundaries at runtime.
  • Missing detection / guardrail: regression coverage did not include shell-expanded safe-bin option values or positional tokens.
  • Contributing context (if known): safe-bin checks operate before shell transport executes the command.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/infra/exec-approvals-safe-bins.test.ts; src/node-host/invoke-system-run.test.ts
  • Scenario the test should lock in: shell-expanded safe-bin value and positional tokens are denied before command execution.
  • Why this is the smallest reliable guardrail: it covers the shared validator plus the node-host system.run policy path without requiring a full gateway run.
  • Existing test that already covers this (if any): none specific to this token-carrier form.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

Safe-bin allowlist mode is stricter for shell-expanded argument tokens. Commands using those forms now require approval or fail allowlist matching instead of being auto-allowed.

Diagram (if applicable)

Before:
[system.run safe-bin command] -> [literal-token check passes] -> [shell may rewrite argv]

After:
[system.run safe-bin command] -> [expansion-token check fails] -> [allowlist miss]

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? Yes
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: command execution allowlist behavior is narrowed for safe-bin arguments that can be rewritten by shell expansion; mitigation is fail-closed validation with regression coverage.

Repro + Verification

Environment

  • OS: Linux-compatible POSIX path covered by tests
  • Runtime/container: Node test runtime
  • Model/provider: N/A
  • Integration/channel (if any): node-host system.run
  • Relevant config (redacted): tools.exec security allowlist, ask off, default safe bins

Steps

  1. Submit a safe-bin shell-wrapper command containing parameter expansion in an option value.
  2. Evaluate allowlist policy.
  3. Confirm the command is denied before runCommand dispatch.

Expected

  • Allowlist matching fails and the command is not executed.

Actual

  • Covered by added regression tests; full wrapper command not run during metadata drafting.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: reviewed validator and regression-test changes for safe-bin value and positional token handling.
  • Edge cases checked: short option value, long option value, positional token, node-host system.run allowlist miss.
  • What you did not verify: full OpenClaw runtime pairing flow; repository test wrapper in this PR drafting step.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: some previously auto-allowed safe-bin shell commands with literal dollar-sign arguments may now require approval.
    • Mitigation: the change is scoped to safe-bin literal validation, and explicit approval remains available for intentional commands.

AI-assisted: yes

@openclaw-barnacle openclaw-barnacle Bot added size: XS maintainer Maintainer-authored PR labels May 12, 2026
@clawsweeper

clawsweeper Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge.

Summary
The branch rejects POSIX shell-expansion carriers in safe-bin argument validation, rewrites POSIX safe-bin shell payloads before system.run dispatch, and adds policy/node-host regression tests.

Reproducibility: yes. By source inspection, current main accepts these safe-bin value and positional tokens through isSafeLiteralToken while the docs promise no $VARS expansion for safe bins; I did not run a live repro because this review is read-only.

Real behavior proof
Needs real behavior proof before merge: Missing: the PR body says no real environment command was run and after-fix evidence is N/A; the contributor should add redacted terminal output, logs, screenshot, recording, live output, or a linked artifact showing a real after-fix system.run denial, then update the PR body to trigger re-review or ask a maintainer to comment @clawsweeper re-review.

Next step before merge
Remaining blockers are contributor-supplied real behavior proof and explicit protected-label maintainer handling, not a narrow repair-lane code defect.

Security
Cleared: The diff narrows command-execution allowlist behavior and adds targeted tests; I found no new dependency, workflow, secret, permission, or supply-chain exposure.

Review details

Best possible solution:

Land the fail-closed validator and POSIX shell-payload rewrite after the contributor supplies redacted real system.run denial proof and a maintainer accepts the protected security-policy change.

Do we have a high-confidence way to reproduce the issue?

Yes. By source inspection, current main accepts these safe-bin value and positional tokens through isSafeLiteralToken while the docs promise no $VARS expansion for safe bins; I did not run a live repro because this review is read-only.

Is this the best way to solve the issue?

Yes. The proposed direction is the narrow maintainable fix: reject expansion carriers in the shared safe-bin validator and rebuild POSIX safe-bin shell payloads before dispatch, with merge held for proof and protected-label handling.

Acceptance criteria:

  • pnpm test src/infra/exec-approvals-safe-bins.test.ts src/node-host/invoke-system-run.test.ts

What I checked:

Likely related people:

  • steipete: Peter Steinberger authored the safe-bin policy centralization and module split that created the current validator path touched by this PR. (role: introduced behavior / feature owner; confidence: high; commits: 0d0f4c699237, 9530c0108589; files: src/infra/exec-safe-bin-policy.ts, src/infra/exec-safe-bin-policy-validator.ts, src/infra/exec-approvals-allowlist.ts)
  • pgondhi987: Current-main history attributes recent shell-wrapper and inline-command hardening near this system.run/exec analysis path to Pavan Kumar Gondhi, beyond this PR branch itself. (role: recent adjacent contributor; confidence: medium; commits: de47989731d3, 50f4440c9663; files: src/infra/shell-inline-command.ts, src/infra/shell-wrapper-resolution.ts, src/infra/system-run-command.ts)

Remaining risk / open question:

  • No after-fix real behavior proof is present for a real system.run denial path; tests are supplemental only for this external PR gate.
  • The protected maintainer label requires explicit maintainer handling before merge.

Codex review notes: model gpt-5.5, reasoning high; reviewed against ac3bf79d9d8b.

@pgondhi987

Copy link
Copy Markdown
Contributor Author

Not applicable to this automation stage; changelog/release-note and external real behavior proof requirements are handled outside auto-pr stages.

Quoted comment from @clawsweeper:

Codex review: needs real behavior proof before merge.

Summary
The PR rejects shell-expansion tokens in safe-bin literal argument validation and adds regression coverage for policy and node-host system.run allowlist paths.

Reproducibility: yes. by source inspection: current main accepts safe-bin values and positionals through isSafeLiteralToken, which only checks glob and path-like tokens. I did not execute the repro because this sweep is read-only.

Real behavior proof
Needs real behavior proof before merge: The PR body explicitly says no real environment command was run and evidence is N/A, so the contributor needs after-fix terminal output, logs, screenshot, recording, or linked artifact from a real system.run denial with private details redacted; updating the PR body should trigger a fresh ClawSweeper review, or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, ask a maintainer to comment @clawsweeper re-review.

Next step before merge
Not a repair-lane candidate because the remaining blockers are external real behavior proof and protected-label maintainer handling, not a narrow automation repair.

Security
Cleared: The diff narrows the command execution allowlist surface and adds targeted tests; I found no new secret, permission, dependency, or supply-chain exposure.

Review details

Best possible solution:

Land a shared-validator fail-closed check with the added regression coverage after the contributor supplies real system.run denial proof and a maintainer accepts the stricter safe-bin policy.

Do we have a high-confidence way to reproduce the issue?

Yes, by source inspection: current main accepts safe-bin values and positionals through isSafeLiteralToken, which only checks glob and path-like tokens. I did not execute the repro because this sweep is read-only.

Is this the best way to solve the issue?

Yes, the proposed direction is the narrowest maintainable fix: reject expansion carriers in the shared safe-bin literal validator and cover both direct policy and node-host system.run paths. Merge should wait for real behavior proof and maintainer review.

What I checked:

  • Current validator gap: Current main's safe-bin literal check rejects glob and path-like tokens, but it has no shell-expansion-token check before accepting option values or positionals. (src/infra/exec-safe-bin-policy-validator.ts:34, 3a4c97c291da)
  • Safe-bin runtime path: isSafeBinUsage resolves a trusted safe-bin executable and then delegates argv validation to validateSafeBinArgv, so the shared validator is the right place to fail closed. (src/infra/exec-approvals-allowlist.ts:65, 3a4c97c291da)
  • Node-host shell path: system.run evaluates shell payloads through evaluateShellAllowlist while threading safe-bin profiles and trusted dirs, so the PR's node-host regression target is on the relevant dispatch path. (src/node-host/invoke-system-run-allowlist.ts:36, 3a4c97c291da)
  • PR diff coverage: The PR adds hasShellExpansionToken to safe literal validation and tests short-option values, long-option values, positionals, and a node-host system.run allowlist miss. (src/infra/exec-safe-bin-policy-validator.ts:29, 24fb806d7390)
  • Real behavior proof gap: The PR body says the real environment was not run and after-fix evidence is N/A, so the external proof gate is not satisfied. (24fb806d7390)
  • Protected label: The provided GitHub context shows the maintainer label on this PR, which blocks conservative cleanup closure and requires explicit maintainer handling.

Likely related people:

  • Peter Steinberger: Authored the commits that centralized safe-bin policy checks and split the safe-bin validator/profile modules now touched by this PR. (role: introduced behavior / feature owner; confidence: high; commits: 0d0f4c699237, 9530c0108589; files: src/infra/exec-safe-bin-policy.ts, src/infra/exec-safe-bin-policy-validator.ts, src/infra/exec-approvals-allowlist.ts)
  • pgondhi987: Current-main history in this checkout attributes recent exec and node-host inline-command hardening to Pavan Kumar Gondhi, including adjacent tests in invoke-system-run.test.ts. (role: recent area contributor; confidence: medium; commits: 47eb2d48d434, de47989731d3; files: src/infra/exec-safe-bin-policy-validator.ts, src/infra/exec-approvals-allowlist.ts, src/node-host/invoke-system-run.test.ts)

Remaining risk / open question:

  • No after-fix real behavior proof is attached for the external PR; tests and source review are supplemental only.
  • The change intentionally narrows safe-bin allowlisting, so maintainers should accept the fail-closed behavior for literal-dollar safe-bin arguments before merge.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 3a4c97c291da.

@pgondhi987
pgondhi987 merged commit 9ac4272 into openclaw:main May 12, 2026
eleqtrizit pushed a commit to eleqtrizit/openclaw that referenced this pull request May 14, 2026
* fix: reject shell expansion in safe-bin tokens

* fix: complete safe-bin shell payload handling

* addressing codex review

* addressing ci

* addressing ci

* addressing codex review

* docs: add changelog entry for PR merge
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix: reject shell expansion in safe-bin tokens

* fix: complete safe-bin shell payload handling

* addressing codex review

* addressing ci

* addressing ci

* addressing codex review

* docs: add changelog entry for PR merge
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
* fix: reject shell expansion in safe-bin tokens

* fix: complete safe-bin shell payload handling

* addressing codex review

* addressing ci

* addressing ci

* addressing codex review

* docs: add changelog entry for PR merge
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
* fix: reject shell expansion in safe-bin tokens

* fix: complete safe-bin shell payload handling

* addressing codex review

* addressing ci

* addressing ci

* addressing codex review

* docs: add changelog entry for PR merge
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant