# OpenClaw apply_patch Path Traversal via LLM Guardrail Bypass (CVE-2026-32060 / GHSA-r5fq-947m-xm57)

> Path traversal in OpenClaw's apply_patch tool (npm openclaw <= 2026.2.13) allows an authenticated API caller to write or delete arbitrary files outside the workspace in non-sandboxed deployments. LLM guardrails were the only runtime control and were bypassed by injecting fabricated function_call and function_call_output entries into the /v1/responses input. Fixed in 2026.2.14.

- **Published:** 2026-11-11T02:28:05Z
- **Last reviewed:** 2026-11-11T02:28:05Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5716
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-5716.png
- **ID:** TL-2026-5716
- **Severity:** HIGH (CVSS 8.8)
- **Category:** VULNERABILITY
- **Status:** PATCHED
- **Detections:** 9 (1 shown free below) · **IOCs:** 8 (1 shown free below)
- **CVEs:** CVE-2026-32060, CVE-2026-32007

## Description

OpenClaw is an AI agent runtime that exposes an OpenResponses-compatible HTTP API (/v1/responses) and lets the model invoke tools, including apply_patch, which applies file patches. In src/agents/apply-patch.ts, resolvePatchPath() branches on whether a sandboxRoot is configured. With a sandbox root, assertSandboxPath() blocks traversal. Without one, which is the default for native non-containerized runs, resolvePathFromCwd() calls path.resolve() and returns the result with no containment check. The resolved path goes straight to fs.writeFile and fs.rm, so ../ sequences or absolute paths in a patch hunk can write or delete files anywhere the OpenClaw process can reach.

The only effective runtime control was the LLM's own reluctance to emit a traversal path. Endor Labs (AI SAST data-flow analysis plus manual exploit development) traced the flow parsePatchText() -> hunk.path -> resolvePatchPath() -> resolvePathFromCwd() -> path.resolve(cwd, filePath) -> fs.writeFile / fs.rm. Of 10 bypass strategies tried, 9 failed (5 silent non-compliance, 3 explicit refusals, 1 path sanitization). The strategy that worked abused two design properties. First, OpenClaw implements tool_choice as a system-prompt instruction rather than a hard API constraint (openresponses-http.ts:130-165). Second, /v1/responses accepts a caller-supplied input array that may contain function_call and function_call_output items. The attacker fabricates a prior conversation in which apply_patch was already called with a traversal path and reported success. Following that in-context precedent, the model emits a real function_call with the attacker's path, and the server executes it unvalidated. Results were non-deterministic.

The researcher's validated PoC (2026-02-04) demonstrated writing an SSH public key to ~/.ssh/authorized_keys for persistent access, overwriting ~/.openclaw/openclaw.json to disable authentication, injecting cron jobs for recurring command execution, and deleting critical files. Exploitation requires a valid Bearer token for the API and apply_patch enabled, which is the default. Impact depends on who can trigger tool execution. It is highest where tool invocation is exposed to less-trusted callers or operators assumed workspace-only containment.

