Back to skill

Security audit

Cmms

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local CMMS CLI skill, but it contains a real shell-injection flaw in configuration updates and weak export encoding that warrant review before installation.

Review or patch the shell script before installing. At minimum, replace the sed-based config update with data-safe file rewriting, validate config keys, encode JSON with a real JSON encoder, quote CSV fields correctly, and treat exported CSV files from untrusted entries carefully.

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 GNU sed Program Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 138-150, with the vulnerable command at lines 145-146
Vulnerability Type: Shell command execution through unsafe construction of a GNU sed program
Risk Level: High

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

Both key and val originate from command-line arguments and are interpolated directly into a double-quoted sed program. No validation or escaping is applied for sed delimiters, regular-expression metacharacters, replacement metacharacters, backslashes, or newline characters.

An attacker can place a newline in val, terminate the intended substitution with the | delimiter, and append another sed command. On GNU sed, the e command executes a shell command. For example, a value shaped like the following can turn the generated sed program into multiple commands:

text
benign|
e touch /tmp/cmms-proof
# 

The resulting program is conceptually equivalent to:

sed
s|^existing=.*|existing=benign|
e touch /tmp/cmms-proof
#|

The vulnerability is reached only through the update branch, so the selected configuration key must already match an entry in config.txt. Input in key can also alter the regular expression an ...[truncated 1803 chars]

Remediation
View remediation

Remediation Suggestions

Do not construct a sed program by interpolating untrusted configuration data.

  1. Validate configuration keys against a strict allowlist, such as:
    bash
    [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || {
        echo "Invalid configuration key" >&2
        return 1
    }
    
  2. Replace the sed update with a parser that treats keys and values exclusively as data. Write the revised configuration into a securely created temporary file in the same directory.
  3. Use mktemp, restrictive permissions, and an atomic mv after the complete file has been written successfully.
  4. Preserve values without evaluating them as shell, regular-expression, or sed syntax.
  5. If sed must be retained, escape every character significant to both the search expression and replacement expression, reject carriage returns and newlines, and avoid GNU sed extensions capable of command execution. A structured implementation without dynamically generated sed code is preferred.
  6. Add regression tests covering newlines, |, backslashes, ampersands, regular-expression metacharacters, and attempted e command injection.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:13
Finding

Unsafe JSONL and CSV Serialization Allows Record Forgery and Spreadsheet Formula Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, line 13 and lines 102-115
Vulnerability Type: Improper output encoding for JSONL and CSV data
Risk Level: Medium

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"
}
bash
cmd_export() {
    local fmt="${1:-json}"
    local out="cmms-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

_save_entry inserts the attacker-controlled entry value directly between JSON quotation marks. It does not escape quotation marks, backslashes, control characters, carriage returns, or newline characters according to JSON encoding rules.

A value containing " can terminate the intended JSON string and inject additional properties. A value containing a literal newline can terminate the physical JSONL record and create additional forged lines. Consequently, data.jsonl is not guaranteed to contain one valid JSON object per line, despite the documented storage format. The later list, search, and export operations use regular-expression extraction rather than a JSON parser, which further perm ...[truncated 2483 chars]

Remediation
View remediation

Remediation Suggestions

  1. Generate JSON through a real JSON encoder rather than string interpolation. For example, use jq with --arg:
    bash
    jq -cn \
      --arg ts "$ts" \
      --arg cmd "$cmd" \
      --arg val "$val" \
      '{ts: $ts, cmd: $cmd, val: $val}' >> "$DATA_DIR/data.jsonl"
    
  2. Parse stored records with a JSON parser instead of grep and cut. Reject or quarantine malformed legacy records.
  3. Generate CSV using an RFC 4180-compliant serializer. Enclose fields in quotation marks and double embedded quotation marks while safely preserving commas and line breaks.
  4. If exports are intended for spreadsheet use, neutralize fields beginning with =, +, -, or @, for example by prefixing a single quotation mark, or provide an export mode that explicitly treats all values as text.
  5. Document any formula-neutralization behavior so consumers understand that exported values may differ from raw stored values.
  6. Add tests for quotation marks, backslashes, commas, CRLF sequences, multiline values, Unicode control characters, and spreadsheet formula prefixes.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill documentation lists remove and export commands, and elsewhere states that data is stored under ~/.cmms/ and configuration can be set, but it provides no warning about deletion, file creation, or modification of local user data. For markdown files, the rubric requires warnings when behaviors could affect user data or system integrity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This shell script writes persistent configuration data to $DATA_DIR/config.txt, but the code provides no prior warning in comments or help text that using the config command will modify files under the user's home directory. Although it echoes the result after writing, that is not a disclosure before the safety-relevant file modification occurs.

Content

No source excerpt is available for this finding.