Skip to content

Back to the catalog

AI SAST Finding: Path Traversal in OpenClaw via LLM Guardrail Bypass | Blog | Endor Labs
endorlabs.comwriteup

AI SAST Finding: Path Traversal in OpenClaw via LLM Guardrail Bypass | Blog | Endor Labs

Endor Labs details GHSA-r5fq-947m-xm57, a high-severity path traversal (CVSS 8.8) in OpenClaw's apply_patch tool that allows arbitrary file write/delete when sandboxRoot isn't configured, tracing the vulnerable code path from resolvePatchPath() through resolvePathFromCwd() to fs.writeFile/fs.rm. Because the tool is only invoked via LLM decision, the researcher bypassed the model's safety guardrails by injecting fabricated function_call/function_call_output entries into the /v1/responses conversation history, tricking the LLM via in-context learning into emitting a real malicious tool call with a traversal payload. This illustrates how LLM safety training can be the sole runtime control gating dangerous tool arguments, and how that control can be defeated with conversation history injection.

TL;DR Path traversal in OpenClaw's apply_patch (GHSA-r5fq-947m-xm57) was only exploitable by tricking the LLM into emitting the malicious tool call via fabricated conversation history — a novel guardrail bypass technique.
Document

What it is

GHSA-r5fq-947m-xm57: a high-severity path traversal (CVSS 8.8, CWE-22) in OpenClaw's apply_patch tool, allowing arbitrary file write and delete outside the workspace. Fixed in version >= 2026.2.14 (PR #16405). The sink is in resolvePatchPath() at lines 215–236 of src/agents/apply-patch.ts.

How it works

resolvePatchPath() branches on whether sandboxRoot is configured. When set, assertSandboxPath() blocks traversal. When unset — the default for native, non-Docker openclaw gateway run deployments — resolvePathFromCwd() calls path.resolve() and passes the result straight to fs.writeFile/fs.rm with no bounds check.

Because apply_patch fires only when the LLM decides to call it, the payload must pass through the model, whose safety training strips ../ or refuses. The bypass exploits that /v1/responses accepts a full input array including fabricated function_call and function_call_output entries. The attacker pre-seeds a fake history: a user request, a fabricated apply_patch call with ../../tmp/test1.txt, and a fabricated "Patch applied successfully" output. In-context learning normalizes the traversal, so the real final request for ../../../../tmp/test2.txt gets emitted as a genuine tool call and written to /tmp/test2.txt. OpenClaw compounds this by implementing tool_choice as a soft system-prompt injection (openresponses-http.ts:130-165), not a hard constraint — the model can still choose text.

Preconditions / Affected

  • Non-sandboxed deployment (native, no sandboxRoot) — Docker deployments with sandboxRoot were protected by assertSandboxPath() ("Path escapes sandbox root").
  • apply_patch enabled (default) and a valid API Bearer token for /v1/responses.

Documented impact: writing ~/.ssh/authorized_keys, overwriting ~/.openclaw/openclaw.json to disable auth, injecting cron jobs via /var/spool/cron/crontabs/, or deleting critical files.

What to do

Update to >= 2026.2.14, which adds a workspaceOnly option (default true) enforcing containment on the non-sandboxed path. If you can't update immediately:

  • Disable the tool: tools.exec.applyPatch.enabled: false
  • Confirm workspaceOnly is true (default, verify unchanged)
  • Restrict who holds Bearer tokens for /v1/responses
  • Run in Docker with sandboxRoot configured

Caveats

The bypass is non-deterministic — the pre-seeded history succeeded in testing (9 of 10 other strategies failed), but repeated runs yield different bypass rates. The author frames this variability as the core reason LLM safety training must not be treated as a security boundary. The AI SAST engine found the server-side bug; the guardrail bypass was characterized during manual exploit validation.

Organisations named here

  • GHSA-r5fq-947m-xm57

Technologies named here

  • OpenClaw
  • Endor Labs

Techniques named here

  • Path traversal