Back to skill

Security audit

Turbine

Security checks for vulnerabilities and agentic risk

Overview

This package is advertised as a turbine calculator, but the inspected files implement a stateful local record manager with deletion, export, config mutation, and a real shell-injection risk.

Review this carefully before installing. It is not just a turbine calculator; it stores and manages local records, can delete them, writes export files, and contains shell-script input-handling bugs that could be dangerous if an agent or another user can supply command arguments. Install only if you want this datastore behavior and trust the script in your environment.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/script.sh:136
Finding

Arbitrary Command Execution Through GNU sed Configuration Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 136-150
Vulnerability Type: Shell command execution through an attacker-controlled sed program
Risk Level: High

Vulnerable Code

bash
cmd_config() {
    local key="${1:-}" val="${2:-}"
    local cfg="$DATA_DIR/config.txt"
    if [ -z "$key" ]; then
        echo "=== Config ==="
        if [ -f "$cfg" ]; then
            while IFS="=" read -r k v; do echo "  $k=$v"; done < "$cfg"
        else echo "  (empty — use config <key> <value>)"; fi
    elif [ -z "$val" ]; then
        grep "^${key}=" "$cfg" 2>/dev/null | cut -d= -f2- || echo "(not set)"
    else
        if [ -f "$cfg" ] && grep -q "^${key}=" "$cfg" 2>/dev/null; then
            sed -i "s|^${key}=.*|${key}=${val}|" "$cfg"
        else
            echo "${key}=${val}" >> "$cfg"
        fi
        echo "Set: $key=$val"
    fi
}

Technical Analysis

The configuration key and value are interpolated directly into a GNU sed expression. Neither value is escaped for the regular-expression, replacement-string, or command-delimiter contexts.

On GNU sed, an attacker can terminate the replacement expression with the | delimiter and append the e flag. The e flag executes the resulting replacement text as a shell command. Because the generated replacement starts with key=, a value beginning with a semicolon can terminate that assignment and introduce a second command.

The same unsafe interpolation also permits regular-expression injection, replacement metacharacter injection, and unintended modification of configuration records.

Attack Path

  1. Create a configuration entry so that the vulnerable update branch is reached:
bash
scripts/script.sh config foo safe
  1. Update the existing key with a crafted value:
bash
scripts/script.sh config foo ';touch /tmp/turbine-pwned|e'
  1. The script constructs an expression equivalent to:
bash
sed -i 's|^foo=.*|foo
...[truncated 906 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not construct a sed program by interpolating untrusted keys or values.
  • Restrict configuration keys to a strict allowlist, such as:
bash
[[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || {
    echo "Invalid configuration key" >&2
    return 1
}
  • Replace the record using a safe temporary-file workflow in which the value is handled as data rather than executable syntax.
  • Prefer a structured configuration format and serializer, such as JSON manipulated with jq.
  • Create temporary files with mktemp inside the protected data directory, verify every operation, and atomically rename the completed file.
  • Add regression tests using values containing |, ;, &, backslashes, newlines, and sed flags.
  • If sed must be retained, escape all regular-expression and replacement metacharacters and reject line breaks. Escaping alone is less robust than replacing the implementation.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:10
Finding

Stored JSONL Corruption and Terminal Control-Sequence Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 10-15 and 54-69
Vulnerability Type: Improper JSON serialization and unsafe rendering of stored input
Risk Level: Medium

Vulnerable Code

bash
_save_entry() {
    _ensure_dirs
    local cmd="$1" val="$2"
    local ts=$(date '+%Y-%m-%d %H:%M:%S')
    printf '{"ts":"%s","cmd":"%s","val":"%s"}\n' "$ts" "$cmd" "$val" >> "$DATA_DIR/data.jsonl"
}

The stored data is later parsed and printed using regular expressions:

bash
cmd_list() {
    echo "=== Turbine Entries ==="
    if [ -f "$DATA_DIR/data.jsonl" ]; then
        local count=$(wc -l < "$DATA_DIR/data.jsonl")
        echo "Total: $count"
        echo "---"
        tail -20 "$DATA_DIR/data.jsonl" | while IFS= read -r line; do
            local ts=$(echo "$line" | grep -o '"ts":"[^"]*' | cut -d'"' -f4)
            local cmd=$(echo "$line" | grep -o '"cmd":"[^"]*' | cut -d'"' -f4)
            local val=$(echo "$line" | grep -o '"val":"[^"]*' | cut -d'"' -f4)
            echo "  [$ts] $cmd: $val"
        done
    else
        echo "No entries yet."
    fi
}

Technical Analysis

The _save_entry function inserts user-controlled entry text directly into a JSON string without JSON escaping. Characters such as double quotes, backslashes, carriage returns, and newlines therefore change the structure of the stored data.

A newline can create additional physical records in data.jsonl, while quotes can terminate the intended val field and inject additional JSON properties or malformed content. Consequently, line counts, removals, searches, listings, and exports can operate on attacker-forged or corrupted records.

The listing and search operations subsequently print extracted values directly to the terminal. Stored ANSI escape sequences or other control characters may manipulate terminal presentation, hide output, forge prompts, create deceptive links, or alter terminal state. The regular-expression-based pars ...[truncated 1324 chars]

Remediation
View remediation

Remediation Suggestions

  • Generate JSON with a real JSON serializer rather than printf. For example:
bash
jq -cn \
  --arg ts "$ts" \
  --arg cmd "$cmd" \
  --arg val "$val" \
  '{ts: $ts, cmd: $cmd, val: $val}' >> "$DATA_DIR/data.jsonl"
  • Parse records with jq instead of grep and cut.
  • Reject invalid records and report data corruption rather than silently processing malformed content.
  • Sanitize control characters before displaying stored values in an interactive terminal. Preserve the original encoded value in storage, but render a safe representation.
  • Consider rejecting embedded NUL bytes, carriage returns, and other non-printable characters where they are not needed.
  • Add tests covering quotes, backslashes, multiline text, Unicode, and ANSI escape sequences.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:100
Finding

Spreadsheet Formula Injection and Malformed CSV Export

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 100-119
Vulnerability Type: CSV injection caused by unescaped attacker-controlled fields
Risk Level: Medium

Vulnerable Code

bash
cmd_export() {
    local fmt="${1:-json}"
    local out="turbine-export.$fmt"
    if [ ! -f "$DATA_DIR/data.jsonl" ]; then echo "No data."; return 0; fi
    case "$fmt" in
        json) cp "$DATA_DIR/data.jsonl" "$out" ;;
        csv)
            echo "timestamp,command,value" > "$out"
            while IFS= read -r line; do
                ts=$(echo "$line" | grep -o '"ts":"[^"]*' | cut -d'"' -f4)
                c2=$(echo "$line" | grep -o '"cmd":"[^"]*' | cut -d'"' -f4)
                vl=$(echo "$line" | grep -o '"val":"[^"]*' | cut -d'"' -f4)
                echo "$ts,$c2,$vl" >> "$out"
            done < "$DATA_DIR/data.jsonl"
            ;;
        *) echo "Formats: json, csv"; return 1 ;;
    esac
    echo "Exported: $out ($(wc -c < "$out") bytes)"
}

