fix(node-host): sync rawCommand with hardened argv after executable path pinning#33137
Conversation
Greptile SummaryThis PR fixes a regression introduced by the GHSA-h3f9-mjwj-w476 security fix, where Key changes:
Confidence Score: 4/5
Last reviewed commit: b25ad3b |
b25ad3b to
9d1d007
Compare
…ath pinning The security fix for GHSA-h3f9-mjwj-w476 added rawCommand/command[] consistency validation. After hardenApprovedExecutionPaths pins an executable to its absolute path (e.g. echo → /usr/bin/echo), the rawCommand was not updated, causing all nodes.run direct commands to fail validation. Regenerate rawCommand via formatExecCommand(hardening.argv) when hardening produces a new argv, so the consistency check passes. Closes openclaw#33080
9d1d007 to
a798790
Compare
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 Control-character/log injection risk via rawCommand regeneration using formatExecCommand
Description
Because Security impact (grounded in current flows):
Vulnerable code (new behavior): const rawCommand = hardening.argvChanged
? formatExecCommand(hardening.argv) || null
: command.cmdText.trim() || null;Relevant formatter behavior: const needsQuotes = /\s|"/.test(arg);
return `"${arg.replace(/"/g, "\\\"")}"`;
// (no escaping/sanitization for \r, \n, \t, \x1b, etc.)RecommendationTreat Options (in increasing robustness):
export function formatExecCommandForDisplay(argv: string[]): string {
// JSON escaping distinguishes newline vs literal "\\n".
return argv.map((a) => JSON.stringify(a)).join(" ");
}
If you must keep a shell-like rendering, implement a dedicated escaping layer that:
Analyzed PR: #33137 at commit Last updated on: 2026-03-04T17:23:36Z |
* main: Compaction/Safeguard: require structured summary headings (openclaw#25555) Fix gateway restart false timeouts on Debian/systemd (openclaw#34874) fix(review): enforce behavioral sweep validation chore(changelog): clarify outbound media-only fallback openclaw#32788 thanks @liuxiaopai-ai fix(outbound): fail media-only text-only adapter fallback chore(changelog): align outbound adapter entry openclaw#32788 thanks @liuxiaopai-ai Outbound: avoid empty multi-media fallback sends Outbound: allow text-only plugin adapters chore(changelog): add PR entry openclaw#24337 thanks @echoVic test(ollama): add default header precedence coverage fix(ollama): pass provider headers to Ollama stream function (openclaw#24285) Agents: add generic poll-vote action support fix(node-host): sync rawCommand with hardened argv after executable path pinning (openclaw#33137) fix(daemon): handle systemctl is-enabled exit 4 (not-found) on Ubuntu (openclaw#33634) fix(model): propagate custom provider headers to model objects (openclaw#27490) fix(memory): serialize local embedding initialization to avoid duplicate model loads (openclaw#15639) Delete changelog/fragments directory fix(slack): route system events to bound agent sessions (openclaw#34045)
Summary
nodes.run(system.run) commands fail with "rawCommand does not match command". The security fix for GHSA-h3f9-mjwj-w476 added rawCommand/command[] consistency validation, buthardenApprovedExecutionPathspins executables to absolute paths without updating rawCommand.echo hello. Remote node execution is completely broken.formatExecCommand(hardening.argv)so the consistency check passes.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
nodes.runcommands work again after the 2026.3.2 security fix.Security Impact (required)
NoNoNoNo(restores pre-regression behavior)NoRepro + Verification
Environment
Steps
["echo", "hello"])Expected
Actual
Evidence
Identity comparison
hardening.argv === command.argvdetects when hardening created a new array. Test creates a PATH-resolvable symlink and verifies plan.rawCommand matches formatExecCommand(plan.argv).Human Verification (required)
Compatibility / Migration
YesNoNoFailure Recovery (if this breaks)
src/node-host/invoke-system-run-plan.tsRisks and Mitigations