Back to skill

Security audit

BORT Agent (BAP-578)

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward BORT agent helper that sends user-provided messages to a configured runtime and performs read-only status and blockchain queries.

Before installing, verify the BORT_RUNTIME_URL and BNB_RPC_URL destinations and treat anything sent as a message as leaving your environment. Do not send credentials, wallet secrets, tokens, personal data, or confidential material. The author argument should be considered unsafe with quotes or structured text until it is JSON-escaped properly.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send-message.sh:21
Finding

Unescaped Author Value Permits JSON Payload Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/send-message.sh, lines 21–31
Vulnerability Type: JSON injection caused by unsafe string interpolation
Risk Level: Medium

Vulnerable Code

bash
# Build JSON payload with proper escaping
PAYLOAD=$(cat <<EOF
{
  "content": $(echo "$MESSAGE" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().strip()))'),
  "author": "$AUTHOR",
  "metadata": {
    "source": "openclaw",
    "timestamp": $(date +%s)
  }
}
EOF
)

Technical Analysis

The script safely serializes MESSAGE with Python's json.dumps(), but directly interpolates the attacker-controlled AUTHOR argument into a JSON string. Quotes, backslashes, delimiters, and object members in AUTHOR are therefore interpreted as JSON syntax rather than data.

A crafted author can terminate the intended author string and inject additional properties. Depending on how the BORT runtime parses duplicate keys, an injected later content or metadata property may override the script-generated value. Even when duplicate keys are rejected, an attacker can cause malformed requests and denial of service for this operation.

This is JSON/data injection, not shell command injection: the author is expanded inside a here-document and is not passed to eval or otherwise executed as shell code.

Attack Path

  1. An attacker obtains the ability to control the optional third argument to send-message.sh.

  2. The attacker supplies an author containing a closing quote and additional JSON fields, conceptually similar to:

    text
    attacker", "content": "replacement instruction", "extra": "
    
  3. The script inserts that value directly into the JSON here-document.

  4. The generated payload contains attacker-selected structure or duplicate fields.

  5. curl sends the manipulated payload to:

    text
    $BORT_RUNTIME_URL/agents/$AGENT_ID/messages
    
  6. If the runtime accepts the resulting JSON and resolves duplicate fields in the ...[truncated 687 chars]

Remediation
View remediation

Remediation Suggestions

Construct the entire payload with one JSON serializer rather than interpolating individual values into a here-document. Pass all dynamic values as arguments or environment variables and let the serializer encode them:

bash
TIMESTAMP=$(date +%s)

PAYLOAD=$(python3 - "$MESSAGE" "$AUTHOR" "$TIMESTAMP" <<'PY'
import json
import sys

message, author, timestamp = sys.argv[1:4]

print(json.dumps({
    "content": message,
    "author": author,
    "metadata": {
        "source": "openclaw",
        "timestamp": int(timestamp),
    },
}))
PY
)

Additionally:

  1. Validate AGENT_ID against a strict non-negative integer pattern before inserting it into the URL:

    bash
    [[ "$AGENT_ID" =~ ^[0-9]+$ ]] || {
      echo "Error: agentId must be a non-negative integer" >&2
      exit 1
    }
    
  2. Consider imposing reasonable length limits on MESSAGE and AUTHOR.

  3. Use curl --fail-with-body --show-error and explicit connection and request timeouts.

  4. Add regression tests using author values containing quotes, backslashes, newlines, braces, Unicode, and attempted duplicate properties.

  5. Ensure the receiving API rejects duplicate JSON keys or validates the parsed request against a strict schema.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises blockchain-facing functionality: interacting with BORT AI agents on BNB Chain, sending messages, verifying on-chain identity, and checking agent status via BAP-578. The actual code does none of that. It only performs a simple HTTP GET to a /health endpoint on a configured runtime URL, then prints the response or exits with an error based on the HTTP status code. While one could loosely interpret this as checking the health of a local BORT runtime, that is materially different from interacting with autonomous NFT agents on-chain or verifying their identity/status. Therefore, the code's primary purpose does not match the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description promises broad interaction with BORT agents, especially message sending and AI-soul communication. The code does not implement any messaging, conversational interface, transaction submission, or agent communication pathway. It only queries on-chain state using eth_call/getState(uint256) from a hardcoded BAP-578 contract and formats the result. The on-chain identity/status verification portion is accurately represented, but the primary declared capability is broader than the actual implementation. Therefore this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broader blockchain-oriented skill for interacting with BORT agents on BNB Chain, including identity verification and status checks. The supplied code only implements one narrow function: sending a message to an agent through an HTTP WebAPI connector endpoint. There is no evidence of on-chain operations, BAP-578 protocol handling, identity verification, or status retrieval. While message sending is consistent with part of the description, the actual code materially underdelivers relative to the claimed purpose and relies on a web service rather than direct BNB Chain interaction.

Content

No source excerpt is available for this finding.

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

The skill's core function is transmitting user-supplied content to an external agent runtime, which creates a real exfiltration channel. In this context, 'send messages' is not inherently malicious, but it is dangerous because the skill invites outbound data transfer to autonomous agents and downstream LLM/platform integrations with little safety framing.

Content

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

md
---
name: bort-agent
version: 1.0.0
description: Interact with BORT AI agents on BNB Chain via BAP-578. Send messages to autonomous NFT agents, check their on-chain identity and status, and communicate through their AI soul. Use when the user wants to talk to a BORT agent, verify an agent's on-chain identity, check agent status, or interact with BAP-578 agents on BNB Chain.
---

# BORT Agent Skill (BAP-578)

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/query-agent.sh (reported line 46)May include surrounding context.

sh
exit 1
  fi
else
  # Fallback: raw JSON-RPC call via curl
  RESPONSE=$(curl -s -X POST "$RPC_URL" \
    -H "Content-Type: application/json" \
    -d "{

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documents shell-script execution but declares no explicit tool scope or permissions boundaries. That makes the operational capability broader and less auditable, increasing the chance that an agent invokes shell access unexpectedly or with insufficient user awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill encourages users to send arbitrary messages to an external BORT runtime, and the file states those messages may be processed by configurable third-party LLMs and platform connectors. Without a clear warning, users may disclose secrets, personal data, or proprietary information under the false assumption the interaction stays local or on-chain.

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/query-agent.sh (reported line 46)May include surrounding context.

sh
exit 1
  fi
else
  # Fallback: raw JSON-RPC call via curl
  RESPONSE=$(curl -s -X POST "$RPC_URL" \
    -H "Content-Type: application/json" \
    -d "{

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/send-message.sh (reported line 34)May include surrounding context.

sh
EOF
)

RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
  "$BORT_URL/agents/$AGENT_ID/messages" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" 2>&1)

Static analysis

No suspicious patterns detected.