Back to skill

Security audit

Fleet Communication System

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real fleet message bus, but it exposes unauthenticated network messaging and a writable dashboard in ways users should review carefully before installing.

Only use this skill on a tightly trusted network, preferably localhost or behind a VPN/firewall, and do not send secrets or sensitive task results through it. Treat incoming fleet messages as untrusted until authentication, authorization, escaping, size limits, and retention controls are added.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
fleet_bus.js:133
Finding

Unauthenticated Fleet Access, Message Disclosure, and Node Identity Spoofing

Content
View full analysis
{ if (e) return send(res, 400, { error: e.message }); regNode(data.nodeId, { ip: req.socket.remoteAddress, ...data }); send(res, 200, { ok:true, nodes: Object.keys(knownNodes) }); }); } if (m === 'POST' && p === '/send') { return getBody(req, (e, msg) => { if (e) return send(res, 400, { error: e.message }); if (!msg.from || !msg.to || !msg.msg) return send(res, 400, { error:'need from,to,msg' }); regNode(msg.from, { lastAction:'send' }); send(res, 200, { ok:true, entry: appendMsg(msg) }); }); } if (m === 'POST' && p === '/broadcast') { return getBody(req, (e, msg) => { if (e) return send(res, 400, { error: e.message }); msg.to = 'all'; if (!msg.from || !msg.msg) return send(res, 400, { error:'need from,msg' }); regNode(msg.from, { lastAction:'broadcast' }); send(res, 200, { ok:true, entry: appendMsg(msg) }); }); } send(res, 404, { error:'not found' }); }); server.listen(PORT, '0.0.0.0', () => console.log('🚌 Fleet Bus v1.1 on :' + PORT)); ``` ### Technical Analysis The message bus listens on every available net ...[truncated 2810 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
fleet_bus.js:94
Finding

Stored Cross-Site Scripting in the Fleet Dashboard

Content
View full analysis
''+k+' ('+( v.role||'agent')+')').join(' '); const msgs=await(await fetch(BASE+'/messages?node=all&since=0')).json(); const all=await(await fetch(BASE+'/status')).json(); // get all messages via a trick - fetch for each node const r=await fetch(BASE+'/all'); let allMsgs=[]; try{allMsgs=await r.json();}catch{} const el=document.getElementById('msgs'); el.innerHTML=allMsgs.map(m=>{ const t=new Date(m.ts).toLocaleTimeString(); const cls=m.to==='all'?'msg broadcast':'msg'; return '
'+t+' '+m.from+' → '+m.to+': '+m.msg+'
'; }).join(''); el.scrollTop=el.scrollHeight; } ``` ### Technical Analysis The dashboard constructs HTML strings containing untrusted values and assigns those strings to `innerHTML`. The affected data includes: - Registered node IDs. - Registered node roles. - Message sender identities. - Message recipients. - Message bodies. These fields are controllable through the unauthenticated `/register`, `/send`, and `/broadcast` endpoints. Messages and node registrations are persisted before being displayed, making the vulnerability stored rather than merely reflected. No HTML escaping, sanitization, field validation, or restrictive Content Security Policy is present. An attacker can therefore store markup containing an event handler or another browser-executable HTML construct. The payload executes ...[truncated 1750 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
fleet_bus.js:23
Finding

Unbounded Request Buffering and Persistent Message Storage Enable Denial of Service

Content
View full analysis
{ try { return JSON.parse(l); } catch { return null; } }) .filter(m => m && (m.to === node || m.to === 'all') && m.ts > since); } function getBody(req, cb) { let d = ''; req.on('data', c => d += c); req.on('end', () => { try { cb(null, JSON.parse(d)); } catch (e) { cb(e); } }); } ``` Related full-log processing also occurs in the status handler: ```js if (m === 'GET' && p === '/status') { const total = fs.existsSync(MSG_FILE) ? fs.readFileSync(MSG_FILE,'utf8').trim().split('\n').filter(Boolean).length : 0; return send(res, 200, { status:'ok', port:PORT, total, nodes:Object.keys(knownNodes), uptime: process.uptime()|0 }); } ``` ### Technical Analysis `getBody` concatenates incoming request chunks into a string without enforcing a maximum body size. A single client can therefore cause the process to allocate memory proportional to the submitted request. Accepted messages are synchronously appended to an indefinitely growing JSON Lines file. Message count, message length, sender length, and recipient length are not limited. There is no rate limiting, storage quota, retention policy, or log rotation. Message retrieval and status handling use synchronous filesystem calls and load the complete message file into memory. They then split and parse the full contents while blocking the Node.js event loop. As the log grows, ordinary reads become increasingly expensive. This combines net ...[truncated 1516 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · fleet_cli.js (reported line 84)May include surrounding context.

js
status              - Bus status
  nodes               - List known nodes
  register [role]     - Register this node
  send <to> <msg>     - Send message to node
  broadcast <msg>     - Broadcast to all
  read [since_ts]     - Read messages for this node
  task <to> <desc>    - Send task to node

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly describes a lightweight HTTP message bus and even defers encrypted messaging to a future 'Pro' feature, but it does not warn users that messages may be transmitted in cleartext or exposed to interception if used beyond strict localhost or a trusted private network. In a multi-machine fleet context, operators may send tasking or results that contain sensitive data, so the omission can lead to unsafe deployment assumptions and confidentiality risks.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The top-level documentation says this is a "simplified HTTP relay," which implies a transport/relay service. In addition to relaying traffic, the code serves a full dashboard UI and lets any visitor compose and submit messages through browser actions via /send and /broadcast, which is a broader interactive control surface than the stated comment suggests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The embedded dashboard presents core status, node, message, input, and send controls entirely in Chinese string literals. This imposes a specific language on all users without offering a language choice or documenting a justified regional constraint, which matches the natural-language locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The read command prints 无新消息 when there are no messages, which imposes a specific language in user-facing output. There is no indication elsewhere in the file that the user can choose the locale or that this tool is intentionally restricted to Chinese-speaking users.

Content

No source excerpt is available for this finding.