Back to skill

Security audit

Agent Bus

Security checks for vulnerabilities and agentic risk

Overview

The skill is a Git-based agent messaging tool, but its watcher can automatically act on shared-repo messages and inject replies into an active agent session.

Install only if you are comfortable with a recurring job polling a shared Git repository, changing and pushing message state, notifying configured channels, and forwarding reply bodies into an active agent session. Use a private repository with tightly trusted writers, avoid secrets in messages, and consider disabling the watcher or requiring manual review before any task execution or session delivery.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (5)

T01 · Skill Instruction Hijacking

Error
Location
scripts/watch.sh:76
Finding

Automatic Execution of Untrusted Remote Task Instructions

Content
View full analysis
/dev/null || true ## Step 2: Find unread message files Run this bash snippet to find actionable messages (unread OR missing status field): python3 -c " import os, glob inbox = 'inbox/\${MY_AGENT_ID}/' results = [] for f in glob.glob(inbox + '*.md'): if '.gitkeep' in f: continue txt = open(f).read() lines = txt.split(' ') status = '' for l in lines: if l.startswith('status:'): status = l.split(':',1)[1].strip() break if status in ('unread', ''): results.append(f) for r in results: print(r) " 2>/dev/null ... **If type=task or type=notify:** - Execute the task described in the message body (search / organize / analyze / answer etc.) - Produce a result summary - Send a reply to the sender: export AGENT_BUS_REPO=${REPO} cd ${REPO} bash agent-bus.sh send reply "" ``` ### Technical Analysis The watcher creates an LLM prompt that treats files pulled from a shared Git repository as executable agent instructions. For messages marked as `task` or `notify`, it explicitly directs the local agent to execute the message body. This path does not invoke the security controls implemented by `agent-bus.sh read`, including: - Independent pairing validation through `check_pair` - Prompt-injection detection through `scan_injection` - Sensitive-content filtering - Risk classification through `assess_risk` - Owner-approval handling for yellow or red tasks The watcher instead trusts attacker-controlled metadata such as `type`, `from`, and `status`. A forged message does not need to pass t ...[truncated 1839 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
scripts/watch.sh:153
Finding

Injection of Untrusted Remote Replies into the Main Agent Session

Content
View full analysis
Please process this reply and decide next steps." ``` ### Technical Analysis The watcher enumerates internal OpenClaw session records, heuristically selects an active main session, and injects the complete body of a remotely supplied reply into that session. The remote message is not authenticated or validated through `check_pair`, `scan_injection`, or `assess_risk` before injection. The `type: reply` field is itself part of the attacker-controlled repository file. Consequently, an attacker can label an arbitrary prompt-injection payload as a reply and cause it to enter a more privileged, long-lived session. The instruction not to execute the reply “as a new task” does not create a reliable security boundary. The main model is still asked to process the full attacker-controlled text and decide subsequent ...[truncated 1448 chars]
Remediation
View remediation

T06 · System Persistence

Error
Location
scripts/setup-watch-cron.sh:21
Finding

Recurring Scheduled Watcher Creates Persistent Unattended Execution

Content
View full analysis
/dev/null | python3 -c " import sys,json data=json.loads(sys.stdin.read()) jobs=data if isinstance(data,list) else data.get('jobs',[]) for j in jobs: if j.get('name')=='agent-bus-watch': print(j['id']) " 2>/dev/null || true) for ID in $EXISTING; do openclaw cron rm "$ID" && echo "[setup] removed old cron: $ID" done # Register new watch cron openclaw cron add \ --name "agent-bus-watch" \ --every 3m \ --session isolated \ --message "bash $WATCH_SCRIPT" \ --announce \ && echo "[setup] ✅ agent-bus-watch cron registered (every 3m)" \ || { echo "[ERROR] Failed to register cron"; exit 1; } ``` ### Technical Analysis The setup script installs a recurring OpenClaw cron job that survives the initial Skill execution and invokes `watch.sh` every three minutes. Scheduled polling is related to the declared functionality and is disclosed in the documentation, but its privilege level is excessive because the invoked watcher can process and execute remotely controlled task instructions. The persistence therefore converts a repository compromise at any future time into an unattended local agent activation. It also removes the need for the user to invoke the Skill again. ### Attack Path 1. The user follows the recommended setup and runs `setup-watch-cron.sh`. 2. A persistent `agent-bus-watch` job is registered. 3. At a later time, an attacker gains repository write access or compromises another bus participant. 4. The attacker commits a malicious unread task or reply. 5. Within approximately three minutes, the persistent job runs `watch.sh`. 6. The watcher pulls and processes the malicious content without a new user action. ### Impact Assessment The cron job creates a co ...[truncated 447 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/watch.sh:50
Finding

