Back to skill

Security audit

Podcast Notes

Security checks for vulnerabilities and agentic risk

Overview

This is a mostly disclosed local podcast note logger, but its search and export code has review-worthy safety flaws around out-of-scope file reads and unsafe exported data.

Review before installing. The skill keeps podcast content in local plaintext logs and can export all history, so avoid entering secrets, confidential sponsor details, or unpublished material unless that storage is acceptable. The author should fix grep option handling and use proper JSON/CSV serializers before this is treated as a low-risk utility.

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

Warning
Location
scripts/script.sh:104
Finding
Search-Term Option Injection Allows Out-of-Scope File Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/script.sh`, lines 104-119 **Vulnerability Type**: Argument and option injection into `grep` **Risk Level**: Medium ### Vulnerable Code ```bash _search() { local term="${1:?Usage: podcast-notes search <term>}" echo "Searching for: $term" local found=0 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local matches=$(grep -i "$term" "$f" 2>/dev/null || true) if [ -n "$matches" ]; then echo " --- $(basename "$f" .log) ---" echo "$matches" | while read -r line; do echo " $line" found=$((found + 1)) done fi done [ $found -eq 0 ] && echo " No matches found." } ``` ### Technical Analysis The user-controlled `term` is passed to `grep` without terminating option parsing. Quoting the variable prevents shell word splitting but does not prevent `grep` from interpreting a value beginning with a hyphen as an option. For example, a search term in the form `-f/path/to/file` may be interpreted as a `grep` pattern-file option rather than as a literal search term. This causes `grep` to read a user-selected, process-readable file outside the declared podcast data directory and use its contents as search patterns. The redirected standard error limits direct error disclosure, but matching behavior and output may still provide a content oracle. Selecting a device or unusually large file as a pattern source may also consume excessive CPU, memory, or I/O resources. ### Attack Path 1. An attacker supplies a crafted search term beginning with a valid `grep` option, such as `-f/path/to/readable/file`. 2. The `search` dispatch passes that value to `_search`. 3. `_search` executes `grep -i "$term" "$f"` for every podcast log. 4. `grep` interprets the term as an option and reads the attacker-selected file as a pattern source. 5. Any resulting matches are printed, potentially revealing whethe ...[truncated 713 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Terminate option parsing and use literal fixed-string matching unless regular expressions are explicitly required: ```bash local matches matches=$(grep -iF -- "$term" "$f" 2>/dev/null || true) ``` Additional hardening should include: 1. Reject empty search terms explicitly. 2. Use `--` before every user-controlled positional argument passed to command-line utilities. 3. Prefer `grep -F` to avoid unintended regular-expression interpretation. 4. Consider limiting the maximum search-term length to reduce resource-exhaustion risk. 5. Add tests for terms such as `-f/etc/passwd`, `--help`, `-e`, and strings containing regular-expression metacharacters. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:62
Finding
Unescaped JSON and CSV Export Enables Data Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/script.sh`, lines 62-85 **Vulnerability Type**: Unsafe serialization and spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```bash json) echo "[" > "$out" local first=1 for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do [ $first -eq 1 ] && first=0 || echo "," >> "$out" printf ' {"type":"%s","time":"%s","value":"%s"}' "$name" "$ts" "$val" >> "$out" done < "$f" done echo "" >> "$out" echo "]" >> "$out" ;; csv) echo "type,time,value" > "$out" for f in "$DATA_DIR"/*.log; do [ -f "$f" ] || continue local name=$(basename "$f" .log) while IFS='|' read -r ts val; do echo "$name,$ts,$val" >> "$out" done < "$f" done ;; ``` ### Technical Analysis Podcast entry values are attacker-controllable and are written directly into JSON and CSV output without format-specific escaping. For JSON exports, quotation marks, backslashes, control characters, and embedded line breaks are not escaped. A crafted value can terminate the intended JSON string, inject additional properties or objects, or make the entire export invalid. For CSV exports, fields are not quoted and embedded quotation marks are not escaped. Commas and line breaks can create additional columns or rows. Values beginning with spreadsheet formula prefixes such as `=`, `+`, `-`, or `@` may be interpreted as formulas when the export is opened in spreadsheet software. This is a stored injection path because malicious content is first persisted in a log and later incorporated into an export. ### Attack Path 1. An attacker causes a crafted entry to be saved through a content command such as `draft`, `edit`, or `outline`. 2. The entry is stored in the associated plaintext log. 3. A user invokes `podcast-notes export json` o ...[truncated 1176 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use format-aware serializers rather than constructing JSON or CSV through string interpolation. For JSON: 1. Encode every string according to JSON escaping rules. 2. Use a trusted serializer such as `jq` if adding a dependency is acceptable. 3. If the implementation must remain pure Bash, implement and thoroughly test escaping for quotation marks, backslashes, tabs, carriage returns, line feeds, and other control characters. 4. Validate the completed export with a standards-compliant JSON parser. For CSV: 1. Enclose every field in double quotes. 2. Replace each embedded double quote with two double quotes. 3. Preserve embedded commas and line breaks according to RFC 4180. 4. Neutralize formula-prefixed values before spreadsheet use, for example by applying an explicit safe-text policy. 5. Document whether exports are intended for machine processing, spreadsheet use, or both. Representative CSV field escaping: ```bash csv_escape() { local value=$1 value=${value//\"/\"\"} printf '"%s"' "$value" } ``` The implementation should call the escaping function separately for each field and avoid constructing rows with an unescaped `echo`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill is presented as a podcast content generation assistant, but the documented behavior is primarily persistent logging, search, export, and reporting over user-supplied text. This mismatch can mislead users into providing sensitive draft content or business information without understanding that the tool stores it locally and does not actually perform the promised generation tasks.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The skill advertises podcast content generation, but the implementation only stores and redisplays user input. This is a capability mismatch that can mislead users into providing sensitive draft material under false assumptions, while the real behavior is silent local collection and retention of their content.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation explicitly states that all inputs are written to plain-text logs in the user's home directory, but it does not warn about retention of sensitive material such as unpublished episode plans, guest details, sponsor notes, or credentials accidentally pasted into commands. Because the logs are searchable and exportable, accidental disclosure risk increases beyond a transient prompt interaction.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
User-supplied podcast notes are written to persistent files under the home directory without any notice, consent, or retention policy. Because creative drafts may contain unpublished content, sponsor details, guest information, or other sensitive material, silent retention creates a privacy and confidentiality risk.

