Back to skill

Security audit

Relay

Security checks for vulnerabilities and agentic risk

Overview

This skill is presented as an electrical relay helper, but its actual behavior is a persistent local record manager with deletion, export, and config-writing features.

Review this carefully before installing. It is not really a relay-logic or wiring-diagram helper; it stores arbitrary local entries under ~/.relay by default, can delete entries, writes export files in the current directory, and persists config values. Avoid storing sensitive data in it and avoid using RELAY_DIR paths that are shared, untrusted, or symlink-prone.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:9
Finding

Unescaped JSONL Serialization Permits Record Injection and Data Corruption

Content
View full analysis
> "$DATA_DIR/data.jsonl" } ``` The vulnerable function is reached from `cmd_add` at lines 47-52: ```bash cmd_add() { local value="${1:?Usage: relay add }" shift || true _save_entry "add" "$value $*" local count=$(wc -l < "$DATA_DIR/data.jsonl" 2>/dev/null || echo 0) echo "Added: $value (entry #$count)" } ``` ### Technical Analysis The `val` variable contains user-controlled command-line input and is inserted directly into a purported JSON object. No JSON encoding is applied to quotation marks, backslashes, control characters, or newline characters. For example, an entry containing a quotation mark can terminate the `val` string and introduce attacker-controlled JSON fields. An entry containing a newline can inject additional physical records into the JSONL file. Subsequent commands parse records using regular expressions rather than a JSON parser, making forged or malformed records more likely to be treated as legitimate data. ### Attack Path 1. An attacker or untrusted automation supplies an entry containing JSON syntax or newline characters. 2. `cmd_add` combines the arguments and passes them to `_save_entry`. 3. `_save_entry` interpolates the text directly into a JSON template. 4. The malformed text is appended to `data.jsonl`. 5. Later `list`, `search`, `stats`, `remove`, or `export` operations process the injected or corrupted records. ### Impact Assessment Exploitation does not grant additional operating-system privileges. It affects the integrity and availability of the application's local data within the configured `RELAY ...[truncated 223 chars]
Remediation
View remediation
> "$DATA_DIR/data.jsonl" ``` Additional hardening should include: 1. Validate or reject control characters if multiline entries are not required. 2. Parse stored records with a real JSON parser instead of `grep` and `cut`. 3. Write records to a securely created temporary file and atomically rename it when modifying the complete data file. 4. Detect and report malformed existing records rather than silently processing them. 5. Add tests covering quotes, backslashes, commas, Unicode, tabs, and newlines. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/script.sh:76
Finding

User-Controlled Regular Expression in Search

Content
View full analysis
}" if [ -f "$DATA_DIR/data.jsonl" ]; then local matches=$(grep -ic "$term" "$DATA_DIR/data.jsonl" 2>/dev/null || echo 0) echo "Found: $matches matches" grep -i "$term" "$DATA_DIR/data.jsonl" 2>/dev/null | head -20 | while IFS= read -r line; do local val=$(echo "$line" | grep -o '"val":"[^"]*' | cut -d'"' -f4) local ts=$(echo "$line" | grep -o '"ts":"[^"]*' | cut -d'"' -f4) echo " [$ts] $val" done else echo "No data to search." fi } ``` ### Technical Analysis The user-supplied `term` is passed to `grep` as a regular expression. Consequently, characters such as `.`, `*`, `[`, `]`, `^`, and `$` are interpreted as expression syntax rather than searched as literal text. This behavior allows a caller to match records outside the intended literal search scope. Invalid expressions can also make `grep` fail, while computationally expensive expressions may consume disproportionate resources on sufficiently large data files. ### Attack Path 1. An attacker supplies a search term containing regular-expression metacharacters. 2. `cmd_search` passes the term directly to two `grep` invocations. 3. `grep` interprets the term as a pattern rather than literal text. 4. The command returns unintended records, fails on malformed syntax, or performs avoidable pattern-processing work. ### Impact Assessment The issue does not provide elevated privileges or direct arbitrary command execution. Its scope is limited to the search operation and the configured data file. A caller can obtain broader-than-intended search results and interfere with reliable command execution. The practical availability impact depends on the size of the local data file and the ...[truncated 26 chars]
Remediation
View remediation
/dev/null || true) grep -Fi -- "$term" "$DATA_DIR/data.jsonl" ``` Prefer parsing each JSON record and searching only the intended field. If regular-expression search is an intentional feature, document it explicitly, validate patterns before use, impose reasonable input and file-size limits, and distinguish “no matches” from an invalid expression. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:137
Finding

Configuration Key and Value Injection Through Unsafe grep and sed Construction

Content
View full analysis
)"; 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 Configuration keys are embedded in `grep` and `sed` regular expressions without validation or escaping. A key containing regular-expression metacharacters can therefore match configuration entries other than the exact requested key. The key and value are also inserted into a `sed` substitution program without escaping the `|` delimiter, backslashes, replacement metacharacters such as `&`, or newline characters. Crafted input can alter replacement semantics, make the expression invalid, modify an unintended configuration line, or corrupt the configuration file. Because the script enables `set -e`, failures caused by malformed expressions may terminate the complete command unexpectedly. ### Attack Path 1. An attacker invokes `config` with a key containing regular-expression syntax or with a key/value containing `sed` metacharacters. 2. The initial `grep` may report that an unintended configuration key already exists. 3. The script constructs a `sed` program from the unescaped input. 4. `sed` modifies an unintended line, produces altered replacement content, or fails. 5. The configur ...[truncated 499 chars]
Remediation
View remediation
&2 return 1 fi ``` 2. Avoid constructing `sed` programs from untrusted strings. Use a structured configuration format and parser, or rebuild the file safely with exact string comparison. 3. If plain `key=value` storage is retained, reject newlines in keys and values and define an escaping format for `=` and backslashes. 4. Use literal matching, such as `grep -F`, where appropriate. 5. Write updates to a securely created temporary file in the same directory, set restrictive permissions, validate the result, and atomically rename it over the original. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:108
Finding