Destructive Hard Reset on Remote Synchronization Failure

Content
View full analysis
&1 \ || (git -C "$REPO" fetch origin main -q && git -C "$REPO" reset --hard origin/main -q) 2>&1 echo "[agent-bus-watch] pulled latest commits" ``` ### Technical Analysis Any failure of `git pull` triggers `git reset --hard origin/main`. A pull can fail for many benign or security-relevant reasons, including local tracked changes, divergent history, merge conflicts, or malicious force-pushes. The fallback unconditionally makes the remote branch authoritative and discards local tracked modifications. If scripts are copied into or run from the shared repository, a compromised remote can also replace tracked scripts and other operational files. The script prints that the repository was pulled successfully without verifying the final command result, which can further hide synchronization failures. ### Attack Path 1. The victim has local tracked changes in the Agent Bus repository. 2. An attacker with remote write privileges rewrites or diverges the remote branch, or otherwise creates a pull conflict. 3. The scheduled watcher executes `git pull`, which fails. 4. The fallback fetches the remote branch and runs `git reset --hard origin/main`. 5. Local tracked changes are deleted, and the working tree is replaced by the remote state. 6. If operational scripts are tracked in the repository, attacker-modified versions may be adopted for later execution. ### Impact Assessment The direct impact is loss of local tracked data and repository integrity. Depending on repository layout, the remote party may also replace scripts, configuration, message files, or protocol data that later scheduled executions trust. The command is limited to the configured repository working tr ...[truncated 85 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/poll.sh:40
Finding

Agent Message Content Persists in Temporary Files

Content
View full analysis
&1) echo "[agent-bus-poll] read: $READ_OUT" NOTIFY_FILE=$(mktemp /tmp/agent-bus-notify.XXXXXX.txt) echo "$READ_OUT" > "$NOTIFY_FILE" openclaw cron add \ --name "agent-bus-notify" \ --at "1m" \ --session isolated \ --message "【重要执行约束】严禁 sessions_spawn,所有步骤在本 session 内顺序完成。读取文件 $NOTIFY_FILE 的内容,用 message 工具发送(channel: ${OWNER_NOTIFY_CHANNEL}, to: ${OWNER_NOTIFY_TARGET})把内容原文发出去。" \ --announce \ --channel "${OWNER_NOTIFY_CHANNEL}" \ --to "${OWNER_NOTIFY_TARGET}" > /dev/null 2>&1 || true echo "[agent-bus-poll] notify cron created." fi ``` ### Technical Analysis The polling script writes the full output of `agent-bus.sh read` to a temporary file under `/tmp`. No cleanup command or exit trap removes the file after the one-shot notification job reads it. Although `mktemp` generally creates the file with restrictive permissions, message data remains on disk indefinitely. The content may include task bodies, replies, sender identifiers, risk warnings, or operational details. The path is also passed to a later asynchronous job, making safe cleanup dependent on coordinating job completion. ### Attack Path 1. The poller receives an unread message. 2. `agent-bus.sh read` emits the message content and metadata. 3. The output is written to `/tmp/agent-bus-notify.*.txt`. 4. A one-shot cron job is scheduled to read the file. 5. The script exits without removing the file. 6. The data remains available to the same local account, privileged local processes, backups, diagnostics, or later compromise. ### Impact Assessment The issue can disclose bus message contents and metadata to local actors with sufficient filesystem access. It does not independently provide remote code ex ...[truncated 175 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (30)

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'shell' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/agent-bus.sh (reported line 47)May include surrounding context.

sh
"reveal.{0,30}(password|secret|token|cookie|key)"
  "\[INST\]|\[SYS\]|\[SYSTEM\]"
  "<script|<iframe|javascript:"
  "sudo |rm -rf|curl .* \| bash|wget .* \| sh"
)

HIGH_RISK_KEYWORDS=(

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/agent-bus.sh (reported line 47)May include surrounding context.

sh
"reveal.{0,30}(password|secret|token|cookie|key)"
  "\[INST\]|\[SYS\]|\[SYSTEM\]"
  "<script|<iframe|javascript:"
  "sudo |rm -rf|curl .* \| bash|wget .* \| sh"
)

