Back to skill

Security audit

Currconv

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent currency converter, but it has an unsafe code-construction bug where live API data can be inserted into Python code executed locally.

Review before installing. The skill's purpose and network use are clear, and it does not appear deceptive, but it should be fixed to pass API values to Python as data, validate rates as finite positive numbers, and avoid building executable code from remote responses.

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:296
Finding

Remote API Data Is Interpolated into Executable Python Source

Content
View full analysis
/dev/null)" # Also get today's rate for comparison local today_url="${API_BASE}/latest?from=${from}&to=${to}" local today_response today_rate today_date today_response="$(api_get "$today_url")" || true today_rate="$(echo "$today_response" | python3 -c " import sys, json d = json.load(sys.stdin) rates = d.get('rates', {}) to = '${to}' if to in rates: print(rates[to]) else: print('N/A') " 2>/dev/null || echo "N/A")" today_date="$(json_get "$today_response" "date" || echo "N/A")" local change_str="N/A" if [[ "$rate_val" != "N/A" && "$today_rate" != "N/A" ]]; then change_str="$(python3 -c " h = float('${rate_val}') t = float('${today_rate}') diff = t - h pct = (diff / h) * 100 sign = '+' if diff >= 0 else '' print(f'{sign}{diff:.6f} ({sign}{pct:.2f}%)') " 2>/dev/null || echo "N/A")" fi ``` ### Technical Analysis The `rate_val` and `today_rate` variables originate from JSON returned by the external `api.frankfurter.app` service. Although the responses are parsed as JSON, the values selected from the `rates` object are printed without verifying that they are JSON numbers. These remotely supplied values are subsequently interpolated directly into Python source passed to `python3 -c`: ```python h = float('${rate_val}') t = float('${today_rate}') ``` Shell quoting does not make this safe because variable expansion occurs before Python parses the generated source. If either value contains Python syntax that terminates the quoted string, that syntax becomes part of the program executed by Python. For example, a specially ...[truncated 1898 chars]
Remediation
View remediation
= 0 else '' print(f'{sign}{diff:.6f} ({sign}{pct:.2f}%)') PY )" || change_str="N/A" ``` Additional hardening should include: 1. Validate the decoded API schema before using it: - Require the top-level response to be an object. - Require `rates` to be an object. - Require the requested currency entry to be an integer or floating-point JSON number. - Reject strings, booleans, null values, arrays, and objects. 2. Reject non-finite values, zero, and negative exchange rates. 3. Apply the same data-versus-code separation to all `python3 -c` calls. Values such as JSON keys and formatting inputs should be supplied through `sys.argv` or standard input rather than interpolated into source. 4. Preserve HTTPS certificate verification and avoid adding options such as `curl -k`. 5. Add regression tests containing quote characters and Python syntax in mocked API rate values, confirming that the input is rejected and no code is executed. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/script.sh (reported line 142)May include surrounding context.

sh
from="$(validate_currency "$from_raw")"
  to="$(validate_currency "$to_raw")"

  check_curl

  echo "  Converting ${amount} ${from} → ${to} ..."
  echo ""

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/script.sh (reported line 204)May include surrounding context.

sh
local base
  base="$(validate_currency "$base_raw")"

  check_curl

  echo "  Fetching rates for ${base} ..."
  echo ""

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/script.sh (reported line 240)May include surrounding context.

sh
}

cmd_list() {
  check_curl

  echo "  Fetching available currencies ..."
  echo ""

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/script.sh (reported line 285)May include surrounding context.

sh
to="$(validate_currency "$to_raw")"
  validate_date "$date_str"

  check_curl

  echo "  Fetching historical rate for ${date_str} ..."
  echo ""

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill documentation indicates shell execution capability ('Requires curl', Bash usage, and command examples) but does not declare any explicit tool scope such as permissions or allowed-tools. This creates a trust and execution-boundary problem: an agent may invoke shell access more broadly than intended, and any future implementation details added to the skill could run with ambient shell privileges without clear user-visible constraints.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.