Back to skill

Security audit

crypto-monitor

Security checks for vulnerabilities and agentic risk

Overview

This crypto-monitoring skill mostly matches its purpose, but it needs review because one script can automatically modify the host system and multiple shell options can be abused to run unintended commands.

Review before installing. Run it only in a low-privilege environment, do not let it auto-install packages, and avoid passing untrusted or generated option values until the numeric arguments are validated and the missing/overstated features are corrected.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/price.sh:39
Finding

Arbitrary Command Execution Through Bash Arithmetic Injection in Price Options

Content
View full analysis
0" | bc -l 2>/dev/null || echo 0) )); then arrow="📈" elif (( $(echo "$change < 0" | bc -l 2>/dev/null || echo 0) )); then arrow="📉" else arrow="➡️" fi local sign="" (( $(echo "$change > 0" | bc -l 2>/dev/null || echo 0) )) && sign="+" printf "%s #%s %s: \$%'.2f (%s%.1f%%) | MCap: \$%'.0f | Vol: \$%'.0f\n" \ "$arrow" "$rank" "${symbol^^}" "$price" "$sign" "$change" "$(( $(printf '%.0f' "$mcap") ))" "$(( $(printf '%.0f' "$vol") ))" done ``` ```bash main() { while true; do DATA=$(fetch_prices) || { echo "❌ Failed to fetch prices"; exit 1; } case "$FORMAT" in json) output_json "$DATA" ;; csv) output_csv "$DATA" ;; *) output_text "$DATA" ;; esac [[ "$WATCH" -gt 0 ]] && sleep "$WATCH" || break done } ``` ### Technical Analysis The `--top` and `--watch` arguments are stored as arbitrary strings without checking that they contain only decimal digits. They are later evaluated by Bash arithmetic operators through ...[truncated 2130 chars]
Remediation
View remediation
&2 exit 2 fi } require_uint "top value" "$TOP" require_uint "watch interval" "$WATCH" ``` Apply explicit bounds to prevent excessive resource use: ```bash (( TOP >= 1 && TOP <= 100 )) || { echo "Top value must be between 1 and 100" >&2 exit 2 } (( WATCH == 0 || (WATCH >= 5 && WATCH <= 86400) )) || { echo "Watch interval must be 0 or between 5 and 86400 seconds" >&2 exit 2 } ``` Additional hardening should include: 1. Check that options requiring values actually have a following argument before reading `$2`. 2. Reject unknown options instead of treating all unrecognized arguments as coin identifiers. 3. Avoid passing untrusted text into Bash arithmetic contexts. 4. Add negative tests using malformed values, arithmetic syntax, array references, and command-substitution payloads. 5. Run the Skill as a non-privileged user with minimal filesystem and environment access. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/whale.sh:21
Finding

Arbitrary Command Execution Through Bash Arithmetic Injection in Whale Result Limit

Content
View full analysis
/dev/null | jq -r '.result // "0"' 2>/dev/null) if [[ "$latest_block" == "0" || -z "$latest_block" ]]; then echo "⚠️ Etherscan API unavailable" return fi # Convert hex to decimal local block_dec=$((latest_block)) local count=0 for ((i=0; i<20; i++)); do local bn=$((block_dec - i)) local hex_bn hex_bn=$(printf "0x%x" "$bn") local block block=$(curl -sf "https://api.etherscan.io/api?module=proxy&action=eth_getBlockByNumber&tag=$hex_bn&boolean=true" 2>/dev/null) echo "$block" | jq -r ' .result.transactions[]? | select((.value | tonumber) > 10000000000000000000) | # > 10 ETH "🐋 \((.value | tonumber / 1000000000000000000 * 100 | round / 100)) ETH | \(.from[0:10])... → \(.to[0:10])... | block \(.blockNumber)" ' 2>/dev/null | head -5 count=$((count + 1)) [[ $count -ge $LIMIT ]] && break done } ``` ### Technical Analysis The `--limit` option accepts arbitrary input and stores it in `LIMIT`. The expression: ```bash [[ $count -ge $LIMIT ]] ``` causes Bash to evaluate `LIMIT` as an arithmetic expression. Bash arithmetic evaluat ...[truncated 1540 chars]
Remediation
View remediation
&2 exit 2 fi if (( LIMIT < 1 || LIMIT > 100 )); then echo "Limit must be between 1 and 100" >&2 exit 2 fi ``` The same validation pattern should be applied to `MIN_VALUE`. Although its current use is primarily as a URL parameter, validating it avoids malformed requests and prevents future unsafe reuse. Further hardening should include: 1. Verify that `$2` exists for every value-taking option. 2. Validate `CHAIN` against an explicit allowlist: ```bash case "$CHAIN" in ethereum|bitcoin|all) ;; *) echo "Invalid chain" >&2; exit 2 ;; esac ``` 3. Reject unknown options with a nonzero exit status. 4. Do not rely on shell quoting as protection in arithmetic contexts. 5. Add regression tests proving that arithmetic syntax and command substitutions are rejected. 6. Run the tracker under a least-privileged account without unnecessary secrets in its environment. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/price.sh:10
Finding

Automatic Unpinned System Package Installation During Price Queries

Content
View full analysis
/dev/null 2>&1 || { echo "Installing jq..." >&2; apt-get install -y -qq jq 2>/dev/null || true; } ``` ### Technical Analysis The price script invokes the system package manager automatically whenever `jq` is unavailable. This behavior occurs before command-line argument processing, so even a benign operation such as requesting `--help` can attempt to modify the host. The installation: - Is not subject to explicit user confirmation. - Does not pin a package version. - Trusts all currently configured APT repositories and package metadata. - May execute package maintainer scripts. - Can modify system-wide files if the Skill runs with sufficient privileges. - Suppresses installation errors and then continues, making failures difficult to diagnose. The Skill's declared purpose only requires querying and formatting public cryptocurrency data. Automatically changing the operating system is broader than the minimum runtime privilege necessary for that function. ### Attack Path 1. The Skill is invoked on a Debian-compatible host where `jq` is absent. 2. The dependency check fails. 3. The script automatically runs: ```bash apt-get install -y -qq jq ``` 4. APT retrieves the package and metadata from the host's configured repositories. 5. If the process has sufficient privileges, APT installs system files and runs applicable package lifecycle scripts. 6. A compromised or incorrectly configured repository could therefore introduce hostile package content into a privileged execution path. No evidence shows that this project configures a malicious repository or intentionally installs a malicious package. The risk arises from implicit, unpinned, potentially privileged dependency installation. ### Impact As ...[truncated 710 chars]
Remediation
View remediation
/dev/null 2>&1; then echo "Error: jq is required. Install it through your trusted system administration process." >&2 exit 127 fi ``` Recommended dependency controls: 1. Install dependencies during a separate, explicit deployment phase rather than during a price query. 2. Require informed administrator or user approval before changing system packages. 3. Pin and test dependency versions in a controlled container image or reproducible environment. 4. Use only authenticated, organization-approved repositories. 5. Run installation separately from the Agent runtime and with narrowly scoped privileges. 6. Do not suppress package-manager errors. 7. Move dependency checking after argument parsing so `--help` does not require runtime dependencies. 8. Document `jq` as a prerequisite without claiming that it will be installed automatically. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Claiming broad crypto analytics while only performing a much narrower trending-token retrieval is a deceptive capability mismatch. In this context, the danger is less about direct code execution and more about misrouting users and concealing the true operational scope, which weakens oversight and increases the chance of unsafe approval.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Claiming broad crypto analytics while only performing a much narrower trending-token retrieval is a deceptive capability mismatch. In this context, the danger is less about direct code execution and more about misrouting users and concealing the true operational scope, which weakens oversight and increases the chance of unsafe approval.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

Claiming broad crypto analytics while only performing a much narrower trending-token retrieval is a deceptive capability mismatch. In this context, the danger is less about direct code execution and more about misrouting users and concealing the true operational scope, which weakens oversight and increases the chance of unsafe approval.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Claiming broad crypto analytics while only performing a much narrower trending-token retrieval is a deceptive capability mismatch. In this context, the danger is less about direct code execution and more about misrouting users and concealing the true operational scope, which weakens oversight and increases the chance of unsafe approval.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/whale.sh (reported line 96)May include surrounding context.

sh
fetch_etherscan_whales

echo ""
echo "💡 Free tier limits apply. For production use, get API keys from whale-alert.io and etherscan.io"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises shell-based capabilities and auto-install behavior but does not declare any explicit tool scope or permissions. This creates a trust and containment gap: a host may permit broader command execution than users expect, and reviewers cannot easily verify what system actions are intended.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger list is broad enough to activate on ordinary finance, research, or multilingual conversation that may not require this skill. Overbroad activation increases unnecessary invocation of networked or shell-capable behavior, which expands attack surface and can lead to unintended data access or execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Ambiguous activation conditions without clear exclusions make it difficult to predict when the skill will run. In a skill with internet and shell expectations, vague routing is dangerous because it can cause the agent to invoke external actions for loosely related user requests.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/airdrop.sh (reported line 11)May include surrounding context.

sh
# Check DefiLlama airdrops
echo "📡 Checking DeFiLlama airdrops..."
data=$(curl -sf --connect-timeout 10 "https://api.llama.fi/airdrops" 2>/dev/null) || {
    echo "⚠️  DeFiLlama API unavailable"
    data="[]"
}

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script silently attempts to install jq with apt-get, which exceeds the stated purpose of price monitoring and performs a privileged system modification. In an agent/skill context this is risky because invoking the skill can trigger unexpected package management activity, potentially requiring elevated privileges and changing the host environment without explicit consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Automatically installing a system package without warning or confirmation is unsafe because it can alter the system state unexpectedly and may run with elevated privileges in some environments. In a skill intended only to fetch crypto prices, this behavior is unnecessary and increases the blast radius from simple data retrieval to host modification.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/price.sh (reported line 6)May include surrounding context.

sh
# Discover trending tokens via CoinGecko
set -euo pipefail

API_BASE="https://api.coingecko.com/api/v3"

usage() {
    cat << EOF

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/trending.sh (reported line 5)May include surrounding context.

sh
# Discover trending tokens via CoinGecko
set -euo pipefail

API_BASE="https://api.coingecko.com/api/v3"

usage() {
    cat << EOF

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/whale.sh (reported line 33)May include surrounding context.

sh
# Try whale-alert.io free API
fetch_whale_alert() {
    local url="https://api.whale-alert.io/v1/transactions?api_key=free&min_value=${MIN_VALUE}&limit=${LIMIT}"
    
    local result
    result=$(curl -sf --connect-timeout 10 "$url" 2>/dev/null) || {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/whale.sh (reported line 57)May include surrounding context.

sh
# Use etherscan API for latest block transactions
    local latest_block
    latest_block=$(curl -sf "https://api.etherscan.io/api?module=proxy&action=eth_blockNumber" 2>/dev/null | jq -r '.result // "0"' 2>/dev/null)
    
    if [[ "$latest_block" == "0" || -z "$latest_block" ]]; then
        echo "⚠️  Etherscan API unavailable"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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/whale.sh (reported line 74)May include surrounding context.

sh
# Use etherscan API for latest block transactions
    local latest_block
    latest_block=$(curl -sf "https://api.etherscan.io/api?module=proxy&action=eth_blockNumber" 2>/dev/null | jq -r '.result // "0"' 2>/dev/null)
    
    if [[ "$latest_block" == "0" || -z "$latest_block" ]]; then
        echo "⚠️  Etherscan API unavailable"

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The inline comment at L51 says 'no API key for basic', presenting the Etherscan access path as keyless. However, the script's own output at L96 tells users to get API keys from etherscan.io, which conflicts with that guidance and could mislead users about the actual operational requirements of the code path.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.