Technical Analysis

The CSV exporter concatenates fields with commas without applying CSV quoting or escaping. An entry containing commas, quotes, carriage returns, or newlines can alter the column or row structure of the exported document.

Additionally, spreadsheet applications may interpret cells beginning with =, +, -, or @ as formulas. Because the value field is attacker-controlled and exported unchanged, a crafted entry can become an active spreadsheet formula when a user opens the generated file.

The exact effect depends on the spreadsheet application and its security settings. Potential behaviors include deceptive hyperlinks, formula evaluation, and attempts to reference external resources or local spreadsheet data.

Attack Path

  1. Add an entry whose value begins with a spreadsheet formula marker, for example:
bash
scripts/script.sh add '=HYPERLINK("https://example.invalid","Open report")'
  1. Export the stored data:
bash
scripts/scrip
...[truncated 851 chars]
Remediation
View remediation

Remediation Suggestions

  • Use a standards-compliant CSV serializer.
  • Enclose every field in double quotes and escape embedded double quotes by doubling them.
  • Normalize or reject embedded carriage returns and newlines if multiline cells are unnecessary.
  • Neutralize spreadsheet formulas in untrusted text fields. For cells beginning with =, +, -, or @, prefix the value with an apostrophe or use another mitigation appropriate to the target spreadsheet application.
  • Document that exported values are untrusted data.
  • Add tests for formulas, commas, quotes, carriage returns, newlines, and Unicode content.
  • Parse the source JSONL with a real JSON parser before export so malformed records cannot silently become malformed CSV.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims to be a turbine performance calculator, but the documented behavior is a generic local datastore with persistent storage, deletion, search, export, and configuration management. This mismatch is dangerous because it can mislead users and higher-level agents into granting trust or invoking the skill for a benign calculation task while it actually performs broader data-handling operations, increasing the risk of unintended data collection, retention, or exfiltration.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation presents an industrial calculator, but every command shown implements CRUD-style record management instead of turbine calculations. In an agent ecosystem, this kind of deceptive or inaccurate interface description can cause unsafe tool selection and over-broad trust, leading users or orchestrators to run a skill with materially different capabilities than expected.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script’s behavior materially contradicts the declared skill purpose: instead of calculating turbine performance, it implements a general local datastore with add/list/search/remove/export/config capabilities. In an agent skill ecosystem, this kind of purpose mismatch is dangerous because it can smuggle unrelated data-handling functionality under an innocuous description, increasing the chance of unauthorized persistence, exfiltration, or manipulation of user data.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The command descriptions directly contradict the stated purpose by documenting add/list/search/remove/export/config operations rather than turbine analysis functions. This inconsistency increases the chance of accidental misuse and conceals stateful data operations behind a benign industrial label, which is especially risky for autonomous agents relying on metadata to judge tool safety.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill exposes persistent storage, deletion, export, and free-form config editing that are not necessary for a turbine performance calculator. Even if not overtly exploitative by themselves, these capabilities broaden the attack surface and enable local data collection and modification under misleading pretenses, which is especially risky in agent environments where users may grant trust based on the advertised function.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The remove command deletes stored data immediately with sed -i and no confirmation, preview, undo, or backup. In a CLI/agent context this can cause accidental or induced data loss, especially if the command is invoked programmatically or with user-supplied indices.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The remove command states only that it removes an entry by number, without warning that it irreversibly deletes persisted local data. This can cause unintended data loss, particularly because the skill is framed as a calculator rather than a stateful datastore with destructive operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The export command is documented without disclosing where files are written, what data is included, or that previously stored local data may be persisted to another file. That omission can lead to accidental exposure of sensitive local records through unexpected file creation or later sharing of exported artifacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The export command creates or overwrites turbine-export.<fmt> in the current working directory, which is a file write affecting user data. Although the script reports the output path after completion, there is no prior disclosure, prompt, or inline warning that running the command will write a local file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.