The fix (PR #16405, squash-merge commit 5544646a09c0121fca7d7093812dc2de8437c7f1, released as 2026.2.14) reuses the sandbox path guard for non-sandbox resolution and enforces workspace-root bounds, rejecting relative traversal, absolute paths outside the workspace and symlink escapes. The advisory documents tools.exec.applyPatch.workspaceOnly (default true) as the control; setting it to false deliberately disables containment. The GitHub advisory (GHSA-r5fq-947m-xm57) lists no CVE. The CVE-2026-32060 identifier was published 2026-03-11 and maps to the same flaw (OpenClaw < 2026.2.14). A separate apply_patch bypass in opt-in sandbox mounts (GHSA-h9xm-j4qg-fvpg / CVE-2026-32007, fixed in 2026.2.23) is a different issue. No in-the-wild exploitation, threat actor or network infrastructure is reported in the sources.

## MITRE ATT&CK

- T1190 Exploit Public-Facing Application
- T1078 Valid Accounts
- T1098.004 SSH Authorized Keys
- T1053.003 Cron
- T1685 Disable or Modify Tools
- T1070.004 File Deletion
- T1485 Data Destruction
- AML.T0051 LLM Prompt Injection
- AML.T0054 LLM Jailbreak
- AML.T0053 AI Agent Tool Invocation

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**OpenClaw Process Writes SSH Keys, Cron or Auth Config Outside Workspace (CVE-2026-32060) — Post-Exploitation** (`TL-2026-5716-SPL-002`)

Detects the OpenClaw node process creating or modifying ~/.ssh/authorized_keys, ~/.openclaw/openclaw.json, or cron locations. These are the PoC targets for CVE-2026-32060: SSH key persistence, auth-disabling config overwrite and cron job injection through apply_patch fs.writeFile. Uses Sysmon for Linux file-create events.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1098.004, T1053.003, T1562.001
- **Data sources:** sysmon_for_linux, linux_auditd
- **Severity:** high
- **Confidence:** high

### Splunk SPL

```spl
index=linux sourcetype="sysmon:linux" EventCode=11 (Image="*/node" OR Image="*/openclaw") (TargetFilename="*/.ssh/authorized_keys" OR TargetFilename="*/.openclaw/openclaw.json" OR TargetFilename="/etc/crontab" OR TargetFilename="/etc/cron.*" OR TargetFilename="/var/spool/cron/*") | eval technique=case(like(TargetFilename,"%authorized_keys"),"T1098.004",like(TargetFilename,"%openclaw.json"),"T1562.001",true(),"T1053.003") | stats count min(_time) as first_seen max(_time) as last_seen values(TargetFilename) as files values(technique) as techniques by host, User, Image | convert ctime(first_seen) ctime(last_seen)
```

### Microsoft KQL

```kql
let SensitivePaths = dynamic(['/.ssh/authorized_keys', '/.openclaw/openclaw.json', '/etc/crontab', '/etc/cron.', '/var/spool/cron/']);
DeviceFileEvents
| where Timestamp > ago(24h)
| where ActionType in ('FileCreated', 'FileModified', 'FileRenamed')
| where InitiatingProcessFileName in~ ('node', 'openclaw')
| where FolderPath has_any (SensitivePaths)
| extend Technique = case(FolderPath endswith 'authorized_keys', 'T1098.004', FolderPath has 'openclaw.json', 'T1562.001', 'T1053.003')
| project Timestamp, DeviceName, ActionType, FolderPath, FileName, Technique, InitiatingProcessAccountName, InitiatingProcessCommandLine
```

### Sigma

```yaml
title: OpenClaw Process Modifies SSH Keys, Cron or Auth Config Outside Workspace (Splunk Primary)
id: 3c9d5a72-81b4-4f6e-a0d3-6e1b92c7f408
status: experimental
description: Detects the OpenClaw node process writing authorized_keys, openclaw.json or cron files, the PoC targets of CVE-2026-32060.
references:
  - https://github.com/openclaw/openclaw/security/advisories/GHSA-r5fq-947m-xm57
author: Threadlinqs Team
date: 2026-11-11
tags:
  - attack.persistence
  - attack.t1098.004
  - attack.execution
  - attack.t1053.003
  - attack.defense-evasion
  - attack.t1562.001
  - cve.2026-32060
logsource:
  product: linux
  category: file_event
detection:
  selection_proc:
    Image|endswith:
      - '/node'
      - '/openclaw'
  selection_target_end:
    TargetFilename|endswith:
      - '/.ssh/authorized_keys'
      - '/.openclaw/openclaw.json'
      - '/etc/crontab'
  selection_target_start:
    TargetFilename|startswith:
      - '/etc/cron.'
      - '/var/spool/cron/'
  condition: selection_proc and 1 of selection_target_*
falsepositives:
  - Node-based configuration management or deployment tooling managing cron or SSH keys
  - Legitimate OpenClaw onboarding that writes its own openclaw.json
level: high

```

**Known false positives:**

- Node-based configuration management or deployment tooling managing cron or SSH keys
- Legitimate OpenClaw onboarding or CLI that writes its own openclaw.json

**Tuning notes:** Exclude the openclaw.json write when performed by the expected 'openclaw' CLI during known change windows. Confirm Sysmon for Linux (or auditd watches on these paths) is deployed on OpenClaw hosts. File deletions (T1070.004, T1485) are not visible via Sysmon file-create; see the KQL-002 variant or add auditd unlink rules.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- [indicator] [indicator] Fabricated Tool History with apply_patch Traversal (Sentinel) — Exploitation (locked: unlock with TL Creds)
- [indicator] Process Modifies or Deletes Sensitive Files Outside Workspace (Defender for Endpoint) — Post-Exploitation (locked: unlock with TL Creds)
- SSH Key Login After [indicator] authorized_keys Modification (Sentinel) — Persistent Access (locked: unlock with TL Creds)
- [indicator] apply_patch Traversal via Fabricated function_call History (Sigma) — Exploitation (locked: unlock with TL Creds)
- [indicator] Process Writes authorized_keys, [indicator].json or Cron Files (Sigma) — Post-Exploitation (locked: unlock with TL Creds)
- [indicator] Process Writes SSH authorized_keys (Sigma) — Persistent Access Precursor (locked: unlock with TL Creds)
- [indicator] apply_patch Path Traversal via [indicator] (CVE-2026-32060) — Exploitation (locked: unlock with TL Creds)
- SSH Public-Key Login Following [indicator] authorized_keys Write (CVE-2026-32060) — Persistent Access (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (1 of 8)

Defanged, TLP:CLEAR.

- File hash: `5544646a09c0121fca7d7093812dc2de8437c7f1`

Full set of 8 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [AI SAST Finding: Path Traversal in OpenClaw via LLM Guardrail Bypass (Endor Labs)](https://www.endorlabs.com/learn/ai-sast-finding-path-traversal-in-openclaw-via-llm-guardrail-bypass)
- [GHSA-r5fq-947m-xm57: Path traversal in apply_patch could write/delete files outside the workspace](https://github.com/openclaw/openclaw/security/advisories/GHSA-r5fq-947m-xm57)
- [OpenClaw PR #16405: enforce workspace bounds for apply_patch in non-sandbox mode](https://github.com/openclaw/openclaw/pull/16405)
- [OpenClaw fix commit 5544646a09c0121fca7d7093812dc2de8437c7f1](https://github.com/openclaw/openclaw/commit/5544646a09c0121fca7d7093812dc2de8437c7f1)
- [Tenable: CVE-2026-32060](https://www.tenable.com/cve/CVE-2026-32060)
- [VulnCheck: OpenClaw path traversal in apply_patch via crafted paths](https://www.vulncheck.com/advisories/openclaw-path-traversal-in-apply-patch-via-crafted-paths)
- [ENISA EUVD-2026-11150](https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-11150)
- [GitLab Advisory Database: GHSA-r5fq-947m-xm57 (npm openclaw)](https://advisories.gitlab.com/npm/openclaw/GHSA-r5fq-947m-xm57/)
- [Positive Technologies dbugs PT-2026-24670](https://dbugs.ptsecurity.com/pt/vulnerability/PT-2026-24670)
- [Related: GHSA-h9xm-j4qg-fvpg / CVE-2026-32007 apply_patch sandbox-mount bypass](https://www.miggo.io/vulnerability-database/cve/GHSA-h9xm-j4qg-fvpg)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5716
