Back to skill

Security audit

Ppe

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent PPE tracker, but its configuration command has an artifact-backed command-execution flaw and its data-changing/export behavior is under-warned.

Review this skill before installing. It appears intended to be a local PPE tracker, but avoid using the config command with untrusted values, be careful with remove/export because they change or write local files, and do not open exported CSVs in spreadsheet software unless the data is trusted.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/script.sh:145
Finding

Arbitrary Command Execution Through Sed Expression Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 145-149
Vulnerability Type: Command injection through dynamically constructed sed expression
Risk Level: High

Vulnerable Code

bash
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"

Technical Analysis

The config command accepts key and val as user-controlled command-line arguments. When an existing key is updated, both values are interpolated directly into a sed program.

GNU sed supports the e substitution flag, which executes the substitution result using a shell. An attacker can include the sed delimiter and an e flag in val, terminating the intended replacement expression and enabling shell execution.

For example, a value such as:

text
;id >/tmp/ppe-proof|e

causes the constructed sed expression for key x to resemble:

bash
s|^x=.*|x=;id >/tmp/ppe-proof|e

If the expression matches an existing configuration line, GNU sed executes the generated replacement text through /bin/sh. Quoting the shell variable expansion does not mitigate this issue because the injection occurs inside the syntax interpreted by sed, rather than during the caller's initial shell parsing.

The key is also inserted into a grep regular expression and sed regular expression without validation, creating additional expression-injection and matching-integrity risks.

Attack Path

  1. The attacker causes a configuration key to exist:

    bash
    PPE_DIR=/tmp/ppe-test scripts/script.sh config x initial
    
  2. The attacker updates that key with a crafted value:

    bash
    PPE_DIR=/tmp/ppe-test scripts/script.sh config x ';id >/tmp/ppe-proof|e'
    
  3. The script builds a sed substitution expression containing the injected delimiter and e flag.

  4. The exi ...[truncated 832 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not construct sed programs by interpolating untrusted input.

  • Restrict configuration keys to a safe identifier format, for example:

    bash
    if [[ ! "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then
        echo "Invalid configuration key" >&2
        return 1
    fi
    
  • Rewrite the configuration through a securely created temporary file instead of dynamically modifying it with sed.

  • Pass data separately from program syntax, such as through environment variables or appropriately constrained awk -v variables.

  • Reject line breaks and control characters in configuration values.

  • Create temporary files inside the data directory with mktemp, apply restrictive permissions, and atomically replace the original file only after successful processing.

  • Add regression tests using values containing |, backslashes, newlines, semicolons, and sed flags to verify that they remain inert data.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:13
Finding

Unsafe JSONL and CSV Serialization of Attacker-Controlled Entries

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, line 13 and lines 112-116
Vulnerability Type: Output injection through missing JSON and CSV escaping
Risk Level: Medium

Vulnerable Code

JSONL serialization at line 13:

bash
printf '{"ts":"%s","cmd":"%s","val":"%s"}\n' "$ts" "$cmd" "$val" >> "$DATA_DIR/data.jsonl"

CSV serialization at lines 112-116:

bash
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"

Technical Analysis

The add command ultimately passes user-controlled entry text to _save_entry. The value is inserted into a JSON string without escaping quotation marks, backslashes, carriage returns, newlines, or other JSON control characters.

A crafted entry can therefore terminate the intended JSON string, add fields, or introduce additional physical records. The file may no longer be valid JSONL, and downstream processing based on grep and quote delimiters can interpret attacker-controlled content as structural data.

During CSV export, fields are concatenated with commas without RFC 4180 quoting. Commas, quotation marks, and line breaks can alter the number and meaning of records and columns. In addition, values beginning with spreadsheet formula indicators such as =, +, -, or @ may be interpreted as formulas when the exported file is opened in spreadsheet software.

Attack Path

  1. An attacker supplies a crafted PPE entry through the add command.

  2. The entry is inserted directly into data.jsonl without JSON encoding.

  3. Quotes or line breaks in the entry corrupt the record or inject additional apparent fields or records.

  4. The attacker or another user invokes:

    bash
    scripts/script.sh export csv
    
  5. The script writes the extracted value to CSV without quoting ...[truncated 958 chars]

Remediation
View remediation

Remediation Suggestions

  • Use a real JSON serializer rather than formatting JSON with printf. For example, use jq with values supplied through --arg:

    bash
    jq -cn --arg ts "$ts" --arg cmd "$cmd" --arg val "$val" \
      '{ts:$ts,cmd:$cmd,val:$val}' >> "$DATA_DIR/data.jsonl"
    
  • Parse stored JSON with a JSON parser instead of grep and delimiter-based extraction.

  • Produce RFC 4180-compliant CSV by enclosing every field in double quotes and replacing each embedded double quote with two double quotes.

  • Preserve embedded newlines only through a CSV-aware library or serializer.

  • If exports are intended for spreadsheet use, neutralize formula-leading cells according to the target application's guidance, such as by prefixing dangerous values with an apostrophe.

  • Add tests covering quotation marks, backslashes, commas, CR/LF characters, Unicode, and values beginning with =, +, -, or @.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill description and trigger phrases are broad and loosely scoped, such as 'use when json ppe tasks, csv ppe tasks, checking ppe status,' without defining boundaries, required user intent, or safe operating conditions. This can cause over-invocation in unrelated contexts and may lead an agent to run local scripts unexpectedly, increasing the chance of unintended data access or state-changing operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The documentation lists destructive and data-moving commands like 'remove' and 'export' without warning that removal changes persistent state or that export writes data to files. In an agent setting, missing warnings reduce friction for risky actions and can lead to accidental deletion, unintended file creation, or disclosure of PPE tracking data to unsafe locations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This shell script is a code file, so SQP-2 applies to file writes that lack disclosure. The config command updates or appends to a persistent file in the user's data directory, but there is no prior comment, docstring, or help text warning that this command changes saved configuration on disk; only a post-action success message is shown after the write occurs.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.