T09 · Insecure Skill Coding Practices
- Location
scripts/setup.sh:112- Finding
API Secret Is Entered with Terminal Echo Enabled
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill does what it claims, but it handles merchant payment credentials in ways that need careful review before installation.
Review this before installing on any shared, managed, recorded, or multi-user machine. The skill can create and modify real payment links using your MoonPay Commerce credentials, so confirm amounts, currencies, pay-link IDs, and wallet selection before running commands. Store the config with strict owner-only permissions, avoid running setup while screen sharing or recording, and rotate the API secret if it may have appeared in terminal output or process logs.
scripts/setup.sh:112API Secret Is Entered with Terminal Echo Enabled
scripts/setup.sh:119Bearer Credential Is Exposed Through curl Process Arguments
scripts/setup.sh:39Credential Loader Accepts Group-Readable or Group-Writable Configuration Files
scripts/setup.sh:68Status Command Unnecessarily Discloses API Secret Fragments
The skill clearly instructs use of shell commands and external network access, but it does not declare an explicit tool scope such as allowed-tools or permissions. That weakens runtime safety boundaries and can let an agent invoke shell/network capabilities more broadly than reviewers or the platform expect.
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.
---
name: mpc-accept-crypto-payments
description: Accept crypto payments on Solana via MoonPay Commerce (formerly Helio). Create Pay Links, generate checkout URLs, check transactions, and list supported currencies. Use when the user wants to accept crypto payments, create payment links, charge for products/services with crypto, or query payment transactions. Requires a MoonPay Commerce account with API key and secret.
metadata:
openclaw:
requires:
The skill is designed to create persistent payment artifacts such as pay links and associated charges, which can outlive the current session and have financial consequences. In a payments context this is expected functionality, but it is still security-relevant because accidental or unauthorized creation of links can lead to fraud, confusion, or operational issues.
curl -s https://api.hel.io/v1/currency | jq '.[].symbol'
### Create a Pay Link
```bash
curl -s -X POST "https://api.hel.io/v1/paylink/create/api-key?apiKey=$HELIO_API_KEY" \
-H "Authorization: Bearer $HELIO_API_SECRET" \
The pay-link creation example performs authenticated outbound transmission and includes credential material in a way that may be captured by logs or telemetry. Because the skill handles payment operations, this is contextually expected, but compromise of these credentials could enable unauthorized payment-link creation or merchant account abuse.
curl -s -X POST "https://api.hel.io/v1/paylink/create/api-key?apiKey=$HELIO_API_KEY" \
-H "Authorization: Bearer $HELIO_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
The pay-link creation example performs authenticated outbound transmission and includes credential material in a way that may be captured by logs or telemetry. Because the skill handles payment operations, this is contextually expected, but compromise of these credentials could enable unauthorized payment-link creation or merchant account abuse.
curl -s -X POST "https://api.hel.io/v1/paylink/create/api-key?apiKey=$HELIO_API_KEY" \
-H "Authorization: Bearer $HELIO_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
This charge-creation request sends authenticated data to the external API and again exposes the API key in the URL. While this network access is core to the skill's function, the credential handling approach raises the risk of secret disclosure and unauthorized transaction-related actions if logs are exposed.
curl -s -X POST "https://api.hel.io/v1/charge/api-key?apiKey=$HELIO_API_KEY" \
-H "Authorization: Bearer $HELIO_API_SECRET" \
-H "Content-Type: application/json" \
-d '{"paymentRequestId": "<PAYLINK_ID>"}'
The transaction-check request is an authenticated external call using sensitive credentials, with the API key in the URL. Even read-oriented calls can leak account data and credentials if request details are logged or shared unintentionally.
curl -s "https://api.hel.io/v1/paylink/<PAYLINK_ID>/transactions?apiKey=$HELIO_API_KEY" \
-H "Authorization: Bearer $HELIO_API_SECRET"
This authenticated PATCH request can change pay-link state and exposes the API key in the request URL. If the credentials leak, an attacker could disable or re-enable payment links and disrupt payment operations.
curl -s -X PATCH "https://api.hel.io/v1/paylink/<PAYLINK_ID>/disable?apiKey=$HELIO_API_KEY&disabled=true" \
-H "Authorization: Bearer $HELIO_API_SECRET"
The documentation explicitly instructs users to send the API secret as a bearer token and the API key in the query string, but it does not include any guidance on securely storing, redacting, or avoiding exposure of those credentials. In a payment-processing skill, this omission increases the chance that implementers will log secrets, paste them into shared traces, or otherwise mishandle credentials that grant access to financial operations.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
echo "Creating Pay Link: $name — $amount $symbol ($price base units, currency=$currency_id, swap=on)"
result=$(curl -s -X POST "$BASE/paylink/create/api-key?apiKey=$HELIO_API_KEY" \
-H "Authorization: Bearer $HELIO_API_SECRET" \
-H "Content-Type: application/json" \
-d "$(jq -n \
This shell script sends authenticated requests to the Helio API using both an API key and bearer secret, but it does not include any user-facing warning about transmitting credentials and payment-link metadata to a third-party network service. While the script logs the action being taken, the usage/help text does not disclose the privacy-sensitive external transmission behavior.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
check_auth
echo "Creating charge for paylink $paylink_id..."
result=$(curl -s -X POST "$BASE/charge/api-key?apiKey=$HELIO_API_KEY" \
-H "Authorization: Bearer $HELIO_API_SECRET" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg id "$paylink_id" '{paymentRequestId: $id}')")
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.
Commands:
currencies List Solana currencies (no auth needed)
currency-id <SYMBOL> Get currency ID for a symbol
create-paylink <name> <amount> <symbol> Create a Pay Link
charge <paylink-id> Create a checkout URL for payers
transactions <paylink-id> List transactions for a Pay Link
disable <paylink-id> Disable a Pay Link
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
CONFIG_DIR="$HOME/.mpc/helio"
CONFIG_FILE="$CONFIG_DIR/config"
BASE="https://api.hel.io/v1"
die() { echo "❌ $1" >&2; exit 1; }
ok() { echo "✅ $1"; }
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
return 1
fi
# Reject world-readable or world-writable
local perms
if stat --version &>/dev/null 2>&1; then
perms=$(stat -c '%a' "$cfg") # GNU
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
return 1
fi
# Reject world-readable or world-writable
local perms
if stat --version &>/dev/null 2>&1; then
perms=$(stat -c '%a' "$cfg") # GNU
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
return 1
fi
# Reject world-readable or world-writable
local perms
if stat --version &>/dev/null 2>&1; then
perms=$(stat -c '%a' "$cfg") # GNU
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
return 1
fi
# Reject world-readable or world-writable
local perms
if stat --version &>/dev/null 2>&1; then
perms=$(stat -c '%a' "$cfg") # GNU
No suspicious patterns detected.