Skip to content

Commit 53c2d94

Browse files
1 parent cc50335 commit 53c2d94

File tree

3 files changed

+194
-0
lines changed

3 files changed

+194
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-74wf-h43j-vvmj",
4+
"modified": "2026-03-26T21:46:42Z",
5+
"published": "2026-03-26T21:46:42Z",
6+
"aliases": [],
7+
"summary": "OpenClaw's Conflicting Tool Identity Hints Bypass Dangerous-Tool Prompting",
8+
"details": "## Summary\nACP permission resolution trusted conflicting tool identity hints from rawInput and metadata, which could suppress dangerous-tool prompting.\n\n## Affected Packages / Versions\n- Package: `openclaw` (npm)\n- Affected: < 2026.3.22\n- Fixed: >= 2026.3.22\n- Latest released tag checked: `v2026.3.23-2` (`630f1479c44f78484dfa21bb407cbe6f171dac87`)\n- Latest published npm version checked: `2026.3.23-2`\n\n## Fix Commit(s)\n- `e4c61723cd2d530680cc61789311d464ab8cdf60`\n\n## Release Status\nThe fix shipped in `v2026.3.22` and remains present in `v2026.3.23` and `v2026.3.23-2`.\n\n## Code-Level Confirmation\n- src/acp/client.ts now fails closed when meta, rawInput, and title tool identities conflict instead of trusting spoofable raw input.\n- src/acp/client.test.ts ships regressions for conflicting tool identity hints and dangerous-tool prompting.\n\nOpenClaw thanks @zpbrent for reporting.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "openclaw"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "2026.3.22"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-74wf-h43j-vvmj"
40+
},
41+
{
42+
"type": "WEB",
43+
"url": "https://github.com/openclaw/openclaw/commit/e4c61723cd2d530680cc61789311d464ab8cdf60"
44+
},
45+
{
46+
"type": "PACKAGE",
47+
"url": "https://github.com/openclaw/openclaw"
48+
}
49+
],
50+
"database_specific": {
51+
"cwe_ids": [
52+
"CWE-807",
53+
"CWE-863"
54+
],
55+
"severity": "HIGH",
56+
"github_reviewed": true,
57+
"github_reviewed_at": "2026-03-26T21:46:42Z",
58+
"nvd_published_at": null
59+
}
60+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-7xr2-q9vf-x4r5",
4+
"modified": "2026-03-26T21:49:25Z",
5+
"published": "2026-03-26T21:49:25Z",
6+
"aliases": [],
7+
"summary": "OpenClaw: Symlink Traversal via IDENTITY.md appendFile in agents.create/update (Incomplete Fix for CVE-2026-32013)",
8+
"details": "### Summary\n\nThe patch for CVE-2026-32013 introduced symlink resolution and workspace boundary enforcement for `agents.files.get` and `agents.files.set`. However, two other handlers in the same file (`agents.create` and `agents.update`) still use raw `fs.appendFile` on the `IDENTITY.md` file **without any symlink containment check**. An attacker who can place a symlink in the agent workspace can hijack the `IDENTITY.md` path to append attacker-controlled content to arbitrary files on the system.\n\n### Details\n\nIn `src/gateway/server-methods/agents.ts`, the `agents.create` handler constructs the identity path and appends agent metadata without verifying symlinks:\n\n```typescript\n// agents.create — line 283-291\nconst identityPath = path.join(workspaceDir, DEFAULT_IDENTITY_FILENAME);\nconst lines = [\n \"\",\n `- Name: ${safeName}`,\n ...(emoji ? [`- Emoji: ${sanitizeIdentityLine(emoji)}`] : []),\n ...(avatar ? [`- Avatar: ${sanitizeIdentityLine(avatar)}`] : []),\n \"\",\n];\nawait fs.appendFile(identityPath, lines.join(\"\\n\"), \"utf-8\"); // ← NO SYMLINK CHECK\n```\n\nThe `agents.update` handler has the same issue at line 348-349:\n\n```typescript\n// agents.update — line 348-349\nconst identityPath = path.join(workspace, DEFAULT_IDENTITY_FILENAME);\nawait fs.appendFile(identityPath, `\\n- Avatar: ${sanitizeIdentityLine(avatar)}\\n`, \"utf-8\"); // ← NO SYMLINK CHECK\n```\n\n`fs.appendFile` follows symlinks by default. If the `IDENTITY.md` file in the workspace is a symlink pointing to a sensitive file (e.g., `/etc/crontab`, `~/.bashrc`, or `~/.ssh/authorized_keys`), calling `agents.create` will append the agent identity metadata to that file.\n\nThe `ensureAgentWorkspace` function (called at line 274 before the append) uses exclusive-create mode (`flag: 'wx'`) for `IDENTITY.md`. If a symlink already exists at that path, the `EEXIST` error is silently caught, and the subsequent `fs.appendFile` follows the symlink.\n\n**Attack flow:**\n```\n1. Attacker plants symlink: workspace/IDENTITY.md → /etc/crontab\n2. ensureAgentWorkspace skips creation (EEXIST from symlink)\n3. fs.appendFile follows symlink → writes to /etc/crontab\n4. Attacker-controlled content (name, emoji, avatar) injected into crontab → RCE\n```\n\n### PoC\n\n**Prerequisites:** Docker and Python 3 installed.\n\n**Step 1: Build and start the test environment.**\n```bash\ncd llm-enhance/cve-finding/RCE/CVE-2026-32013-identity-appendFile-variant-exp/\ndocker compose up -d --build\nsleep 3\n```\n\n**Step 2: Run the exploit.**\n```bash\npython3 poc_exploit.py\n```\n\nThis script:\n1. Plants a symlink `IDENTITY.md → /etc/target-file.txt` inside the agent workspace\n2. Calls the `agents.create` API endpoint via HTTP POST\n3. Verifies that the agent identity metadata was appended to `/etc/target-file.txt`\n\n**Step 3: Run the control experiment.**\n```bash\npython3 control-patched_realpath.py\n```\n\n**Step 4: Cleanup.**\n```bash\ndocker compose down\n```\n\n### Log of Evidence\n\n**Exploit output:**\n```\n=== CVE-2026-32013 Variant: Symlink Traversal via IDENTITY.md appendFile ===\n[*] Planting symlink: IDENTITY.md -> /etc/target-file.txt\n[*] Symlink: lrwxrwxrwx 1 root root 20 /workspaces/evil-agent/IDENTITY.md -> /etc/target-file.txt\n[*] Original /etc/target-file.txt: ORIGINAL_SENSITIVE_CONTENT\n\n[*] Calling agents.create with name='evil-agent'...\n[*] API response: {'ok': True, 'agentId': 'evil-agent', 'workspace': '/workspaces/evil-agent'}\n\n[*] /etc/target-file.txt after exploit:\n ORIGINAL_SENSITIVE_CONTENT\n\n- Name: evil-agent\n- Emoji: 💀\n- Avatar: evil.png\n\n[+] SUCCESS! Symlink traversal confirmed.\n[+] fs.appendFile followed IDENTITY.md symlink and wrote to /etc/target-file.txt\n[+] Attacker-controlled content injected into arbitrary file.\n```\n\n**Control output:**\n```\n=== CONTROL: Patched agents.create blocks symlink traversal ===\n[*] Planting symlink: IDENTITY.md -> /etc/target-file.txt\n[*] Original /etc/target-file.txt: ORIGINAL_SENSITIVE_CONTENT\n\n[*] Calling PATCHED agents.create with name='safe-agent'...\n[*] API response: {'ok': False, 'error': 'symlink_traversal_blocked', 'realPath': '/etc/target-file.txt'}\n\n[*] /etc/target-file.txt after patched call: ORIGINAL_SENSITIVE_CONTENT\n\n[+] CONTROL PASSED: Patched endpoint detected and blocked symlink traversal.\n[+] /etc/target-file.txt remains unchanged.\n```\n\n### Impact\n\nAn attacker who can plant a symlink in the agent workspace directory can use the `agents.create` or `agents.update` gateway API to **append attacker-controlled content to arbitrary files** on the system. If the target file is:\n\n- `/etc/crontab` or user crontab → **Remote Code Execution**\n- `~/.bashrc` or `~/.profile` → **Persistent code execution on login**\n- `~/.ssh/authorized_keys` → **Unauthorized SSH access**\n- Application configuration files → **Service disruption**\n\nThe attacker-controlled content includes the agent name (arbitrary string), emoji, and avatar fields, which are only lightly sanitized (whitespace normalization via `sanitizeIdentityLine`).\n\n### Affected products\n- **Ecosystem**: npm\n- **Package name**: openclaw\n- **Affected versions**: <= 2026.2.22\n- **Patched versions**: None\n\n### Occurrences\n\n| Permalink | Description |\n| :--- | :--- |\n| [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291) | `agents.create` handler uses `fs.appendFile` on `IDENTITY.md` without symlink resolution or workspace boundary check. |\n| [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349) | `agents.update` handler uses `fs.appendFile` on `IDENTITY.md` without symlink resolution or workspace boundary check. |\n| [https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274](https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274) | `ensureAgentWorkspace` is called before append, but its exclusive-create (`wx`) flag silently skips existing symlinks (EEXIST). |",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "openclaw"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"last_affected": "2026.2.22"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-7xr2-q9vf-x4r5"
40+
},
41+
{
42+
"type": "ADVISORY",
43+
"url": "https://github.com/advisories/GHSA-fgvx-58p6-gjwc"
44+
},
45+
{
46+
"type": "PACKAGE",
47+
"url": "https://github.com/openclaw/openclaw"
48+
},
49+
{
50+
"type": "WEB",
51+
"url": "https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L274"
52+
},
53+
{
54+
"type": "WEB",
55+
"url": "https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L283-L291"
56+
},
57+
{
58+
"type": "WEB",
59+
"url": "https://github.com/openclaw/openclaw/blob/main/src/gateway/server-methods/agents.ts#L348-L349"
60+
}
61+
],
62+
"database_specific": {
63+
"cwe_ids": [
64+
"CWE-61"
65+
],
66+
"severity": "HIGH",
67+
"github_reviewed": true,
68+
"github_reviewed_at": "2026-03-26T21:49:25Z",
69+
"nvd_published_at": null
70+
}
71+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-cfp9-w5v9-3q4h",
4+
"modified": "2026-03-26T21:48:06Z",
5+
"published": "2026-03-26T21:48:06Z",
6+
"aliases": [],
7+
"summary": "OpenClaw: Image Tool `tools.fs.workspaceOnly` Bypass via Sandbox Bridge Mounts",
8+
"details": "## Summary\nThe `image` tool did not fully honor the `tools.fs.workspaceOnly` filesystem boundary. In affected releases, image-path resolution could still traverse sandbox bridge mounts outside the workspace and read files from mounted directories that the other file tools would reject.\n\n## Affected Packages / Versions\n- Package: `openclaw` (npm)\n- Affected: `< 2026.3.2`\n- Fixed: `>= 2026.3.2`\n- Latest released tags checked: `v2026.3.23` (`ccfeecb6887cd97937e33a71877ad512741e82b2`) and `v2026.3.23-2` (`630f1479c44f78484dfa21bb407cbe6f171dac87`)\n- Latest published npm version checked: `2026.3.23-2`\n\n## Fix Commit(s)\n- `dd9d9c1c609dcb4579f9e57bd7b5c879d0146b53`\n- `14baadda2c456f3cf749f1f97e8678746a34a7f4`\n\n## Release Status\nThe complete fix shipped in `v2026.3.2` and remains present in `v2026.3.23` and `v2026.3.23-2`.\n\n## Code-Level Confirmation\n- `src/agents/openclaw-tools.ts` now passes `fsPolicy` into `createImageTool`, so the image tool receives the same workspace-only policy input as the other filesystem tools.\n- `src/agents/tools/image-tool.ts`, `src/agents/tools/media-tool-shared.ts`, and `src/agents/sandbox-media-paths.ts` now restrict local roots and sandbox-bridge resolution to the workspace when `tools.fs.workspaceOnly` is enabled.\n\nOpenClaw thanks @YLChen-007 for reporting.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "openclaw"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "2026.3.2"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-cfp9-w5v9-3q4h"
40+
},
41+
{
42+
"type": "WEB",
43+
"url": "https://github.com/openclaw/openclaw/commit/14baadda2c456f3cf749f1f97e8678746a34a7f4"
44+
},
45+
{
46+
"type": "WEB",
47+
"url": "https://github.com/openclaw/openclaw/commit/dd9d9c1c609dcb4579f9e57bd7b5c879d0146b53"
48+
},
49+
{
50+
"type": "PACKAGE",
51+
"url": "https://github.com/openclaw/openclaw"
52+
}
53+
],
54+
"database_specific": {
55+
"cwe_ids": [
56+
"CWE-863"
57+
],
58+
"severity": "MODERATE",
59+
"github_reviewed": true,
60+
"github_reviewed_at": "2026-03-26T21:48:06Z",
61+
"nvd_published_at": null
62+
}
63+
}

0 commit comments

Comments
 (0)