Back to skill

Security audit

Chefpad

Security checks for vulnerabilities and agentic risk

Overview

ChefPad appears to be a local recipe tool, but crafted recipe text could cause code to run on the user's machine.

Review before installing. The tool is local and does not appear to phone home, but it should not be used with untrusted or automatically imported recipe text until the publisher fixes argument handling by passing values as data rather than interpolating them into Python code.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/script.sh:16
Finding
Arbitrary Python Code Execution Through Unsafe Heredoc Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/script.sh`, lines 16-27. The same vulnerable pattern also occurs at lines 38-50, 61-73, 96-116, 126-138, 150-162, 176-189, and 202-222. **Vulnerability Type**: Python source-code injection **Risk Level**: High ### Vulnerable Code ```bash cmd_add() { local name="$1"; shift local cuisine="${1:-general}"; shift local time_mins="${1:-30}" if [ -z "$name" ]; then echo "Usage: chefpad add <name> [cuisine] [time_minutes]" return 1 fi python3 << PYEOF import json, time as t recipe = {"id": int(t.time()), "name": "$name", "cuisine": "$cuisine", "time": int("$time_mins"), "ingredients": [], "steps": [], "rating": 0, "created": t.strftime("%Y-%m-%d")} try: with open("$RECIPES_FILE") as f: data = json.load(f) except: data = [] data.append(recipe) with open("$RECIPES_FILE", "w") as f: json.dump(data, f, indent=2) print("Recipe added: {} ({}, {}min)".format("$name", "$cuisine", "$time_mins")) PYEOF } ``` ### Technical Analysis The script constructs Python programs using unquoted heredocs and inserts command-line arguments directly into Python string literals. Values such as `$name`, `$cuisine`, `$ingredient`, `$step`, `$recipe_id`, `$query`, `$rating`, and `$ingredients` are treated as Python source rather than serialized data. Shell quoting used when invoking the CLI does not make these values safe for insertion into Python source. An argument containing quotation marks, backslashes, Python syntax, or embedded newline characters can terminate the intended string or expression and introduce additional Python statements. This pattern appears in the following commands: - `add`: lines 16-27 - `ingredient`: lines 38-50 - `step`: lines 61-73 - `show`: lines 96-116 - `search`: lines 126-138 - `rate`: lines 150-162 - `random`: lines 176-189, through interpolation of the storage path - `suggest`: lines 202-222 The storage path is derived from `$HOME`, so an attacker who ...[truncated 2026 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Stop interpolating input into Python source.** Pass all dynamic values as positional arguments: ```bash python3 - "$name" "$cuisine" "$time_mins" "$RECIPES_FILE" <<'PYEOF' import json import sys import time name, cuisine, time_mins_raw, recipes_file = sys.argv[1:] time_mins = int(time_mins_raw) recipe = { "id": int(time.time()), "name": name, "cuisine": cuisine, "time": time_mins, "ingredients": [], "steps": [], "rating": 0, "created": time.strftime("%Y-%m-%d"), } try: with open(recipes_file, encoding="utf-8") as source: data = json.load(source) except (FileNotFoundError, json.JSONDecodeError): data = [] data.append(recipe) with open(recipes_file, "w", encoding="utf-8") as destination: json.dump(data, destination, indent=2) print("Recipe added: {} ({}, {}min)".format(name, cuisine, time_mins)) PYEOF ``` 2. **Quote every heredoc delimiter** as `<<'PYEOF'`. This prevents shell parameter, command, and arithmetic expansion inside the Python program. 3. **Apply the same correction to every command**, including `ingredient`, `step`, `show`, `search`, `rate`, `random`, and `suggest`. File paths must also be passed as data rather than embedded in Python source. 4. **Validate input explicitly**: - Require recipe IDs to match the intended numeric format. - Parse cooking time as an integer and enforce a reasonable range. - Continue enforcing ratings from 1 through 5. - Reject malformed input with a nonzero exit status and a clear error message. 5. **Avoid broad exception handlers** such as `except:`. Catch specific exceptions so programming errors and maliciously corrupted files are not silently treated as empty databases. 6. **Protect data integrity** by writing to a securely created temporary file in the same directory and atomically replacing the destination after successful serialization. 7. **Add regression tests** for arguments containing single and doub ...[truncated 196 chars]
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The manifest and description promise grocery lists, ingredient tracking, and meal planning, but the documented functionality only covers recipe storage/search/rating and even declares unused internal files like `favorites.json`. This mismatch can mislead users and security reviewers about what the skill actually does, which weakens trust boundaries and can hide undeclared or incomplete behavior.

Lp3

Medium
Category
MCP Least Privilege
Confidence
76% confidence
Finding
The skill documentation describes behavior that writes local files (`~/.chefpad/recipes.json` and `favorites.json`) but does not declare any tool scope or permissions boundary. That creates an integrity and transparency problem: a host agent may allow file-writing behavior without an explicit declaration, making the skill's real capabilities less visible to reviewers and users.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The documentation advertises grocery list and meal plan support, but the command set only implements recipe CRUD, search, rating, and random suggestion features. Security-sensitive systems rely on accurate documentation to understand data flows and permissions, so overstated capabilities can conceal gaps, confuse users, and complicate review.

Intent-Code Divergence

Low
Confidence
61% confidence
Finding
The body documentation emphasizes a strictly local tool with no external services, while the metadata includes remote homepage and source locations. Although these URLs may be informational rather than operational, they create a mild documentation-level inconsistency about how self-contained the skill is presented to be.

Description-Behavior Mismatch

Low
Confidence
96% confidence
Finding
The manifest describes broader capabilities including grocery list management and meal plans. In this file, the implemented commands only add, modify, list, search, rate, and suggest recipes; there are no commands or data structures for grocery lists or meal planning.

Static analysis

No suspicious patterns detected.