fix: tighten openshell exec preflight · openclaw/openclaw@822ee62
steipete
·
2026-05-26
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai
|
15 | 15 | |
16 | 16 | ### Fixes |
17 | 17 | |
| 18 | +- OpenShell/SSH: reject malformed generated exec commands before sandbox/session setup so unresolved workflow placeholders fail fast instead of reaching the remote shell. Fixes #72373. Thanks @brokemac79. |
18 | 19 | - Installer: make Alpine apk installs cover Git, verify the Node runtime floor, try `nodejs-current`, and report Alpine version guidance when repositories only provide older Node packages. |
19 | 20 | - Agents/media: send direct fallback for generated media still missing after an active requester wake fails. (#85489) Thanks @fuller-stack-dev. |
20 | 21 | - Agents: derive overflow compaction budgets from provider-reported and synthetic over-budget token counts so confirmed context overflows compact before retrying. (#70473) Thanks @fuller-stack-dev. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -264,6 +264,7 @@ focused channel/runtime subpaths, `config-contracts`, `string-coerce-runtime`,
|
264 | 264 | | `plugin-sdk/tool-plugin` | Define a simple typed agent-tool plugin and expose static metadata for manifest generation | |
265 | 265 | | `plugin-sdk/tool-payload` | Extract normalized payloads from tool result objects | |
266 | 266 | | `plugin-sdk/tool-send` | Extract canonical send target fields from tool args | |
| 267 | +| `plugin-sdk/sandbox` | Sandbox backend types and SSH/OpenShell command helpers, including fail-fast exec command preflight | |
267 | 268 | | `plugin-sdk/temp-path` | Shared temp-download path helpers and private secure temp workspaces | |
268 | 269 | | `plugin-sdk/logging-core` | Subsystem logger and redaction helpers | |
269 | 270 | | `plugin-sdk/markdown-table-runtime` | Markdown table mode and conversion helpers | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -124,6 +124,8 @@ describe("sandbox ssh helpers", () => {
|
124 | 124 | it.each([ |
125 | 125 | ["workflow install <name>", /unresolved placeholder token <name>/], |
126 | 126 | ["workflow run <workflow-id> --ref main", /unresolved placeholder token <workflow-id>/], |
| 127 | +["echo $(workflow run <workflow-id> --ref main)", /unresolved placeholder token <workflow-id>/], |
| 128 | +["WORKFLOW_ID=<workflow-id> workflow run", /unresolved placeholder token <workflow-id>/], |
127 | 129 | ['echo "unterminated', /unclosed double quote/], |
128 | 130 | ["printf '%s", /unclosed single quote/], |
129 | 131 | ["echo foo\\", /trailing backslash escape/], |
@@ -148,6 +150,7 @@ describe("sandbox ssh helpers", () => {
|
148 | 150 | "cat < input.txt > output.txt", |
149 | 151 | "cat <in>out", |
150 | 152 | "cat <input> output", |
| 153 | +"cat = <input-file> output.txt", |
151 | 154 | 'cat <input-file> "output file"', |
152 | 155 | "cat <<'EOF' > literal.txt", |
153 | 156 | "<workflow-id>", |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -301,6 +301,9 @@ function readPlaceholderToken(command: string, index: number): string | null {
|
301 | 301 | if (!match) { |
302 | 302 | return null; |
303 | 303 | } |
| 304 | +if (command[index - 1] === "=") { |
| 305 | +return match[0]; |
| 306 | +} |
304 | 307 | if (isLikelyGeneratedWorkflowPlaceholder(command, index)) { |
305 | 308 | return match[0]; |
306 | 309 | } |
@@ -330,6 +333,8 @@ function isLikelyGeneratedWorkflowPlaceholder(command: string, index: number): b
|
330 | 333 | prefix.lastIndexOf(";"), |
331 | 334 | prefix.lastIndexOf("&"), |
332 | 335 | prefix.lastIndexOf("|"), |
| 336 | +prefix.lastIndexOf("("), |
| 337 | +prefix.lastIndexOf("`"), |
333 | 338 | ) + 1; |
334 | 339 | const currentCommand = prefix.slice(segmentStart).trim(); |
335 | 340 | return /^workflow(?:\s+[A-Za-z0-9._/-]+)*$/.test(currentCommand); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。