Back to skill

Security audit

SUPAH Pulse

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do its advertised crypto market briefing, but it can automatically spend wallet USDC on broad market prompts and has a local temp-file overwrite risk.

Review this before installing if your agent wallet can make x402 payments. Use it only where paid calls require user approval or strict wallet limits, and avoid running it with elevated privileges until the /tmp output path is fixed.

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/market-pulse.sh:73
Finding

Predictable Shared Temporary Output Permits Symlink-Based File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/market-pulse.sh, lines 73 and 385
Vulnerability Type: Unsafe temporary-file handling and symlink following
Risk Level: Medium

Vulnerable Code

Payment-required path at line 73:

bash
echo '{"error":"payment_required","price":"0.03","currency":"USDC","network":"base","endpoint":"'${API_BASE}'/agent/v1/market/regime","method":"x402","docs":"https://www.x402.org"}' > /tmp/market-pulse-result.json

Successful-result path at line 385:

javascript
fs.writeFileSync('/tmp/market-pulse-result.json', JSON.stringify(json, null, 2));

Technical Analysis

Both execution paths write to the fixed, publicly predictable pathname /tmp/market-pulse-result.json. The script neither securely creates this destination nor verifies that it is a regular file owned by the invoking user. Shell redirection and Node.js fs.writeFileSync() ordinarily follow symbolic links.

On a multi-user system, another local user may create that pathname as a symbolic link before the Skill runs. The subsequent write then truncates and replaces the symlink target with generated JSON. Although the script securely creates its intermediate directory using mktemp -d, it does not use that protected directory for its final output.

Exploitation requires local access and knowledge of when the Skill will run. The attacker does not gain arbitrary file contents or direct code execution through this flaw alone because the data written is generated by the Skill. However, the attacker can target any existing file writable by the account executing the Skill.

Attack Path

  1. A local attacker identifies a file writable by the victim account.
  2. The attacker creates a symbolic link at the predictable destination:
    bash
    ln -s /path/to/victim-writable-file /tmp/market-pulse-result.json
    
  3. The victim invokes scripts/market-pulse.sh.
  4. Either the payment-required branch at line 73 or the successful-result branch at ...[truncated 945 chars]
Remediation
View remediation

Remediation Suggestions

  1. Write results inside the already-secure directory created with mktemp -d:

    bash
    RESULT_FILE="$TMPDIR/market-pulse-result.json"
    

    Pass this path to Node.js through an environment variable or positional argument rather than embedding it in JavaScript source.

  2. If the result must remain available after the cleanup trap runs, create a private per-user result directory with restrictive permissions:

    bash
    RESULT_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/supah-pulse"
    install -d -m 700 "$RESULT_DIR"
    RESULT_FILE="$RESULT_DIR/market-pulse-result.json"
    
  3. Create a unique output file securely:

    bash
    RESULT_FILE=$(mktemp "$RESULT_DIR/market-pulse-result.XXXXXX.json")
    chmod 600 "$RESULT_FILE"
    
  4. If a stable filename is required, write to a securely created temporary file in the same private directory and atomically rename it into place. Ensure the directory is not writable by other users.

  5. Avoid relying only on a pre-write symbolic-link check, because checking and then opening the path introduces a time-of-check/time-of-use race. Use secure creation semantics that reject existing paths or use a private directory controlled exclusively by the invoking user.

  6. Avoid running this Skill with elevated privileges. Its declared market-intelligence functionality does not require administrative access.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises shell-capable execution requirements (curl, node) and outbound network use but does not declare an explicit tool scope such as permissions or allowed-tools. This creates ambiguity about what the agent may execute and makes it easier for an orchestrator to invoke shell/network actions without clear user-facing boundaries, especially in a paid skill that can trigger wallet spending.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill does involve automatic paid network calls, but the description and usage framing do not prominently warn that invoking ordinary market questions may spend USDC from the agent wallet. Because spending is automatic and tied to broad trigger phrases, users or upstream agents may unknowingly authorize repeated micropayments and external data transfers.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The usage phrases are broad natural-language prompts like 'What's the market doing right now?' and 'Is it a good time to buy?', which are common user intents unrelated to explicitly invoking this paid skill. In an agent environment, this can cause accidental activation, leading to unintended external requests and automatic x402 micropayments from the agent wallet.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script performs the paid SUPAH request immediately in the background before any runtime warning is printed, relying only on comments in the file to disclose the $0.03 x402 charge. In agentic or automated environments, this can trigger unintended micropayments without explicit user awareness or consent, especially because the script description says the agent pays automatically.

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/market-pulse.sh (reported line 32)May include surrounding context.

sh
P1=$!

# CoinGecko: Global market + prices (public, enriches the briefing)
curl -sf "https://api.coingecko.com/api/v3/global" \
  -o "$TMPDIR/global.json" 2>/dev/null &
P2=$!

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/market-pulse.sh (reported line 36)May include surrounding context.

sh
P1=$!

# CoinGecko: Global market + prices (public, enriches the briefing)
curl -sf "https://api.coingecko.com/api/v3/global" \
  -o "$TMPDIR/global.json" 2>/dev/null &
P2=$!

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/market-pulse.sh (reported line 41)May include surrounding context.

sh
P3=$!

# Fear & Greed
curl -sf "https://api.alternative.me/fng/?limit=7" \
  -o "$TMPDIR/fng.json" 2>/dev/null &
P4=$!

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

sh
P4=$!

# DeFiLlama: Chain TVLs
curl -sf "https://api.llama.fi/v2/chains" \
  -o "$TMPDIR/chains_tvl.json" 2>/dev/null &
P5=$!

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script formats price output using toLocaleString('en-US'), which hard-codes a specific locale. This is a natural-language/locale policy issue because it imposes one locale format without offering user opt-in or documenting why that locale is required.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.