Why Collaborating Across Different Owners' Agents Is Dangerous
Delegating a coding or research task from your local Claude Code or Codex CLI to an autonomous agent owned by a friend, contractor, or external partner sounds great in theory.
In practice, almost every existing multi-agent framework and wire protocol (including standard MCP or Google A2A setups) assumes a single trust boundary. The moment you connect agents owned by two different people across the internet, you hit three critical security walls:
-
Raw API Key Exfiltration: If a worker process receives
OPENAI_API_KEY,ANTHROPIC_API_KEY, orGITHUB_TOKENin its environment variables, any RCE or process memory disclosure exposes your raw credentials. Last week's PHP2Shell (CVE-2026-109618/CVE-2026-109619) advisories proved how frontier AI models can chain memory bugs to dump secrets straight out of process memory. -
Cross-Session State Bleed & Isolation Spoofing: Earlier this month, AWS Strands Agents (
CVE-2026-115419) suffered an A2A server concurrency flaw where state bled across concurrent requests. Worse, when a remote worker claims it executed your task inside an isolated Docker container, the requester normally has no cryptographic way to verify that claim. - Inbound Ports & NAT Traversal: Opening inbound ports or sharing a VPN mesh with an external party expands your attack surface unnecessarily.
To solve this, I built ACP (Agent Collaboration Platform) — an Apache-2.0 TypeScript reference implementation and zero-trust governance overlay on top of A2A and MCP for cross-owner agent collaboration.
- GitHub Repository: https://github.com/acidnyan/agent-collab-platform
-
Red-Team Security Proofs (
SECURITY_PROOF.md): https://github.com/acidnyan/agent-collab-platform/blob/main/SECURITY_PROOF.md
How ACP Works: 5 Zero-Trust Guarantees
ACP treats both the remote agent and the message relay as untrusted by default.
[Owner A: Requester] [Untrusted Blind Relay] [Owner B: Worker]
Claude Code / Codex ---> ACP Gateway A ===(Ed25519 + RFC 8785 JCS)===> HTTPS/SSE Queue <=== ACP Gateway B
(Outbound Poll Only) |
+------+------+
| |
Credential Proxy Isolated Worker
(Holds raw keys) (acp_cred_... handle only,
shell: false)
1. Zero Raw Keys in Worker Memory (CredentialProxy)
Worker subprocesses and sandboxes never receive raw API keys (OPENAI_API_KEY, ANTHROPIC_API_KEY, GITHUB_TOKEN, etc.). sanitizedEnvironment strips host secrets before spawn.
Instead, the host's local CredentialProxy issues a short-lived, task-scoped capability handle (acp_cred_...) and injects upstream headers only on validated requests. When the task finishes, the handle is immediately revoked. Even a full worker memory dump yields zero bytes of raw secret material.
2. Zero Open Inbound Ports (Outbound-Only Blind Relay)
Neither the requester nor the worker opens an inbound port. Both sides stay behind NAT/firewalls and make outbound HTTPS/SSE calls to a blind relay.
Every inbox poll requires a signed RelayAuth header (Ed25519 over agentDid + timestamp + nonce), preventing cross-session snooping and replay attacks.
3. Ed25519 + RFC 8785 (JCS) Canonical Signatures
Every TaskContract, attenuated CapabilityGrant, and TaskReceipt is canonicalized using RFC 8785 JSON Canonicalization Scheme (JCS) and signed with did:key (Ed25519). Any 1-byte modification to budgets (maxTokens, maxCostUsd, maxDurationSeconds), scopes, or SHA-256 artifact hashes is deterministically rejected.
4. No Shell Interpolation + Cryptographically Verified Isolation
Command workers run strictly via spawn(..., { shell: false }) with inputs passed over stdin and temporary files — eliminating shell metacharacter injection ($(...), backticks, ;).
Furthermore, the worker's signed TaskReceipt binds the actual effectiveIsolationLevel (subprocess, container, etc.). If a contract requires container isolation and a worker attempts to downgrade to subprocess, verification fails automatically.
5. BYOK Cost Isolation
Each owner's agent uses its own local LLM/API keys within the signed budget constraints of the TaskContract.
Don't Trust Claims — Run the Red-Team Security Proof Suite
In 2026, saying "trust me, I designed it securely" is not enough for open-source agent infrastructure.
ACP includes an executable red-team adversarial test suite (conformance/security-proofs.test.ts) that actively attacks the production codebase and proves every attack is blocked in under 5 seconds:
git clone https://github.com/acidnyan/agent-collab-platform.git
cd agent-collab-platform
pnpm install && pnpm build
pnpm test:security-proof
What pnpm test:security-proof Actively Tests
| Proof Category | Simulated Red-Team Attack | Verified Outcome |
|---|---|---|
| Proof 1: Secret Exfiltration | Worker dumps process.env, inspects VM globals, or reuses another task's / expired acp_cred_... handle |
0 bytes of raw secrets exposed; unauthorized handles rejected (401/403) |
| Proof 2: RCE & Shell Injection | Payloads with $(touch /tmp/pwn), ; rm -rf /, ../../etc/passwd, and __proto__ pollution |
shell: false prevents execution; path traversal & schema violations rejected (100%) |
| Proof 3: Cross-Session Bleed | Polling another agent's relay inbox or lying about effectiveIsolationLevel (subprocess vs container) |
Rejected by RelayAuth Ed25519 check and receipt isolation gate (100%) |
| Proof 4: OOM / DoS & SSRF | >1MB relay payloads, queue flooding, nonce replay, and SSRF targets (http://169.254.169.254, 127.0.0.1, file://) |
Oversized payloads/queues rejected (413/429); private IP & non-HTTPS URLs blocked (100%) |
| Proof 5: 1-Byte Tampering | Modifying 1 byte of a signed TaskContract budget, TaskReceipt artifact hash, or RelayAuth timestamp |
Cryptographically rejected via Ed25519 + RFC 8785 JCS (100%) |
Try a 30-Second Live Collaboration Across Two Terminals
A public blind relay is running on Cloudflare Workers + Durable Objects at https://acp-relay.agent-collab.workers.dev (or you can run the offline local relay included in the repo).
Terminal 1 (Worker waiting for tasks)
node cli/acp-cli.mjs demo:worker \
--relay https://acp-relay.agent-collab.workers.dev \
--adapter command \
--command "node -e \"const fs=require('fs');const env=JSON.parse(fs.readFileSync(0,'utf8'));console.log(JSON.stringify({summary:'Processed task safely',output:{taskId:env.taskId}}))\""
This prints a signed acp-invite:... token.
Terminal 2 (Requester delegating a task)
node cli/acp-cli.mjs demo:delegate \
--invite "<paste-acp-invite-token-here>" \
--title "Security architecture review" \
--input '{"target":"relay-auth"}'
The repository also includes AGENTS.md and SKILL.md at the root, so you can point Claude Code, Codex CLI, or Cursor at the repository and ask your agent in natural language to act as a worker or delegate a task using an invite token.
Feedback Welcome
I would love brutal feedback from security engineers and agent builders — especially if you can find a way to bypass any of the checks in conformance/security-proofs.test.ts!
- GitHub: https://github.com/acidnyan/agent-collab-platform
- Threat Model & Proofs: https://github.com/acidnyan/agent-collab-platform/blob/main/SECURITY_PROOF.md
Top comments (0)