Ssd 3

Medium
Confidence
93% confidence
Finding
The workflow persistently logs raw user content and then exposes it through multiple retrieval paths including search, recent activity, status, and export. In the context of a podcast assistant, users are likely to input unreleased outlines, guest questions, and business plans, making broad re-exposure of plaintext history more dangerous than a transient content tool would imply.

Description-Behavior Mismatch

Medium
Confidence
87% confidence
Finding
The manifest specifically names podcast-related outputs such as outlines, show notes, intro scripts, guest questions, monetization strategies, and distribution channels. The CLI exposes additional generic operations like edit, optimize, rewrite, translate, tone, headline, hashtags, search, recent, stats, status, and export, which are not reflected in the stated skill scope.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The script adds persistent logging, search, stats, recent-history viewing, and export of all accumulated content, none of which are necessary for a simple podcast drafting assistant. These features materially increase data exposure by making stored user content easy to enumerate and bulk extract.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The export function aggregates all stored history into a new file and overwrites a predictable path like export.json/csv/txt without confirmation or privacy warning. This increases the blast radius of any disclosure by consolidating all content into one easily copied artifact.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
The description begins in Chinese and then switches to English, but the document does not explain whether the skill supports multilingual interaction by user choice or has a language-selection policy. For organizational language/locale policies, unexplained mixed-language defaults can be a policy concern if users are not offered an explicit choice.

Static analysis

No suspicious patterns detected.