Back to skill

Security audit

Gousto Recipes

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward Gousto recipe search tool with expected network access and local caching, though its documentation has minor disclosure and hardening issues.

Install only in a trusted workspace. Expect it to contact Gousto's API and create a local data/recipes.json cache; avoid running the cache updater from a shared or attacker-writable directory until the temp-file handling is hardened.

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

Warning
Location
scripts/update-cache.sh:9
Finding
Predictable Cache Paths Allow Symlink-Based File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/update-cache.sh`, lines 9, 28–29, and 72–74 **Vulnerability Type**: Predictable temporary file and unsafe symbolic-link handling **Risk Level**: Medium ### Vulnerable Code ```bash TEMP_FILE="$DATA_DIR/.recipes-temp.jsonl" # Clear temp file > "$TEMP_FILE" # Convert JSONL to array, dedupe by slug, sort by title jq -s 'unique_by(.slug) | sort_by(.title | ascii_downcase)' "$TEMP_FILE" > "$CACHE_FILE" rm -f "$TEMP_FILE" ``` ### Technical Analysis The cache update script uses predictable file paths: - `data/.recipes-temp.jsonl` - `data/recipes.json` Shell output redirection follows symbolic links. The statement `> "$TEMP_FILE"` therefore truncates the destination of a preexisting symbolic link. Likewise, redirection to `"$CACHE_FILE"` can overwrite the destination of a symbolic link placed at `data/recipes.json`. An attacker must first have sufficient access to create or replace entries in the project's `data` directory. If that condition is met, the attacker can cause the script to overwrite any file writable by the account running the skill. The use of quoted paths prevents ordinary shell word splitting but does not protect against symbolic-link attacks or time-of-check/time-of-use replacement. ### Attack Path 1. An attacker obtains write access to the project's `data` directory, such as through an insecure shared workspace or overly permissive project permissions. 2. The attacker creates a symbolic link using one of the predictable paths. For example: ```bash mkdir -p data ln -s "$HOME/.config/example.conf" data/.recipes-temp.jsonl ``` 3. A user or AI agent runs: ```bash ./scripts/update-cache.sh ``` 4. Line 29 executes shell redirection against the symbolic link. 5. The shell follows the link and truncates the linked file before recipe data is written. 6. Alternatively, an attacker can link `data/recipes.json` to a target file, causing line 73 to replace its content ...[truncated 784 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the temporary file securely with `mktemp` rather than using a predictable name. 2. Restrict the data directory to the current user and reject it if it is a symbolic link. 3. Write the completed cache to a secure temporary file and atomically rename it into place. 4. Use a trap to remove temporary files on success, failure, or interruption. 5. Verify that the final cache destination is not a symbolic link before replacement. Example hardening pattern: ```bash set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" DATA_DIR="$SCRIPT_DIR/../data" CACHE_FILE="$DATA_DIR/recipes.json" if [[ -L "$DATA_DIR" ]]; then echo "Error: Data directory must not be a symbolic link" >&2 exit 1 fi mkdir -p -- "$DATA_DIR" chmod 700 -- "$DATA_DIR" TEMP_FILE="$(mktemp "$DATA_DIR/.recipes-temp.XXXXXX")" trap 'rm -f -- "$TEMP_FILE"' EXIT HUP INT TERM # Populate TEMP_FILE here. if [[ -L "$CACHE_FILE" ]]; then echo "Error: Cache destination must not be a symbolic link" >&2 exit 1 fi FINAL_TEMP="$(mktemp "$DATA_DIR/.recipes-final.XXXXXX")" trap 'rm -f -- "$TEMP_FILE" "$FINAL_TEMP"' EXIT HUP INT TERM jq -s 'unique_by(.slug) | sort_by(.title | ascii_downcase)' \ "$TEMP_FILE" > "$FINAL_TEMP" chmod 600 -- "$FINAL_TEMP" mv -f -- "$FINAL_TEMP" "$CACHE_FILE" rm -f -- "$TEMP_FILE" trap - EXIT HUP INT TERM ``` For stronger protection in hostile shared directories, use operating-system APIs that reject symbolic links when opening files, or ensure the entire project and data directory are owned by and writable only by the trusted executing user. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The code chunk implements a narrow local search utility over an existing cache file (`recipes.json`). It performs case-insensitive title matching and outputs summary fields only. This does not match key parts of the declared description: there is no API access in the provided code, no retrieval or display of full ingredients, and no step-by-step cooking instructions. While the general domain of Gousto recipe search is aligned, the described functionality materially overstates what this code actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The code interacts with the Gousto API, which is consistent with the domain described, but the actual behavior is narrower and materially different from the declared purpose. It bulk-downloads recipe metadata for caching, not a search/browse interface, and it only stores summary fields rather than full recipe details. There is no logic for fetching ingredients or cooking instructions from individual recipes. Therefore the description overstates the implemented functionality.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill advertises shell and network-capable behavior through its scripts and metadata, but it does not declare an explicit tool scope such as allowed tools or permissions. That weakens sandboxing and user awareness, increasing the chance an agent invokes network or shell actions more broadly than intended.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The skill does not clearly warn users that update and recipe operations perform outbound network requests and write a local cache file. Missing this disclosure can cause unintentional data egress or filesystem modification in environments where network access and local writes are restricted or sensitive.

Intent-Code Divergence

Low
Confidence
90% confidence
Finding
The documentation says recipe fetches use the official Gousto API, yet the notes disclose dependence on a third-party vfjr.dev proxy. That discrepancy is security-relevant because users may unknowingly send requests, identifiers, and usage metadata to an unvetted external service outside the claimed trust boundary.

Static analysis

No suspicious patterns detected.