Back to skill

Security audit

Elite Multi-Agent Comms Mesh

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real agent messaging tool, but it needs review because shared credentials expose/allow forged mesh messages and the cron examples can make agents process and answer untrusted messages unattended.

Use this only for a trusted, low-sensitivity agent fleet. Do not send secrets or private project data through the mesh as documented. Avoid enabling the unattended cron reply templates unless the agent runs with low privileges and a strict policy; prefer per-agent authentication, recipient-scoped RLS, sender verification/signatures, message redaction or encryption, and human review before substantive replies.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
references/cron-templates.md:36
Finding

Untrusted Mesh Messages Are Automatically Treated as Agent Tasks

Content
View full analysis

Vulnerability Details

File Location: references/cron-templates.md:36-48, SKILL.md:89-93, and scripts/mesh-poll.sh:51-68
Vulnerability Type: Remote instruction injection through automatically processed mesh messages
Risk Level: Critical

Vulnerable Code

references/cron-templates.md:36-48:

text
openclaw cron add \
  --name "mesh-relay" \
  --every 10m \
  --model anthropic/claude-sonnet-4-5 \
  --task "MESH RELAY:
1. Run: bash {baseDir}/scripts/mesh-poll.sh
2. If no messages, reply NO_REPLY.
3. For each message, compose a substantive reply with data or results.
4. Send: bash {baseDir}/scripts/mesh-send.sh <from_agent> '<reply>'
5. Skip stale follow-up/check-in messages."

scripts/mesh-poll.sh:51-68:

bash
node -e "
const msgs = JSON.parse(process.argv[1] || '[]');
if (!Array.isArray(msgs) || msgs.length === 0) {
  console.log('No new mesh messages.');
  process.exit(0);
}
console.log('Found ' + msgs.length + ' message(s):');
msgs.forEach(m => {
  const thread = m.thread_id ? ' [thread:' + m.thread_id + ']' : '';
  console.log('  From: ' + m.from_agent + ' | Priority: ' + (m.priority || 'normal') + thread);
  console.log('  Message: ' + m.message);
  console.log('  Time: ' + m.created_at + ' | ID: ' + m.id);
  console.log('');
});
// Output last timestamp for next --since call
const last = msgs[msgs.length - 1].created_at;
console.log('LAST_TIMESTAMP=' + last);
" "$MESSAGES"

Technical Analysis

The polling script prints remotely supplied message values directly into the AI agent's task context. The recommended cron and heartbeat configurations then instruct the agent to process each message and produce a substantive response.

No instruction/data boundary is established between the trusted cron task and untrusted message content. There is no sender authentication, per-sender authorization, operation allowlist, confirma ...[truncated 1991 chars]

Remediation
View remediation

Remediation Suggestions

  1. Treat every mesh message as untrusted data and state this explicitly in the heartbeat and cron system task.
  2. Do not automatically execute free-form requests. Require explicit user approval before any message can cause tool use, filesystem access, service access, configuration changes, or disclosure of data.
  3. Replace free-form task messages with a typed schema containing an allowlisted operation identifier and strictly validated parameters.
  4. Add a fixed higher-priority policy stating that mesh messages cannot override system or user instructions and cannot request secrets, credentials, hidden prompts, local files, or arbitrary commands.
  5. Render messages inside clear untrusted-data delimiters and instruct the model to summarize them rather than obey them.
  6. Authenticate senders cryptographically and enforce per-sender authorization before presenting a request to the agent.
  7. Disable automatic replies by default. For unattended operation, allow only low-risk operations implemented in deterministic code rather than delegated to a general-purpose model.
  8. Apply least privilege to the polling agent's tool set and use a separate restricted agent identity for mesh processing.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/supabase-setup.md:28
Finding

Shared Anonymous Credentials Allow Arbitrary Sender Impersonation

Content
View full analysis

Vulnerability Details

File Location: references/supabase-setup.md:28-41 and scripts/mesh-send.sh:94-110
Vulnerability Type: Missing sender authentication and unrestricted row insertion
Risk Level: High

Vulnerable Code

references/supabase-setup.md:28-41:

sql
ALTER TABLE agent_messages ENABLE ROW LEVEL SECURITY;

-- Agents can read messages
CREATE POLICY "agents_select" ON agent_messages
  FOR SELECT USING (true);

