GitHub Security Advisory: GHSA-3pw3-v88x-xj24
Package: @paperclipai/shared (NPM)
Severity: MODERATE (CVSS 6.5)
CWE: CWE-73: External Control of File Name or Path
Vulnerable versions: < 2026.416.0
Patched in: 2026.416.0

Summary: Paperclip: Arbitrary File Read via Agent-Controlled adapterConfig.instructionsFilePath

Details:
### Summary
Paperclip contains an arbitrary file read vulnerability that allows an attacker with an Agent API key to read files from the Paperclip server host filesystem.
The vulnerability occurs because agents are allowed to modify their own adapterConfig through the /agents/:id API endpoint.
The configuration field adapterConfig.instructionsFilePath is later read directly by the server runtime using fs.readFile().
Because no validation or path restriction is applied, an attacker can supply an arbitrary filesystem path.
The Paperclip server then attempts to read that path from the host filesystem during agent execution.
This breaks the intended trust boundary between agent runtime configuration and server host filesystem access, allowing a compromised or malicious agent to access sensitive files on the host system.

### Details
#### Root Cause
No path normalization, allowlist, or workspace boundary validation is applied before the filesystem read occurs.
Agent configuration can be modified through the API endpoint:
```
PATCH /api/agents/:id
```
The validation schema allows arbitrary configuration fields inside adapterConfig.
File:
```
packages/shared/src/validators/agent.ts
```
Schema fragment:
```
adapterConfig: z.record(z.unknown())
```
Because of this schema, attackers can inject arbitrary configuration values, including:
```
adapterConfig.instructionsFilePath
```
During agent execution, the server runtime reads this path directly from the host filesystem using fs.readFile().
Relevant code path:
```
packages/adapters/claude-local/src/server/execute.ts
```
Execution flow:
```
adapterConfig.instructionsFilePath
        ↓
execute()
        ↓
fs.readFile(instructionsFilePath)
        ↓
file content loaded into runtime
```
Vulnerable logic:
```
const instructionsContent = await fs.readFile(instructionsFilePath, "utf-8");
```
Because the value originates from attacker-controlled configuration and no validation or sandboxing is applied, this becomes a direct host filesystem read primitive.

#### Affected Files
Primary vulnerable file:
```
packages/adapters/claude-local/src/server/execute.ts
```
Relevant function:
```
execute()
```
Sensitive operation:
```
fs.readFile(instructionsFilePath)
```
Configuration source:
```
PATCH /api/agents/:id
```
Validation logic:
```
packages/shared/src/validators/agent.ts
```

#### Attacker Model
Required privileges
Attacker requires:
```
Agent API key
```
Agent credentials are intended for automation and integration with external runtimes.
These credentials are commonly used by:
```
agent runtime environments
third-party integrations
automation pipelines
```
Agent credentials are not intended to grant direct access to the server host filesystem.
No board or administrator privileges are required.

#### Attacker Chain
Complete exploit chain:
```
Attacker obtains Agent API key
        ↓
PATCH /api/agents/:id
        ↓
Inject adapterConfig.instructionsFilePath
        ↓
POST /api/agents/:id/wakeup
        ↓
Server execu