Back to skill

Security audit

Rsi

Security checks for vulnerabilities and agentic risk

Overview

This RSI skill is review-worthy because it overstates its trading-analysis capabilities and contains a real shell command-injection flaw in the calculate command.

Install only if you understand this is mostly an RSI reference script, not a real asset-data calculator or trading advisor. Do not pass untrusted values to the calculate command, and do not rely on its buy/sell labels for financial decisions.

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

Error
Location
scripts/script.sh:8
Finding

Command Injection Through Unvalidated Arithmetic Expansion

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 8-32
Vulnerability Type: Bash arithmetic command injection
Risk Level: High

Vulnerable Code

bash
cmd_calculate() {
    local period="${1:-14}"
    cat << EOF
═══════════════════════════════════════════════════
  RSI Calculator — Period: ${period}
═══════════════════════════════════════════════════

【RSI Formula】
  RSI = 100 - (100 / (1 + RS))
  RS  = Average Gain / Average Loss (over ${period} periods)

【Step-by-step Calculation】
  1. Collect ${period} periods of closing prices
  2. Calculate price changes: Change = Close[i] - Close[i-1]
  3. Separate gains (positive changes) and losses (negative changes)
  4. Average Gain = Sum of gains / ${period}
  5. Average Loss = Sum of losses / ${period}
  6. RS = Average Gain / Average Loss
  7. RSI = 100 - (100 / (1 + RS))

【Smoothed RSI (Wilder's method, more common)】
  After first ${period} periods:
  Avg Gain = (Prev Avg Gain × $(( period - 1 )) + Current Gain) / ${period}
  Avg Loss = (Prev Avg Loss × $(( period - 1 )) + Current Loss) / ${period}

Technical Analysis

The calculate command copies its first command-line argument into the period variable without validating that it is an integer. The variable is subsequently referenced by Bash arithmetic expansions:

bash
$(( period - 1 ))

Bash recursively evaluates the value of a variable used in an arithmetic expression. A malicious value can therefore contain an arithmetic array-subscript expression with command substitution. When Bash evaluates period, the command substitution embedded in that expression is executed by the shell.

Quoting the original assignment does not prevent this issue because the dangerous evaluation occurs later, inside the arithmetic expansion. The use of set -euo pipefail also does not prevent command substitution from running; the script may terminate after the payload has already executed.

For example, a local ca ...[truncated 2093 chars]

Remediation
View remediation

Remediation Suggestions

Validate the argument before it is used in any arithmetic context. Accept only ASCII decimal digits and enforce a reasonable positive range:

bash
cmd_calculate() {
    local period="${1:-14}"

    if [[ ! "$period" =~ ^[0-9]+$ ]]; then
        printf 'Error: period must be a positive integer.\n' >&2
        return 1
    fi

    if (( 10#$period < 1 || 10#$period > 1000 )); then
        printf 'Error: period must be between 1 and 1000.\n' >&2
        return 1
    fi

    local period_num=$((10#$period))
    local previous_period=$((period_num - 1))

Use only the validated numeric variables in output:

bash
Avg Gain = (Prev Avg Gain × ${previous_period} + Current Gain) / ${period_num}
Avg Loss = (Prev Avg Loss × ${previous_period} + Current Loss) / ${period_num}

Additional hardening measures:

  1. Reject signs, whitespace, variable names, brackets, command substitutions, and other non-digit characters.
  2. Use 10# after validation to force base-10 interpretation and avoid unintended octal handling of leading zeros.
  3. Enforce an upper bound to prevent unreasonable or misleading period values.
  4. Add regression tests using malicious arithmetic expressions and verify that no external command executes.
  5. Avoid evaluating untrusted strings through Bash arithmetic expansion anywhere else in the Skill.
  6. If arithmetic is not necessary for the displayed reference text, remove the dynamic arithmetic expansion entirely.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill advertises market-analysis capabilities such as calculating RSI for any asset, spotting divergence, comparing timeframes, and supporting alerts, but the described interface does not show access to asset data or logic matching those claims. In a finance context, this can mislead users or downstream agents into relying on unsupported trading signals, creating integrity and decision-risk even if it is not a classic code-execution issue.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is presented as an RSI calculator, but the implementation only prints explanatory text and example math instead of calculating RSI from user-supplied price data. In a trading context, this mismatch can mislead users into believing they received a computed indicator for a real asset, which may cause incorrect investment decisions based on nonexistent analysis.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script outputs concrete trading signals such as 'STRONG BUY' and 'SELL / CAUTION' without a clear disclaimer that this is not financial advice and that trading can result in losses. In the context of an investing skill, authoritative signal wording can encourage unsafe user reliance, especially when combined with the misleading calculator framing.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The help text and command names reinforce the false impression that the tool calculates RSI for assets, while it actually offers static educational content and interpretation of a manually entered number. This deceptive interface increases the chance of user reliance on inaccurate assumptions in a financial decision-making workflow.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest description says to use the skill when checking trading conditions, spotting divergence, comparing timeframes, or setting alerts, but it does not define specific invocation phrases, scope limits, or negative examples. This broad natural-language activation guidance could overlap with many ordinary finance discussions and lead to unintended invocation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.