CSV Export Permits Spreadsheet Formula Injection and Structural Corruption

Content
View full analysis
"$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" ;; ``` ### Technical Analysis The exporter concatenates fields with commas but does not implement CSV quoting or escaping. Commas, quotation marks, carriage returns, and newlines in stored values can therefore create additional columns or rows. Values beginning with spreadsheet formula indicators such as `=`, `+`, `-`, or `@` may be interpreted as formulas when the exported file is opened in spreadsheet software. Depending on the spreadsheet application and its security settings, formulas may trigger external references or other formula-supported behavior. ### Attack Path 1. An attacker adds an entry whose value begins with a formula indicator or contains CSV delimiters and line breaks. 2. The value is stored in `data.jsonl`. 3. A user runs `scripts/script.sh export csv`. 4. The exporter writes the value without CSV quoting or formula neutralization. 5. The user opens `relay-export.csv` in spreadsheet software. 6. The spreadsheet may evaluate the attacker-controlled value as a formula, or parse the export into attacker-controlled rows and columns. ### Impact Assessment The direct scope includes the generated CSV file and the user who opens it. Structural injection can falsify or obscure exported records. Formula evaluation can cause spreadsheet-supported actions, including external requests in environments where such functionality is en ...[truncated 134 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:6
Finding

Attacker-Controlled Data Directory and Symlink-Following File Writes

Content
View full analysis
> "$DATA_DIR/data.jsonl" } ``` `SKILL.md` explicitly exposes the directory as configurable: ```markdown | `RELAY_DIR` | Data directory (default: ~/.relay/) | ``` ### Technical Analysis `RELAY_DIR` is accepted as an arbitrary path without canonicalization, ownership checks, permission checks, or restrictions to a trusted base directory. `_ensure_dirs` creates that path using the caller's current umask, and `_save_entry` opens `data.jsonl` with ordinary shell append redirection. Shell redirection follows an existing symbolic link. If the selected directory is shared or attacker-controlled, another user can pre-create `data.jsonl` as a symbolic link to a different file writable by the victim. A subsequent `add` operation appends application data to the link target. The code also does not explicitly enforce private directory and file permissions, so confidentiality depends on the caller's umask and the permissions of a user-selected directory. ### Attack Path 1. The victim is induced to use a shared or attacker-controlled `RELAY_DIR`, or automation supplies such an environment value. 2. The attacker creates the directory if needed and places a symbolic link named `data.jsonl` inside it. 3. The link points to another file writable by the victim. 4. The victim runs the `add` command. 5. Shell append redirection follows the symbolic link and appends the generated record to the target file. ### Impact Assessment The script cannot bypass operating-system permissions, so it can only alter f ...[truncated 405 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill advertises relay logic and status-checking functionality, but the documented commands describe a generic local record-management tool with persistent storage, deletion, export, and configuration operations. This mismatch can mislead users or agents into invoking capabilities they did not intend to authorize, increasing the risk of inappropriate file operations and trust abuse.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The banner describes a relay logic and wiring helper, but the code implements unrelated logging and file-management operations. This deceptive labeling increases the risk that a reviewer, user, or calling agent will trust and execute the script under false assumptions, enabling undisclosed local data collection and modification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The implementation materially diverges from the declared purpose: instead of relay-logic assistance, it provides a generic local datastore with search, deletion, export, and config mutation features. In an agent skill ecosystem, this kind of capability mismatch is dangerous because it can mislead users and orchestrators into invoking file-writing and data-handling behavior they did not consent to, creating a deceptive foothold for persistence and local data manipulation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest frames the skill as an electrical/relay helper, while the command set behaves like a generic CRUD utility over local data. This deceptive interface can cause an agent or user to grant the skill broader trust than warranted, leading to unintended persistence or manipulation of local files.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation claims relay-specific help and status checking, but all listed commands are generic entry-management actions. Such contradictions undermine informed consent and can conceal non-obvious side effects like local state changes, even if no direct exploit primitive is evident in the markdown alone.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documentation exposes remove and export operations without any warnings about deletion, overwriting, data disclosure, or destination paths. In agent-driven contexts, insufficient warning around destructive or data-moving operations can lead to accidental loss of locally stored information or unintended export of sensitive content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The remove command irreversibly deletes stored entries with no confirmation, backup, or undo. In an agent context, a mistaken or prompt-injected invocation could silently destroy user data, especially because the skill’s misleading relay-helper framing makes destructive data-management behavior less expected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The export command creates or overwrites relay-export.<fmt> in the working directory, but the help text does not mention that it writes files locally. In code-file review scope, file writes that affect user data should have at least some visible disclosure when not otherwise documented.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The script modifies or creates a persistent config file under the user's data directory, but there is no nearby comment, prompt, or explicit disclosure in the help text that config writes values to disk. Because this is a code file, persistent file writes should have at least some visible warning or explanation unless the behavior is clearly disclosed elsewhere.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.