Skip to content

fix(exec): fail closed on Windows shell wrappers in allowlist mode#67655

Closed
plgonzalezrx8 wants to merge 2 commits into
openclaw:mainfrom
plgonzalezrx8:fix-allowlist-bypass-for-powershell-wrappers-upstream-2026-04-16
Closed

fix(exec): fail closed on Windows shell wrappers in allowlist mode#67655
plgonzalezrx8 wants to merge 2 commits into
openclaw:mainfrom
plgonzalezrx8:fix-allowlist-bypass-for-powershell-wrappers-upstream-2026-04-16

Conversation

@plgonzalezrx8

@plgonzalezrx8 plgonzalezrx8 commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Issue

In Windows allowlist mode, the wrapper guard only failed closed for cmd.exe-style invocations. That left a gap where other shell-wrapper transports such as powershell -Command could still be analyzed like a normal allowlisted command, which is the wrong security posture for inline shell payloads and command chaining.

Fix

  • block any Windows shell-wrapper transport in allowlist mode when shellWrapperInvocation is true, instead of limiting the guard to cmdInvocation
  • update the denial guidance so it explicitly calls out powershell -Command alongside cmd.exe /c
  • add regression coverage for the Windows PowerShell-wrapper path in src/node-host/exec-policy.test.ts

How to test

  • run: pnpm test src/node-host/exec-policy.test.ts src/node-host/invoke-system-run.test.ts -t "PowerShell|shell wrapper|cmd.exe wrappers|allowlist"
  • verify the new PowerShell-wrapper regression covers isWindows: true, shellWrapperInvocation: true, and cmdInvocation: false
  • confirm the decision is denied, windowsShellWrapperBlocked is set, and the error guidance mentions powershell -Command

@plgonzalezrx8 plgonzalezrx8 changed the title fix(exec): block Windows shell wrappers from allowlist bypass fix(exec): fail closed on Windows shell wrappers in allowlist mode Apr 16, 2026
@greptile-apps

