Back to skill

Security audit

Dont Waste Food

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent leftover-recipe helper, but its image handling and local storage controls are broader and less guarded than users would reasonably expect.

Review before installing. The cooking and recipe features appear purpose-aligned, but only use image inputs from trusted uploads or known safe locations, avoid giving it arbitrary local file paths or private/internal URLs, and be aware that it saves cooking history locally until cleared.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/image_handler.py:24
Finding

Arbitrary URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
tuple: """ Download an image from URL. Returns (local_path, error). """ os.makedirs(f"{WORKSPACE}/images", exist_ok=True) filename = f"{WORKSPACE}/images/img_{os.getpid()}.jpg" try: req = urllib.request.Request( url, headers={ "User-Agent": "Mozilla/5.0 (compatible; DontWasteFoodBot/1.0)" } ) with urllib.request.urlopen(req, timeout=timeout) as response: data = response.read() content_type = response.headers.get("Content-Type", "image/jpeg") ext = ".jpg" if "jpeg" in content_type or "jpg" in content_type else ".png" filename = filename.replace(".jpg", ext) with open(filename, "wb") as f: f.write(data) size = os.path.getsize(filename) if size < 500: os.remove(filename) return None, "File too small — not a valid image" return filename, None ``` ```python if is_url(source): return download_image(source) ``` ### Technical Analysis The image handler accepts a user-controlled HTTP or HTTPS URL and passes it directly to `urllib.request.urlopen`. It does not restrict destination hosts, resolve and inspect destination IP addresses, or reject loopback, private, link-local, reserved, and cloud metadata address ranges. Redirects are also not validated. An initially permitted-looking URL can therefore redirect the request to an internal destination. The implementation trusts the remote `Content-Type` header when selecting a file extension and does not verify that the downloaded content is an image. In addition, `response.read()` ...[truncated 1521 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/image_handler.py:94
Finding

Unrestricted Local File Copy Through User-Controlled Image Paths

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/session_manager.py:39
Finding

Path Traversal in Session Filename Construction

Content
View full analysis
str: """Save a session to disk. Returns session ID.""" ensure_dirs() if "id" not in session: session["id"] = str(uuid.uuid4())[:8] if "date" not in session: session["date"] = datetime.now().strftime("%Y-%m-%d") filepath = f"{SESSIONS_DIR}/{session['date']}_{session['id']}.json" with open(filepath, "w", encoding="utf-8") as f: json.dump(session, f, ensure_ascii=False, indent=2) _update_history(session) return session["id"] ``` ### Technical Analysis The function generates safe values only when `id` or `date` is absent. If the caller supplies either field, its value is accepted without validation and interpolated directly into a filesystem path. Directory separators and traversal sequences such as `../` can therefore alter the resolved destination. Because the function opens the resulting path in write mode, an existing writable file may be truncated and replaced with attacker-influenced JSON. The project documentation explicitly describes the session manager as importable, making this trust boundary relevant to module callers. The function does not canonicalize the final path, verify that it remains beneath `SESSIONS_DIR`, or use exclusive and atomic file creation. ### Attack Path 1. An attacker influences a session dictionary passed to `save_session()`. 2. The attacker supplies a crafted `date` or `id` containing directory separators and traversal components. 3. The function concatenates the value into `filepath` without validation. 4. Filesystem path resolution escapes the intended `sessions` directory. 5. `open(filepath, "w")` creates or truncates a writable `.json` file at the traversed location. 6. `json.dump()` writes attacker-influenced session ...[truncated 951 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied code chunk is narrowly focused on extracting ingredient names from natural-language Indonesian text using regex and a predefined alias dictionary. This partially aligns with the description's text-input ingredient analysis component, but it does not implement the broader advertised skill behavior. There is no image handling, no recipe generation, no cooking instructions, no safety assessment, and no stats tracking. There are also no undeclared risky permissions or unrelated external accesses. The mismatch is that the declared description substantially overstates the implemented functionality in this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code substantially aligns with part of the description: it matches user-provided ingredients to Indonesian recipes, formats recommendations, includes recipe details, and supports step-by-step guidance through step retrieval. However, the declared description claims additional capabilities that are not present in this code chunk, notably photo analysis for ingredient extraction and food-waste reduction stats tracking. The safety aspect is only partial: the code can display existing safety notes from recipe data, but it does not actually assess ingredient freshness or perform safety checks on leftovers. Therefore the description overstates the implemented behavior for this supplied code chunk.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module exposes a clear command that recursively deletes the entire workspace via shutil.rmtree(WORKSPACE) and immediately recreates it, with no confirmation, no authorization check, and no scope reduction. In a conversational skill context, this makes accidental or induced history loss plausible if another component wires this command to user input or invokes it programmatically.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documentation instructs the agent to read and write workspace files and fetch images from URLs, but it declares no explicit tool scope or permission boundary. That creates an authorization gap where the agent may use broader file or network capabilities than users or the platform expect, increasing the risk of unintended file access, data persistence, or network retrieval.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The description says to use the skill when the user 'mentions leftover food' or 'wants ideas for what to cook from what they already have,' which are broad conditions that overlap with common cooking conversation. It does not provide clear boundaries or exclusion examples to distinguish when this skill should activate versus a general cooking assistant.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill claims to work fully offline while also documenting the ability to download images from web URLs, which is a deceptive security-relevant inconsistency. Users or reviewers may trust the skill under an offline threat model even though network retrieval expands exposure to untrusted remote content and outbound requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The brand voice mandates 'Bahasa Indonesia as default language,' which sets a language constraint without indicating that the user can choose another language. The policy allows locale or language constraints when there is explicit choice or clearly justified documentation, which is not present here.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The /clear command deletes all history and stats without an explicit warning or confirmation requirement in the skill design. That creates a real integrity risk: users can lose stored data through accidental invocation, ambiguous parsing, or misuse by another party interacting with the session.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Allowing arbitrary web URL fetching for images is broader than necessary and can be abused for server-side request behavior, unexpected outbound connections, or retrieval of maliciously crafted payloads. In this skill context, image intake should be tightly constrained because recipe assistance does not require general web access.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The handler accepts any existing local filesystem path and copies it into the skill workspace without restricting the source to approved upload directories or validating that it is actually an image. In an agent context, if a user can influence source, this creates an arbitrary local file read/copy primitive that could expose sensitive host files to later processing or exfiltration, which is far beyond the stated food-photo use case.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Multiple user-visible strings are written only in Indonesian, such as statistics, history, and deletion messages, with no option for the user to select another language. This can violate language/locale policy when a skill forces a specific language without user opt-in or documented regional justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The required disclaimer mixes Indonesian with German ('Wenn dir nicht sicher bist, vertraue deinem Instinkt') even though no language preference or justification is documented. This introduces a forced language fragment that may violate language/locale policy expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The skill stores cooking history, ratings, notes, and ingredient data on disk but provides no privacy notice, retention policy, or deletion expectations beyond a clear command. While not an immediate exploit, undisclosed persistence can expose personal household patterns or food-related notes to other local users or tools sharing the workspace.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The metadata sets the skill language to "id", which is a natural-language locale restriction. In this file, there is no accompanying indication of user opt-in or a documented region-specific justification, so it may conflict with language/locale choice policy.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code fetches attacker-controlled URLs with no host allowlist, scheme narrowing beyond http/https, size limits, or SSRF protections. In a hosted agent environment, this can be abused to make requests to internal services or cloud metadata endpoints, and to download arbitrary content disguised as an image for further processing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code emits user-facing strings such as the fallback message and result summary only in Indonesian. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly justified, which is not present in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring states that the skill matches user input to Indonesian recipes, which is a locale/language constraint expressed in natural language. The file does not indicate any user choice, opt-in, or justification for enforcing that locale, so this is a policy concern under the language/locale rule.

Content

No source excerpt is available for this finding.