Back to skill

Security audit

AgentYard

Security checks for vulnerabilities and agentic risk

Overview

This skill matches a marketplace concept, but its wallet and payment behavior is misleading and brittle enough that users should review it before installing.

Review this as a financial and privacy-sensitive skill. Do not fund displayed addresses or rely on the sats balances as real Lightning funds until the wallet implementation, transaction handling, backend confirmation flow, and privacy disclosures are fixed. Avoid sending sensitive task details or regulated data through the marketplace or email paths.

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

T09 · Insecure Skill Coding Practices

Error
Location
lib/api.sh:7
Finding
API URL validation allows non-local plaintext endpoints<![CDATA[ ## Vulnerability Details **File Location**: `lib/api.sh`, lines 7–21 **Vulnerability Type**: Insufficient URL validation and plaintext transmission **Risk Level**: High ### Vulnerable Code ```bash # Validate API URL — must be https:// (or http://localhost for dev) if [[ "$AGENTYARD_API" != https://* && "$AGENTYARD_API" != http://localhost* ]]; then echo " Error: AGENTYARD_API must use https:// (got: $AGENTYARD_API)" >&2 return 1 2>/dev/null || exit 1 fi # On Windows (Schannel), SSL revocation checks can fail. CURL_SSL_FLAGS="" if curl --version 2>/dev/null | grep -qi schannel; then CURL_SSL_FLAGS="--ssl-no-revoke" fi # Wrapper for curl with security hardening _curl() { curl --proto "=https,http" $CURL_SSL_FLAGS "$@" } ``` ### Technical Analysis The URL check uses shell prefix matching rather than parsing the URL and verifying its hostname. Consequently, any URL beginning with `http://localhost` passes validation, including URLs such as: ```text http://localhost.attacker.example http://localhost-example.com ``` These hosts are not local loopback endpoints. The `_curl` wrapper also explicitly permits HTTP, so requests to such endpoints are transmitted without TLS. The affected API operations can transmit published agent metadata, wallet addresses, public keys, task descriptions, prices, seller identifiers, and the buyer's delivery email address. No authentication is required before the configured endpoint receives these values. ### Attack Path 1. An attacker influences the environment in which the Skill runs and sets: ```bash export AGENTYARD_API="http://localhost.attacker.example" ``` 2. The value passes the `http://localhost*` prefix check. 3. The user invokes `publish.sh`, `hire.sh`, or `search.sh`. 4. `_curl` permits the plaintext HTTP connection. 5. Marketplace metadata, task details, or delivery email addresses are sent to the attacker-controlled endpoint. 6. A network-positioned attacker could also observe or alter pla ...[truncated 540 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the URL with a dedicated URL parser rather than shell prefix matching. 2. Permit HTTP only when the parsed hostname exactly equals `localhost`, `127.0.0.1`, or `[::1]`. 3. Reject hostnames such as `localhost.example.com`, embedded credentials, fragments, and malformed authorities. 4. Require HTTPS for every non-loopback endpoint. 5. Use separate curl wrappers for production and explicit local development: ```bash curl --proto '=https' --proto-redir '=https' ... ``` 6. If loopback HTTP support is required, enable it only through an explicit development-mode flag and prohibit redirects to non-loopback hosts. 7. Validate redirect destinations or disable redirects entirely. 8. Document all information transmitted to the marketplace and obtain appropriate user consent before sending task or email data. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
send.sh:63
Finding
Non-atomic send rollback can create or duplicate wallet balances<![CDATA[ ## Vulnerability Details **File Location**: `send.sh`, lines 63–101 **Vulnerability Type**: Improper transaction rollback and race condition **Risk Level**: High ### Vulnerable Code ```bash # Check balance sender_balance=$(get_wallet_balance "$sender_wallet") if [[ $sender_balance -lt $amount ]]; then echo " Insufficient balance." echo " Available: $sender_balance sats" echo " Requested: $amount sats" echo "" exit 1 fi echo " From: $sender" echo " To: $receiver" echo " Amount: $amount sats" echo "" echo " Processing..." # Debit sender — set rollback trap for unexpected exit _rollback_send() { update_wallet_balance "$sender_wallet" "$amount" 2>/dev/null echo " Payment interrupted. Balance restored." >&2 } trap _rollback_send EXIT update_wallet_balance "$sender_wallet" "-$amount" # Credit receiver if ! update_wallet_balance "$receiver_wallet" "$amount"; then echo " Payment failed. Balance restored." echo "" exit 1 fi # Payment complete — clear rollback trap trap - EXIT ``` ### Technical Analysis The balance check and debit are separate operations. Although `update_wallet_balance` locks an individual wallet during an update, the complete transfer does not lock both wallets or execute as one atomic transaction. The EXIT trap unconditionally credits the sender. It does not track whether the sender debit actually succeeded. Under `set -e`, a failed debit exits the script and invokes the trap, potentially adding funds even though no funds were removed. There is also an interruption window after the receiver is credited and before `trap - EXIT` executes. If the process terminates during that window, the sender is refunded while the receiver retains the credit. ### Attack Path **Balance creation through a failed debit:** 1. Start two concurrent operations against the same sender wallet. 2. Both operations read a sufficient balance before either debit completes. 3. The first operation reduces the balance. 4. T ...[truncated 900 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Record explicit transaction state, such as `debit_completed` and `credit_completed`. 2. Refund the sender only when the debit is known to have succeeded. 3. If the receiver was credited, reverse that credit before refunding the sender. 4. Acquire locks for both wallets in a deterministic path order and retain them for the entire read-check-debit-credit operation. 5. Prefer a single transactional ledger rather than independently rewriting two JSON files. 6. Use a durable journal with pending, committed, and rolled-back states to support crash recovery. 7. Validate the sender balance again while holding the transaction locks. 8. Add concurrency and forced-termination tests covering every point between debit, credit, and commit. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
hire.sh:81
Finding
Hiring rollback can duplicate credits and corrupt buyer balances<![CDATA[ ## Vulnerability Details **File Location**: `hire.sh`, lines 81–112 **Vulnerability Type**: Improper transaction rollback and non-atomic payment update **Risk Level**: High ### Vulnerable Code ```bash # Check balance if [[ $buyer_balance -lt $seller_price ]]; then echo " Insufficient balance." echo " You need $seller_price sats but have $buyer_balance sats." echo " Fund your wallet and try again." echo "" exit 1 fi echo " Processing payment..." # Debit buyer — set trap for rollback on unexpected exit _rollback_debit() { update_wallet_balance "$WALLET_FILE" "$seller_price" 2>/dev/null echo " Payment interrupted. Balance restored." >&2 } trap _rollback_debit EXIT update_wallet_balance "$WALLET_FILE" "-$seller_price" # Credit seller (local wallet if available) seller_wallet="agents/${seller_agent}/agentyard.key" if [[ -f "$seller_wallet" ]]; then if ! update_wallet_balance "$seller_wallet" "$seller_price"; then # Rollback handled by trap echo " Payment failed. Balance restored." exit 1 fi fi # Payment complete — clear rollback trap trap - EXIT ``` ### Technical Analysis The buyer debit and local seller credit are separately locked file updates, not one atomic transaction. The EXIT trap always adds the price back to the buyer and does not verify that the debit succeeded. If a concurrent operation invalidates the previously checked balance, a failed debit can still trigger a buyer credit. If the process terminates after the seller credit but before the trap is removed, the buyer is refunded without reversing the seller's credit. ### Attack Path 1. Launch multiple hiring or transfer operations against the same buyer wallet. 2. Allow each operation to pass the initial balance check. 3. Cause one operation's debit to fail after another operation changes the balance. 4. The failed operation exits under `set -e`. 5. Its unconditional EXIT trap adds the seller price to the buyer wallet. Alternatively: 1. Begin a h ...[truncated 627 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Track whether the buyer debit completed before allowing rollback to add funds. 2. Track whether the seller credit completed and reverse it during rollback. 3. Lock buyer and seller wallets together in a stable order for the full transaction. 4. Recheck the available balance only after the required locks are acquired. 5. Store transaction identifiers and durable pending/committed states. 6. Make rollback idempotent so repeated cleanup cannot add funds more than once. 7. Handle termination signals explicitly and recover incomplete transactions from a journal on the next run. 8. Add automated race-condition and process-interruption tests. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
hire.sh:99
Finding
Hire operation reports success after backend job creation failure<![CDATA[ ## Vulnerability Details **File Location**: `hire.sh`, lines 99–123 **Vulnerability Type**: Fail-open backend handling and inconsistent financial state **Risk Level**: High ### Vulnerable Code ```bash update_wallet_balance "$WALLET_FILE" "-$seller_price" # Credit seller (local wallet if available) seller_wallet="agents/${seller_agent}/agentyard.key" if [[ -f "$seller_wallet" ]]; then if ! update_wallet_balance "$seller_wallet" "$seller_price"; then # Rollback handled by trap echo " Payment failed. Balance restored." exit 1 fi fi # Payment complete — clear rollback trap trap - EXIT # Try to create hire via backend if [[ -n "$seller_id" ]]; then create_hire "$seller_id" "$task_description" "$seller_price" "$buyer_email" > /dev/null 2>&1 || true fi echo " Payment sent." echo "" # Send notification send_hire_notification "$buyer_email" "$seller_name" "$task_description" "$seller_price" ``` ### Technical Analysis The buyer's local balance is debited and the rollback trap is disabled before the backend is asked to create the job. The result of `create_hire` is redirected, discarded, and explicitly ignored with `|| true`. Therefore, an HTTP error, timeout, malformed response, or backend rejection does not restore the buyer's balance and does not prevent the script from reporting that the hire and payment succeeded. For a remote seller without a local `agents/<name>/agentyard.key` file, the code may debit the buyer without locally crediting any recipient. The backend job request may then fail silently, leaving no accepted job corresponding to the deduction. ### Attack Path 1. The user selects a marketplace seller and invokes `hire.sh`. 2. The local balance check succeeds. 3. The buyer's JSON balance is reduced. 4. The seller has no local wallet, or only the local ledger is updated. 5. The backend `/jobs` request times out or returns an error. 6. `|| true` suppresses the failure. 7. The command prints `Payment sent` and describe ...[truncated 554 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create and validate the backend job before finalizing payment. 2. Do not suppress `create_hire` failures; return a nonzero status and display the server error safely. 3. Introduce a pending transaction state: - Reserve the required balance. - Create the backend job. - Receive a confirmed job identifier. - Commit payment. - Roll back the reservation if any stage fails. 4. Require an idempotency key for backend job creation and payment commit. 5. Confirm both the recipient and payment destination before deducting funds. 6. Never print a completion message until job acceptance and payment state are both confirmed. 7. Provide reconciliation logic for uncertain network outcomes rather than treating them as success. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
lib/wallet.sh:7
Finding
Wallet generation discards the private key and creates nonfunctional fallback addresses<![CDATA[ ## Vulnerability Details **File Location**: `lib/wallet.sh`, lines 7–67 **Vulnerability Type**: Invalid cryptographic key lifecycle and misleading wallet implementation **Risk Level**: High ### Vulnerable Code ```bash # ── Generate Ed25519 keypair ── # Returns the public key. Private key is written to wallet file. generate_keypair() { if command -v openssl &> /dev/null; then # Generate Ed25519 private key, extract public key local privkey=$(openssl genpkey -algorithm Ed25519 2>/dev/null | openssl pkey -outform DER 2>/dev/null | xxd -p | tr -d '\n') local pubkey=$(echo "$privkey" | xxd -r -p | openssl pkey -inform DER -pubout -outform DER 2>/dev/null | xxd -p | tr -d '\n') if [[ -n "$pubkey" ]]; then echo "$pubkey" return 0 fi fi # Fallback: generate random hex keypair local pubkey=$(head -c 32 /dev/urandom | xxd -p | tr -d '\n') echo "$pubkey" } # ── Generate Lightning address ── generate_lightning_address() { if command -v lncli &> /dev/null; then local addr=$(lncli newaddress p2wkh 2>/dev/null | jq -r '.address' 2>/dev/null) if [[ -n "$addr" ]]; then echo "$addr" return 0 fi fi # Generate local Lightning address (stub for offline/dev mode) local random_suffix=$(head -c 16 /dev/urandom | xxd -p | tr -d '\n') echo "lnbc_${random_suffix}" } # ── Create wallet file ── # Usage: create_wallet_file <wallet_path> # Returns: lightning address create_wallet_file() { local wallet_path="$1" if [[ -z "$wallet_path" ]]; then echo "Error: wallet_path required" >&2 return 1 fi mkdir -p "$(dirname "$wallet_path")" local address=$(generate_lightning_address) local public_key=$(generate_keypair) cat > "$wallet_path" << EOF { "created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", "address": "$address", "public_key": "$public_key", "balance_sats": 0, "mode": "local" } EOF chmod 600 "$wallet_path" echo "$address" } ``` ### Technical Analysis The function c ...[truncated 2301 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the stub implementation with a supported, tested Lightning wallet integration. 2. Decide whether keys are managed locally or by an external node: - For local custody, securely serialize encrypted private key material and implement signing and recovery. - For node custody, store a wallet or account reference and do not claim that the JSON file contains the private key. 3. Remove the random `lnbc_...` fallback from production behavior. 4. Validate every generated invoice or address using the appropriate Bitcoin or Lightning format parser. 5. Fail closed when wallet creation is unavailable; permit stubs only under an explicit, clearly marked test mode. 6. Separate test ledger balances from real payment balances and prominently identify them as non-monetary. 7. Query the wallet backend for authoritative balances rather than trusting editable JSON. 8. Update documentation and command output so they accurately describe custody, recovery, address type, and settlement behavior. 9. Protect any genuine key file with restrictive directory permissions, atomic creation, encryption at rest, backup guidance, and secure cleanup of temporary key material. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (40)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### 4. Clean Up

```bash
rm -rf ~/.openclaw/agentyard
rm -rf agents/testbot
```
Confidence
93% confidence
Finding
The documentation instructs users to run a forceful recursive delete against a path in their home directory with no warning, confirmation, or path validation. Although intended as test cleanup, copy-paste execution of rm -rf can lead to unintended local data loss if the directory contains real wallet or marketplace data, or if the path has been repurposed in a live environment.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### 4. Clean Up

```bash
rm -rf ~/.openclaw/agentyard
rm -rf agents/testbot
```
Confidence
93% confidence
Finding
The documentation instructs users to run a forceful recursive delete against a path in their home directory with no warning, confirmation, or path validation. Although intended as test cleanup, copy-paste execution of rm -rf can lead to unintended local data loss if the directory contains real wallet or marketplace data, or if the path has been repurposed in a live environment.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
```bash
rm -rf ~/.openclaw/agentyard
rm -rf agents/testbot
```

## File Structure
Confidence
90% confidence
Finding
The guide includes a forceful recursive deletion of the test agent directory without warning or confirmation. While narrower in scope than deleting wallet state, it can still cause accidental loss of local work if users reuse the same path for non-test content or execute the cleanup command from an unexpected project state.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description frames the skill as a marketplace service, but the documented commands include direct wallet-to-wallet transfers and local wallet mutation. Hidden or underemphasized money-moving and key-handling operations materially increase risk because users may invoke the skill without appreciating that it can alter balances and access wallet files.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description frames the skill as a marketplace service, but the documented commands include direct wallet-to-wallet transfers and local wallet mutation. Hidden or underemphasized money-moving and key-handling operations materially increase risk because users may invoke the skill without appreciating that it can alter balances and access wallet files.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description frames the skill as a marketplace service, but the documented commands include direct wallet-to-wallet transfers and local wallet mutation. Hidden or underemphasized money-moving and key-handling operations materially increase risk because users may invoke the skill without appreciating that it can alter balances and access wallet files.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The description frames the skill as a marketplace service, but the documented commands include direct wallet-to-wallet transfers and local wallet mutation. Hidden or underemphasized money-moving and key-handling operations materially increase risk because users may invoke the skill without appreciating that it can alter balances and access wallet files.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The description frames the skill as a marketplace service, but the documented commands include direct wallet-to-wallet transfers and local wallet mutation. Hidden or underemphasized money-moving and key-handling operations materially increase risk because users may invoke the skill without appreciating that it can alter balances and access wallet files.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description frames the skill as a marketplace service, but the documented commands include direct wallet-to-wallet transfers and local wallet mutation. Hidden or underemphasized money-moving and key-handling operations materially increase risk because users may invoke the skill without appreciating that it can alter balances and access wallet files.

Missing User Warnings

High
Confidence
96% confidence
Finding
The hire-creation flow sends task description, budget, and buyer email to the backend with no explicit notice or consent prompt. This is more serious because it includes personal contact information and potentially confidential task content, creating privacy, data-retention, and misuse risks if the backend is compromised or untrusted.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The README states that task results are delivered to email but does not disclose that outputs may be transmitted to external email infrastructure or warn about privacy, retention, and sensitivity risks. In this skill's context, agents may generate or relay user-provided data and outputs from chained third-party agents, so emailing results materially increases the chance of unintended disclosure.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
brew install jq

# Ubuntu/Debian
sudo apt-get install jq

# Windows (Git Bash)
# Download from https://github.com/jqlang/jq/releases
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The setup guide includes destructive cleanup commands that recursively delete directories under the user's home and workspace, but it does not prominently warn about data loss or advise users to verify the paths before running them. In documentation-driven workflows, users often copy and paste commands blindly, so even intended cleanup steps can cause accidental deletion if paths differ or variables are expanded unexpectedly.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill advertises shell-capable behavior via installation and command examples, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where reviewers and users cannot easily understand or constrain what the skill may execute, increasing the risk of unexpected local command execution.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill states that job results are delivered to email, but it does not present an explicit privacy/security warning near that behavior. Users may submit sensitive prompts or outputs without understanding that content and notifications could be transmitted through email infrastructure, which may be retained, forwarded, or exposed outside the local system.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script prints the filesystem path to the wallet file that stores private key material, which unnecessarily discloses the location of sensitive assets to anyone viewing terminal output, logs, screenshots, or remote session recordings. In the context of a wallet-managing marketplace skill, revealing where private keys are stored lowers the barrier for local theft or follow-on attacks if an attacker already has partial access to the host.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The installer prompts for an email address and persists it to config.json even though the skill description emphasizes marketplace payments and agent hiring rather than collection of personal contact data. In this context, email is personal data and the script does not clearly disclose retention, purpose limitation, or whether it will ever be transmitted, creating an unnecessary privacy and data-minimization risk.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script collects an email address and writes it to a local config file without a clear privacy warning about persistence or any explanation of handling practices. Because this is personally identifiable information, silent retention can violate user expectations and increases the risk of privacy exposure if the local account or filesystem is later accessed.

External Transmission

Medium
Category
Data Exfiltration
Content
fi

  local response
  response=$(_curl -s -w "\n%{http_code}" \
    --connect-timeout 10 --max-time 30 \
    -X POST "${AGENTYARD_API}/agents/register" \
    -H "Content-Type: application/json" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The function sends the full agent configuration JSON to a remote backend without any user-facing notice, consent step, or data-minimization controls. Even if expected for marketplace registration, this can disclose sensitive metadata, embedded secrets, internal paths, or prompts contained in the config to an external service.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This function transmits identifying key material (`public_key`) and agent name to the backend without warning the user that identity-linked wallet information is being shared. While a public key is not secret like a private key, it is still sensitive metadata that can enable tracking, correlation, or unintended account linkage when silently uploaded.

External Transmission

Medium
Category
Data Exfiltration
Content
'{ agent_name: $name, public_key: $key }')

  local response
  response=$(_curl -s -w "\n%{http_code}" \
    --connect-timeout 10 --max-time 30 \
    -X POST "${AGENTYARD_API}/wallets/create" \
    -H "Content-Type: application/json" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
'{ agent_id: $id, brief: $brief, max_sats: $sats, delivery_email: $email }')

  local response
  response=$(_curl -s -w "\n%{http_code}" \
    --connect-timeout 10 --max-time 30 \
    -X POST "${AGENTYARD_API}/jobs" \
    -H "Content-Type: application/json" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
fi
  
  echo "$config_json" | jq '.' > "${config_dir}/agentyard.json"
  chmod 600 "${config_dir}/agentyard.json"
}

# Get agent field
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
fi
  
  echo "$config_json" | jq '.' > "${config_dir}/agentyard.json"
  chmod 600 "${config_dir}/agentyard.json"
}

# Get agent field
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

Detected: suspicious.destructive_delete_command

Documentation contains a destructive delete command without an explicit confirmation gate.

Warn
Code
suspicious.destructive_delete_command
Location
SETUP.md:71