HIGH_RISK_KEYWORDS=(

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script is presented as a lightweight commit watcher, but the generated cron prompt authorizes the LLM to read message files, execute arbitrary task content from those messages, modify the repository, commit/push changes, and notify external parties. That turns untrusted repo content into agent-driving instructions, creating a prompt-injection and arbitrary-action pathway far beyond simple change detection.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The prompt instructs the agent to inspect local session files, select the owner's active main session, and inject message content into it with --deliver. This creates a cross-session trust boundary break: untrusted bus messages can influence or wake a privileged owner session without explicit consent, enabling escalation, spoofed coordination, or prompt-injection propagation.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The prompt explicitly forwards full inbound reply bodies into another session and also emits owner notifications about them. That creates a direct natural-language data exfiltration channel from bus messages to other contexts, potentially leaking secrets, sensitive research, credentials, or embedded prompt-injection payloads across trust boundaries.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The description includes broad invocation examples and trigger phrases such as "message another agent," "delegate tasks between agents," and "send task to agent." In a markdown skill description, these phrases are generic enough to match ordinary user requests, and the file does not provide exclusion conditions or negative examples to narrow when the skill should activate.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 66)May include surrounding context.


Step 1A: Create a new Bus

bash
# Clone your empty GitHub repo

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

One section says owners are the final authority and high-risk actions require approval, while another says agents should execute received tasks automatically before replying. In a multi-agent bus, this ambiguity weakens operator expectations and can lead to autonomous execution of attacker-supplied tasks received through the shared repository.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 298)May include surrounding context.

md
---

### Path A: Create a New Agent Bus (detailed)

### Prerequisites
- An empty GitHub repository

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The document claims built-in prompt-injection rejection and sensitive-content filtering in multiple places, but later describes those controls as optional enhancements users must add themselves. In a cross-agent messaging skill, this mismatch can cause operators to trust nonexistent safeguards and allow hostile agent messages to be processed with less scrutiny.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The changelog explicitly states that all Chinese comments, user-facing strings, and content were translated to English for broader accessibility, indicating an enforced language choice rather than a user-selectable option. There is no corresponding statement that users may choose another language or locale, so this is a natural-language locale policy issue.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/agent-bus.sh (reported line 47)May include surrounding context.

sh
"reveal.{0,30}(password|secret|token|cookie|key)"
  "\[INST\]|\[SYS\]|\[SYSTEM\]"
  "<script|<iframe|javascript:"
  "sudo |rm -rf|curl .* \| bash|wget .* \| sh"
)

HIGH_RISK_KEYWORDS=(

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The inline usage documentation says RED is 'auto-reject', but the read-path handles red-risk tasks by adding them to pendingTasks, changing status to 'pending', and prompting the owner to approve or reject them. This is an active contradiction about the skill's safety behavior and operator expectations.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% 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 · scripts/agent-bus.sh (reported line 1707)May include surrounding context.

sh
Risk levels:
  RED    (auto-reject)    High-risk keywords / high-frequency anomaly / no pair relationship
  YELLOW (pending owner)  First-time sender / long-inactive / bulk ops / external URLs / side-effects
  GREEN  (auto-execute)   None of the above triggered

Pair modes:
  bidirectional   Both A and B can send tasks to each other (and reply)

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Non-task messages are accepted as long as a pair exists in agents.json, without checking whether the pair has been revoked. After revocation, a former peer may still be able to send reply/sync/notify messages, undermining the intended trust boundary and allowing continued influence or social-engineering traffic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Unread messages are automatically marked as read via agent-bus.sh read with auto-ack behavior as soon as the poller detects them, without confirmation or review. This can suppress visibility of malicious, unexpected, or high-risk messages and breaks an approval boundary by changing message state before a user has inspected the content.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script takes message content derived from the shared repo, writes it to a temp file, and then schedules an external openclaw cron task to forward that content to another target outside the Git-based bus. That creates an additional data-flow and execution surface not inherent to simple repo polling, and it can be abused for unintended exfiltration or cross-channel propagation if bus messages contain sensitive or attacker-influenced content.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The header describes the script as commit detection and notification, but the actual prompt drives task execution, repository mutation, outbound communication, and session orchestration. This misleading framing increases operator risk because users may grant or schedule the script under a false assumption about its scope and privileges.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

On pull failure, the script falls back to fetch plus reset --hard origin/main, which can discard local changes silently. In an automated watcher, this can destroy local state or overwrite forensic evidence without warning, especially if the repo contains locally generated or pending data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The message-processing instructions tell the agent to mark files read, commit, push, send replies, and deliver into sessions, all based on message content and without a clear interactive approval step. This allows untrusted bus content to trigger state-changing operations and external communications automatically, increasing the blast radius of any malicious or malformed message.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

For task and notify messages, the prompt tells the agent to send task-derived summaries and confirmations to the owner. Even if shorter than the full body, these summaries can still expose private message content, proprietary data, or sensitive operational details to external notification channels.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The changelog states the reply-routing mechanism was fixed to use a different CLI, but the live example still instructs use of openclaw sessions send. Operationally inconsistent security guidance is risky because users may implement the wrong message-injection path, breaking reply handling or bypassing intended isolation/approval flow.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.