greptile-apps Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR closes an allowlist-bypass for Windows shell wrappers other than cmd.exe (e.g. PowerShell) by removing the cmdInvocation guard from windowsShellWrapperBlocked, and updates the denial message to mention powershell -Command.

  • The new regression test for the PowerShell path is correct, but the existing formatSystemRunAllowlistMissMessage unit test (lines 67–74 of exec-policy.test.ts) was not updated: it asserts .toContain(\"Windows shell wrappers like cmd.exe /c require approval\"), which is no longer a substring of the broadened message, so this test will fail as submitted.

Confidence Score: 4/5

Not safe to merge as-is — a stale test assertion will fail in CI.

The security fix itself is correct and the new PowerShell regression test is well written, but the existing formatSystemRunAllowlistMissMessage test was left with a substring that no longer appears in the updated message, which will cause a test failure. That P1 must be fixed before landing.

src/node-host/exec-policy.test.ts lines 67–74 — stale .toContain() assertion needs to match the new message text.

Comments Outside Diff (2)

  1. src/node-host/exec-policy.test.ts, line 67-74 (link)

    P1 Stale assertion will fail after message change

    The .toContain("Windows shell wrappers like cmd.exe /c require approval") assertion no longer matches because exec-policy.ts line 38-39 now inserts " or powershell -Command" between "cmd.exe /c" and " require approval", breaking the substring match. This test will fail as written.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/node-host/exec-policy.test.ts
    Line: 67-74
    
    Comment:
    **Stale assertion will fail after message change**
    
    The `.toContain("Windows shell wrappers like cmd.exe /c require approval")` assertion no longer matches because `exec-policy.ts` line 38-39 now inserts `" or powershell -Command"` between `"cmd.exe /c"` and `" require approval"`, breaking the substring match. This test will fail as written.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. src/node-host/exec-policy.ts, line 61 (link)

    P2 cmdInvocation is now an unused parameter

    After dropping params.cmdInvocation from the windowsShellWrapperBlocked expression, this required parameter has no effect on the function's output. If the intent is to preserve the public API surface (callers still populate it), add a brief comment explaining that; otherwise remove it and update call sites to avoid dead code and potential lint warnings from no-unused-vars.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/node-host/exec-policy.ts
    Line: 61
    
    Comment:
    **`cmdInvocation` is now an unused parameter**
    
    After dropping `params.cmdInvocation` from the `windowsShellWrapperBlocked` expression, this required parameter has no effect on the function's output. If the intent is to preserve the public API surface (callers still populate it), add a brief comment explaining that; otherwise remove it and update call sites to avoid dead code and potential lint warnings from `no-unused-vars`.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/node-host/exec-policy.test.ts
Line: 67-74

Comment:
**Stale assertion will fail after message change**

The `.toContain("Windows shell wrappers like cmd.exe /c require approval")` assertion no longer matches because `exec-policy.ts` line 38-39 now inserts `" or powershell -Command"` between `"cmd.exe /c"` and `" require approval"`, breaking the substring match. This test will fail as written.

```suggestion
  it("adds Windows shell-wrapper guidance when blocked by Windows shell wrapper policy", () => {
    expect(
      formatSystemRunAllowlistMissMessage({
        shellWrapperBlocked: true,
        windowsShellWrapperBlocked: true,
      }),
    ).toContain("Windows shell wrappers like cmd.exe /c or powershell -Command require approval");
  });
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/node-host/exec-policy.ts
Line: 61

Comment:
**`cmdInvocation` is now an unused parameter**

After dropping `params.cmdInvocation` from the `windowsShellWrapperBlocked` expression, this required parameter has no effect on the function's output. If the intent is to preserve the public API surface (callers still populate it), add a brief comment explaining that; otherwise remove it and update call sites to avoid dead code and potential lint warnings from `no-unused-vars`.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(exec): block Windows shell wrappers ..." | Re-trigger Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d523e57e62

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node-host/exec-policy.ts Outdated
return (
"SYSTEM_RUN_DENIED: allowlist miss " +
"(Windows shell wrappers like cmd.exe /c require approval; " +
"(Windows shell wrappers like cmd.exe /c or powershell -Command require approval; " +

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve message compatibility with existing allowlist tests

The updated denial text in formatSystemRunAllowlistMissMessage inserts or powershell -Command between cmd.exe /c and require approval, which no longer matches the existing assertions that still expect the old contiguous phrase (src/node-host/exec-policy.test.ts:67-74 and src/node-host/invoke-system-run.test.ts:25-31). This commit therefore introduces deterministic test regressions unless the dependent checks are updated in the same change or the message keeps a backward-compatible substring.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as superseded: the merged payload-evaluation fix in #80978 covers the useful Windows shell-wrapper allowlist hardening on current main, while this branch's remaining blanket PowerShell fail-closed behavior would add compatibility risk.

Canonical path: Keep the merged payload-evaluation policy from #80978; open a narrow docs follow-up only if node docs need to describe the current PowerShell payload-evaluation behavior more precisely.

So I’m closing this here and keeping the remaining discussion on #80978.

Review details

Best possible solution:

Keep the merged payload-evaluation policy from #80978; open a narrow docs follow-up only if node docs need to describe the current PowerShell payload-evaluation behavior more precisely.

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

Yes for source-level review: current main tests and allowlist code show the original bare PowerShell wrapper allowlist gap is covered by payload evaluation. I did not run a live Windows node exec scenario in this read-only review.

Is this the best way to solve the issue?

No. The merged payload-evaluation approach in #80978 is the better fix because it rejects bare wrapper matches without blanket-denying allowlisted inner payloads.

Security review:

Security review cleared: No concrete supply-chain regression was found; the security concern here is merge compatibility with the already-merged exec approval policy, not new dependencies or secret handling.

AGENTS.md: found and applied where relevant.

What I checked:

Likely related people:

  • pgondhi987: Authored the merged current-main shell-wrapper payload matching work and the related PowerShell encoded-command parser fix that supersede this branch's useful hardening. (role: recent adjacent contributor; confidence: high; commits: 50f4440c9663, de47989731d3; files: src/infra/exec-approvals-allowlist.ts, src/infra/shell-inline-command.ts, src/infra/shell-wrapper-resolution.ts)
  • BradGroux: Prepared the current PR head, aligned tests/docs after early review feedback, and recorded local verification commands for the branch. (role: branch preparer and recent review context; confidence: medium; commits: 3baf42a36bcd; files: src/node-host/exec-policy.ts, src/node-host/exec-policy.test.ts, docs/nodes/index.md)

Codex review notes: model internal, reasoning high; reviewed against 4644e0c10256.

@BradGroux
BradGroux force-pushed the fix-allowlist-bypass-for-powershell-wrappers-upstream-2026-04-16 branch from d523e57 to 3baf42a Compare May 8, 2026 17:31
@BradGroux

Copy link
Copy Markdown
Contributor

Maintainer update: rebased this onto current main and prepared the branch at 3baf42a36bcdef3a304f90e741fe13df09f03685.

What changed in the prepared head:

  • Kept the fail-closed Windows shell-wrapper allowlist behavior.
  • Aligned denial copy and tests for cmd.exe /c, powershell, and pwsh -Command wrapper runs.
  • Updated node docs/troubleshooting guidance for the broadened Windows wrapper approval behavior.
  • Added the required changelog entry with contributor attribution.

Verification run locally:

  • pnpm test -- src/node-host/exec-policy.test.ts src/node-host/invoke-system-run.test.ts -t "PowerShell|shell wrapper|cmd.exe wrappers|allowlist" (13 tests passed, 26 skipped by filter)
  • pnpm build
  • pnpm check

Waiting on fresh CI/ClawSweeper for this prepared head before merge.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation plugin: file-transfer triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 8, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jun 6, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 6, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jun 7, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@clawsweeper

clawsweeper Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

@clawsweeper clawsweeper Bot closed this Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. plugin: file-transfer rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants