Security Digest · Critical advisory (no CVE assigned)
GHSA-3xx2-mqjm-hg9x: Paperclip: Cross-tenant agent API key IDOR in `/agents/:id/keys` routes allows full victim-company compromise
Summary The GET, POST, and DELETE handlers under /agents/:id/keys in the Paperclip control-plane API only call assertBoard(req), which verifies that the caller has a board-type session but does not verify that the caller has access to the company owning the target agent.
CVSS 9.9 Critical GitHub-reviewed · critical
Should you act?
- Only if you depend on one of the packages below, directly or transitively, in a vulnerable version. Check your lockfile with
npm audit (or: npm ls <package>). - No CVE has been assigned, so it will not appear in CVE-based scanners that ignore GitHub advisories.
npm audit,pip-auditand Dependabot do read GitHub advisories.
Affected packages
| Ecosystem | Package | Vulnerable | First fixed |
|---|---|---|---|
| npm | @paperclipai/server | < 2026.416.0 | 2026.416.0 |
Details
Summary
The GET, POST, and DELETE handlers under /agents/:id/keys in the Paperclip control-plane API only call assertBoard(req), which verifies that the caller has a board-type session but does not verify that the caller has access to the company owning the target agent. A board user whose membership is limited to Company A can therefore list, create, or revoke agent API keys for any agent in Company B by supplying the victim agent's UUID in the URL path. The POST handler returns the newly-minted token in cleartext, which authenticates subsequent requests as {type:"agent", companyId: }, giving the attacker full agent-level access inside the victim tenant — a complete cross-tenant compromise.
Details
The three vulnerable routes are defined in server/src/routes/agents.ts:2050-2087:
assertBoard in server/src/routes/authz.ts:4-8 is intentionally narrow:
It does not consult req.actor.companyIds or req.actor.isInstanceAdmin. Company-scoping is handled by a separate helper, assertCompanyAccess(req, companyId) (same file, lines 18-31), which the key-management routes never call.
The service layer is also unauthenticated. In server/src/services/agents.ts:580-629:
Neither the agent id on POST/GET nor the key id on DELETE is cross-checked against the caller's company membership.
CVSS: 9.9 (v3.1) CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Sources and references
- GitHub Advisory GHSA-3xx2-mqjm-hg9x github.com
- github.com github.com