Back to skill

Security audit

Clawdio

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real P2P messaging library, but its security-sensitive claims are undercut by peer-authentication and key-storage weaknesses users should review before trusting it.

Install only if you are prepared to treat this as review-needed security software: verify peers out of band, avoid autoAccept outside local tests, protect or avoid identityPath files, restrict listener exposure with host/firewall settings, and prefer a version that pins dependencies and fixes connection-string key validation before using it for sensitive agent traffic.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
src/index.ts:186
Finding

Connection-String Peer Identity Is Not Authenticated

Content
View full analysis
{ const { address } = parseConnectionString(connStr); const ws = await this.transport.connect(address); const noise = new NoiseXXHandshake(this.keyPair); const msg1 = noise.writeMessage1(); ``` ```ts // src/protocol.ts:9-13 export function parseConnectionString(connStr: string): { publicKey: string; address: string } { const match = connStr.match(/^clawdio:\/\/([a-f0-9]+)@(.+)$/i); if (!match) throw new Error(`Invalid connection string: ${connStr}`); return { publicKey: match[1], address: match[2] }; } ``` ### Technical Analysis A connection string contains both an advertised static public key and a network address. Although `parseConnectionString()` extracts the public key, `exchangeKeys()` discards it and retains only the address. The Noise XX handshake discovers the remote static key during the handshake, but the discovered key is never compared with the key advertised in the connection string. In addition, outbound connections are automatically accepted and added to the trusted-peer map. Encryption therefore protects the resulting session, but it does not authenticate that the responder is the peer named by the supplied connection string. An attacker able to redirect or intercept the plaintext `ws://` connection can complete the handshake with an attacker-controlled static key. The caller receives the attacker's peer ID and may treat the connection as the intended endpoint. ### Attack Path 1. A victim obtains a legitimate connection string containing the intended peer's public key and address. 2. An attacker gains the ability to redirect or intercept the plaintext WebSocket connection, such as through DNS, routing, proxy, or local-network mani ...[truncated 1181 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/index.ts:351
Finding

Persistent Private Identity Is Stored in Plaintext Without Enforced File Permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/index.ts:323
Finding

Unbounded Pre-Consent Message Queue Enables Remote Memory Exhaustion

Content
View full analysis
pc.ws === ws); if (pendingEntry) { // Queue the message if (wire.nonce && wire.counter) { pendingEntry[1].messageQueue.push({ payload: wire.payload, nonce: wire.nonce, counter: wire.counter }); } return; } ``` ```ts // src/transport.ts:9-16 this.server = new WebSocketServer({ port, host }, () => resolve()); this.server.on('error', reject); this.server.on('connection', (ws) => { ws.on('message', (data) => { this.emit('data', data.toString(), ws); }); }); ``` ### Technical Analysis After an unknown inbound peer completes the cryptographic handshake, the peer enters the pending-consent state. Messages received during this state are appended to `messageQueue` and retained until the user accepts or rejects the peer. There is no limit on queued message count, cumulative encoded size, number of pending peers, or duration of the pending-consent state. The server also does not configure an application-specific WebSocket payload limit or rate limit. Although the WebSocket library may have a general default frame limit, repeated frames within that limit can still accumulate without bound in application memory. The attacker controls the transport keys for its own completed handshake and can therefore generate valid encrypted messages. Decryption is deferred while consent is pending, but the Base64 payload, nonce, and counter strings are retained in memory. ### Attack Path 1. The attacker connects to the listener, which binds to `0.0.0.0` by default. 2. The attacker completes a valid Noise handshake using an attacker-controlled static key. 3. Because the attacker is an unknown inbound peer and `autoAccept ...[truncated 1061 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the implementation uses plain ws:// transport without the claimed cryptographic protections, then the skill's core promise of secure P2P messaging is false. In a security-focused skill, such misleading documentation materially increases danger because operators are encouraged to exchange tasks and data under the assumption of encryption and authenticated peers.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

If the implementation uses plain ws:// transport without the claimed cryptographic protections, then the skill's core promise of secure P2P messaging is false. In a security-focused skill, such misleading documentation materially increases danger because operators are encouraged to exchange tasks and data under the assumption of encryption and authenticated peers.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The server accepts arbitrary WebSocket connections and forwards raw message contents directly to the application without any visible authentication, encryption, consent gating, or verification controls. Because the surrounding skill claims secure, verified P2P communications, this mismatch is dangerous: untrusted peers can connect and inject or observe traffic unless all security guarantees are enforced elsewhere before use.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The client transport connects with plain ws:// rather than a protected channel and shows no evidence of the claimed Noise XX handshake, XChaCha20-Poly1305 encryption, consent, or human verification. In a skill advertised as secure P2P communication, this creates a confidentiality and integrity gap where network attackers or malicious peers can intercept, tamper with, or spoof traffic if higher-layer protections are absent or incomplete.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The Quick Start normalizes autoAccept: true, which weakens the documented consent model by encouraging blind trust of inbound peers. In a peer-to-peer messaging skill—especially one marketed as secure—this increases the likelihood of unauthorized connections, spoofed peers, or accidental exposure during copy-paste adoption of the example.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code persistently writes the node's long-term private identity material, including the secret key, to disk in plaintext JSON with no encryption, permission hardening, or explicit user confirmation. In the context of a secure P2P agent communication library, compromise of this file would let an attacker impersonate the agent, decrypt future traffic where identity is trusted, and bypass the trust model for peers that rely on persisted identity.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency uses a caret range (^12.1.0), which allows future semver-compatible releases to be installed. This weakens build reproducibility and can introduce unintended or compromised upstream changes into the CLI without explicit review, though by itself it is a supply-chain hygiene issue rather than direct evidence of exploitability.

Content

Scanner excerpt · package.json (reported line 21)May include surrounding context.

json
"keywords": ["p2p", "agent", "communication", "encrypted", "websocket"],
  "license": "MIT",
  "dependencies": {
    "commander": "^12.1.0",
    "libsodium-wrappers": "^0.7.15",
    "ws": "^8.18.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The cryptographic dependency libsodium-wrappers is specified with a floating caret range, so consumers may install different versions over time. In a security-sensitive P2P encryption skill, allowing unreviewed upstream changes to a crypto library increases supply-chain risk and makes security properties harder to verify.

Content

Scanner excerpt · package.json (reported line 22)May include surrounding context.

json
"license": "MIT",
  "dependencies": {
    "commander": "^12.1.0",
    "libsodium-wrappers": "^0.7.15",
    "ws": "^8.18.0"
  },
  "devDependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The ws package is unpinned, so installs may resolve to different releases within the allowed range, including versions with security defects if not carefully controlled. Because this package handles network-facing WebSocket communication for a P2P agent system, dependency drift here is more dangerous than usual and can expose the runtime to remotely reachable flaws.

Content

Scanner excerpt · package.json (reported line 23)May include surrounding context.

json
"dependencies": {
    "commander": "^12.1.0",
    "libsodium-wrappers": "^0.7.15",
    "ws": "^8.18.0"
  },
  "devDependencies": {
    "@types/libsodium-wrappers": "^0.7.14",

Unverifiable Dependency: ws has 7 known advisory(ies) (CVE-2016-10518 (Remote Memory Disclosure in ws); CVE-2024-37890 (ws affected by a DoS when handling a request with many HTTP headers); CVE-2026-45736 (ws: Uninitialized memory disclosure) +4 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The manifest does not pin ws, and the package has multiple known advisories, so it is not possible to verify from this file whether the deployed version is patched. In a network-exposed P2P communication skill, that uncertainty materially raises risk because any vulnerable ws release could be reachable by remote peers and exploitable for denial of service or information disclosure.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The @types/libsodium-wrappers package is a development-only dependency with a floating version range, which can affect build reproducibility and trust in the toolchain. However, because it is type metadata rather than runtime code, the direct exploitation impact is comparatively limited.

Content

Scanner excerpt · package.json (reported line 26)May include surrounding context.

json
"ws": "^8.18.0"
  },
  "devDependencies": {
    "@types/libsodium-wrappers": "^0.7.14",
    "@types/ws": "^8.5.13",
    "typescript": "^5.7.0"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The @types/ws package is unpinned, which introduces non-determinism into the development/build environment. While this is less severe than an unpinned runtime dependency, it still weakens supply-chain control and can cause unnoticed changes during builds.

Content

Scanner excerpt · package.json (reported line 27)May include surrounding context.

json
},
  "devDependencies": {
    "@types/libsodium-wrappers": "^0.7.14",
    "@types/ws": "^8.5.13",
    "typescript": "^5.7.0"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

TypeScript is specified with a caret range, so compiler behavior may change across installs. This is primarily a build integrity and reproducibility concern, but compiler/toolchain drift can still affect emitted code and security-relevant checks in subtle ways.

Content

Scanner excerpt · package.json (reported line 28)May include surrounding context.

json
"devDependencies": {
    "@types/libsodium-wrappers": "^0.7.14",
    "@types/ws": "^8.5.13",
    "typescript": "^5.7.0"
  }
}

Static analysis

No suspicious patterns detected.