-- Agents can insert new messages
CREATE POLICY "agents_insert" ON agent_messages
  FOR INSERT WITH CHECK (true);

-- No UPDATE or DELETE policies — the anon key cannot modify or remove rows.
-- Maintenance (cleanup/archival) is done by the project owner via the
-- Supabase Dashboard SQL Editor using the service_role key.

scripts/mesh-send.sh:94-110:

bash
# Direct message to a single agent
PAYLOAD=$(node -e "
console.log(JSON.stringify({
  from_agent: process.argv[1],
  to_agent: process.argv[2],
  message: process.argv[3],
  priority: process.argv[4],
  metadata: {}
}));
" "$MY_AGENT" "$TO_AGENT" "$MESSAGE" "$PRIORITY" "$THREAD_ID")

HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${SUPABASE_URL}/agent_messages" \
  -H "apikey: ${SUPABASE_KEY}" \
  -H "Authorization: Bearer ${SUPABASE_KEY}" \
  -H "Content-Type: application/json" \
  -H "Prefer: return=minimal" \
  -d "$PAYLOAD")

Technical Analysis

Every agent uses the same Supabase anonymous key. The agents_insert RLS policy uses WITH CHECK (true), permitting the anonymous role to insert any row that satisfies basic table constraints.

The asserted sender identity is taken from the client-controlled MESH_AGENT_ID environment variable and serialized directly into from_agent. The database does not derive this identity from an authenticated principal or verify that the caller is entitled to claim it.

Thus, possession of the shared key is sufficient to cr ...[truncated 1634 chars]

Remediation
View remediation

Remediation Suggestions

  1. Provision a distinct authenticated Supabase identity for each agent rather than sharing one anonymous credential.
  2. Create an immutable agent registry mapping auth.uid() to an agent identifier.
  3. Derive the sender identity on the server. Do not accept a client-controlled from_agent value as authoritative.
  4. Replace WITH CHECK (true) with an RLS condition that requires the row's sender identity to match the authenticated principal.
  5. Restrict which recipients and message types each authenticated agent may use.
  6. Add cryptographic message signatures as defense in depth and verify them before displaying or processing messages.
  7. Record authenticated principal IDs and signature verification status in immutable audit fields.
  8. Rotate the shared anonymous key after migrating to individual identities.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/supabase-setup.md:28
Finding

Unrestricted SELECT Policy Exposes All Inter-Agent Messages

Content
View full analysis

Vulnerability Details

File Location: references/supabase-setup.md:28-37, scripts/mesh-status.sh:38-47, and scripts/mesh-agents.sh:24-27
Vulnerability Type: Missing recipient-level access control for stored messages
Risk Level: High

Vulnerable Code

references/supabase-setup.md:28-37:

sql
ALTER TABLE agent_messages ENABLE ROW LEVEL SECURITY;

-- Agents can read messages
CREATE POLICY "agents_select" ON agent_messages
  FOR SELECT USING (true);

-- Agents can insert new messages
CREATE POLICY "agents_insert" ON agent_messages
  FOR INSERT WITH CHECK (true);

scripts/mesh-status.sh:38-47:

bash
# 2. My recent messages (last 30 minutes)
SINCE=$(node -e "console.log(new Date(Date.now() - 30*60*1000).toISOString())")
MY_RECENT=$(curl -s "${SUPABASE_URL}/agent_messages?to_agent=eq.${MY_AGENT}&created_at=gt.${SINCE}&select=id" \
  -H "apikey: ${SUPABASE_KEY}" \
  -H "Authorization: Bearer ${SUPABASE_KEY}")

# 3. Fleet-wide recent activity (last 20 messages across all agents)
RECENT=$(curl -s "${SUPABASE_URL}/agent_messages?order=created_at.desc&limit=20" \
  -H "apikey: ${SUPABASE_KEY}" \
  -H "Authorization: Bearer ${SUPABASE_KEY}")

Technical Analysis

Although Row Level Security is enabled, the SELECT policy is globally permissive because USING (true) authorizes every query made under the shared anonymous role. It does not restrict rows to those where the authenticated agent is the sender or recipient.

The fleet status implementation confirms that this behavior is intentional: it performs an unfiltered query for complete recent message rows. Since no select projection limits the returned columns, the response includes message bodies and associated metadata, not merely activity timestamps.

Any holder of the anonymous key can likewise query the entire table directly, paginate through historical records, filter for specific agents, or monitor on ...[truncated 1211 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the shared anonymous identity with a distinct authenticated identity for each agent.
  2. Restrict SELECT access to rows where the authenticated agent is the verified sender or recipient.
  3. Implement broadcast visibility through a separate, explicit policy instead of granting global table access.
  4. Move agent discovery and health reporting to a secured view or RPC that returns only minimal roster and activity fields.
  5. Do not retrieve message bodies for fleet-status reporting; explicitly project only required columns.
  6. Consider application-layer encryption for message bodies where the server or unrelated mesh members must not read content.
  7. Define and enforce data-retention limits to reduce the impact of credential compromise.
  8. Rotate the current shared key after deploying corrected authentication and RLS policies.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill explicitly instructs users to run shell scripts that make outbound network requests, but the manifest does not declare any tool scope such as permissions or allowed-tools. That creates an authorization gap: a reviewer or policy engine cannot tell from the metadata that installing or invoking this skill enables shell and network activity, which increases the chance of unintended execution in sensitive environments.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
77% confidence
Finding

L106 explicitly documents mesh-poll.sh as 'read-only, no state mutation'. However, the surrounding workflow in L091-L097 and the messaging model centered on 'unread messages' implies some notion of message-read state, which would require mutation unless unread is derived externally. This creates an intent/documentation inconsistency about whether polling changes server-side state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file instructs users to run mesh-poll.sh and mesh-send.sh, which are shell-execution operations and likely transmit message content between agents, but the surrounding documentation does not disclose execution or messaging/privacy implications. Under SQP-2 for markdown files, descriptions should warn when behavior may affect user data, privacy, or system integrity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The cron template configures unattended recurring execution of shell commands that poll for messages and send replies, but the file does not warn users that this will run automatically every few minutes and may send outbound content without review. For markdown guidance, scheduled actions affecting communications or system behavior should include a clear disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This template instructs an autonomous cron task to compose substantive replies and send them outbound without any guardrails such as approval, recipient validation, content restrictions, or logging requirements. In the context of an agent-to-agent mesh, that increases the risk of prompt-injection-driven actions, data leakage, and uncontrolled autonomous messaging, especially because messages originate from a shared external store and are processed unattended.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/gotchas.md (reported line 9)May include surrounding context.

md
**Symptom:** Agent A sends "checking in..." every 30 min. Agent B wastes tokens replying to each.

**Cause:** Agent A nags without checking if B already replied.

**Fix:** Before sending a follow-up, run `mesh-status.sh` to check for recent outbound messages. If you already sent a message to the same agent recently and haven't received a reply, do not send another. Wait.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

This is a real access-control weakness. The documentation says the anon key is scoped to INSERT and SELECT only, but the shown SELECT policy uses USING (true), which allows any party holding the anon key to read every row in agent_messages, exposing all inter-agent traffic and metadata. In this skill's context, the danger is higher because the table is explicitly used for cross-instance agent communication, so messages may include operational instructions, agent discovery data, debugging details, or other sensitive coordination content.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/mesh-send.sh (reported line 76)May include surrounding context.

sh
}));
" "$MY_AGENT" "$AGENT" "$MESSAGE" "$PRIORITY" "$THREAD_ID")

    HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${SUPABASE_URL}/agent_messages" \
      -H "apikey: ${SUPABASE_KEY}" \
      -H "Authorization: Bearer ${SUPABASE_KEY}" \
      -H "Content-Type: application/json" \

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script fetches fleet-wide recent messages and prints sender, recipient, thread ID prefix, and a preview of message content. For a status/health-check utility, this exceeds the minimum data needed and can expose sensitive inter-agent data to any operator or process allowed to run the script. In this skill context, the mesh is specifically for cross-instance agent communication, so messages may contain prompts, task details, or secrets, making broad read access more dangerous.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The script makes an HTTP request to Supabase to retrieve agent message metadata, which involves transmitting credentials and accessing mesh activity data. While comments describe the purpose for maintainers, there is no runtime notice, confirmation, or user-facing disclosure when the network operation occurs.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The inline documentation says the script is read-only and performs only GET requests, which is technically true, but the broader header frames it as a health check and activity report. In practice, the code also reads and displays excerpts of recent message bodies from all agents, which materially exceeds a typical health-check interpretation and makes the documentation misleading about the script's intent.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.