Back to skill

Security audit

design pick2

Security checks for vulnerabilities and agentic risk

Overview

This skill should go to Review because it claims to make food collages but also ships an undeclared Cloudflare image-generation script with embedded credentials and unsafe shell execution.

Do not install this version without review and remediation. The collage script itself is a straightforward local image compositor, but the package should remove or fully disclose the Cloudflare image-generation script, revoke and replace the exposed token, avoid shell=True with prompt input, and handle API responses without a shared /tmp file.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_image.py:13
Finding

Hardcoded Cloudflare API Credential in Source Code

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_image.py:23
Finding

Arbitrary Shell Command Injection Through the Image Prompt

Content
View full analysis
/tmp/cf_response.json''' subprocess.run(cmd, shell=True) ``` ### Technical Analysis The user-controlled `prompt` is serialized as JSON and then inserted inside a shell command delimited by single quotes. JSON serialization escapes JSON metacharacters, but it does not make a value safe for inclusion in POSIX shell syntax. In particular, a single quote contained in the prompt can terminate the shell's quoted `-d` argument. Shell operators appended after that quote can then be interpreted as commands. The call to `subprocess.run(..., shell=True)` causes the constructed string to be parsed by a command shell. Therefore, shell metacharacters introduced through the prompt can alter the command structure rather than remaining inert request data. The prompt is accepted directly from the positional command-line argument: ```python parser.add_argument('prompt', help='Image description/prompt') ``` Consequently, any caller able to influence the prompt can potentially execute arbitrary commands with the privileges of the process running this skill. ### Attack Path 1. An attacker supplies a prompt containing a single quote that terminates the shell-quoted JSON body. 2. The attacker appends shell syntax and an operating-system command, followed by suitable syntax to neutralize the remainder of the generated command. 3. `json.dumps` produces valid JSON but does not neutralize the shell quote. 4. The script interpolates the serialized value into `cmd`. 5. `subprocess.run(cmd, shell=True)` asks the shell to parse the atta ...[truncated 1226 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_image.py:23
Finding

Predictable Shared Temporary File Enables Symlink and Race Attacks

Content
View full analysis
/tmp/cf_response.json''' subprocess.run(cmd, shell=True) with open('/tmp/cf_response.json', 'r') as f: data = json.load(f) ``` ### Technical Analysis Every invocation writes its response to the same predictable path, `/tmp/cf_response.json`. The file is created through shell redirection and is later reopened by path. No secure exclusive creation, ownership verification, file-type verification, permission restriction, locking, or cleanup is performed. In a shared environment, an attacker may create that path as a symbolic link before execution. Shell redirection follows symbolic links, allowing the running process to truncate and overwrite another file that it is authorized to write. The attacker does not inherit additional permissions, but the write occurs with the victim process's permissions. Concurrent legitimate invocations can also overwrite each other's responses between the network request and JSON parsing. An attacker capable of modifying the temporary path may replace its contents with attacker-controlled JSON, causing incorrect processing or controlled error behavior. ### Attack Path A symlink attack can proceed as follows: 1. The attacker predicts the fixed path `/tmp/cf_response.json`. 2. Before the skill runs, the attacker creates that path as a symbolic link to a target file writable by the skill process. 3. The skill executes the shell redirection. 4. The shell follows the link and truncates or overwrites the target with the Cloudflare response. 5. The skill subsequentl ...[truncated 1198 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The stated purpose is a narrowly scoped food-collage generator, but the analyzed behavior reportedly includes generic image generation, missing promised collage/layout logic, undeclared external network access, and hardcoded credentials for a Cloudflare Workers AI API. That combination is dangerous because it conceals materially different behavior from users and reviewers while embedding secrets and enabling undisclosed outbound communications, which can be used for abuse, data exfiltration, or unauthorized third-party API usage.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file contains hardcoded Cloudflare account credentials and bearer token, which are highly sensitive secrets. If exposed through source control, logs, packaging, or reuse, they enable unauthorized API access, billing abuse, and possible compromise of the associated account resources.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

Sensitive credentials are embedded and then transmitted to an external service without any user-facing disclosure or consent flow. In the context of a food-collage skill, undisclosed third-party transmission and secret use is more dangerous because it exceeds reasonable user expectations and masks data egress behind an innocuous description.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The implementation is a generic external image-generation client, not a collage generator matching the declared food-collage skill. This mismatch is dangerous because users and reviewers may grant the skill permissions or trust assumptions based on the stated purpose, while the code actually performs broader prompt transmission to a third-party AI service.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

This is a tool-parameter abuse issue because untrusted prompt data is incorporated into a shell command that invokes an external tool. An attacker can supply crafted input to alter the curl command or execute arbitrary shell commands, leading to code execution, data theft, or filesystem tampering.

Content

Scanner excerpt · scripts/generate_image.py (reported line 30)May include surrounding context.

python
-H "Content-Type: application/json" \
      -d '{json.dumps({"prompt": prompt})}' > /tmp/cf_response.json'''
    
    subprocess.run(cmd, shell=True)
    
    with open('/tmp/cf_response.json', 'r') as f:
        data = json.load(f)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises executable behavior via a Python script and appears to require shell and file-read capabilities, but it does not declare any tool scope or permissions. This creates a least-privilege and review gap: downstream systems or reviewers cannot accurately assess what the skill is allowed to do, increasing the chance of unintended file access or command execution in a broader environment.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The module docstring says this script is a general 'Cloudflare Workers AI Image Generation Script' that 'Generates images' with a model, which conflicts with the skill's documented purpose of generating curated multi-themed food collages. This is an active documentation/code-intent mismatch rather than a mere omission, because the file self-describes a broader generic image generator.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The presence of a hardcoded third-party endpoint confirms outbound network capability to a remote service. In this skill context, that increases risk because a seemingly local content-generation skill actually sends content off-platform, which may expose user inputs and expand the attack surface.

Content

Scanner excerpt · scripts/generate_image.py (reported line 25)May include surrounding context.

python
output_path = f"{prompt.replace(' ', '_')[:30]}.png"
    
    # Call Cloudflare API
    cmd = f'''curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/run/{MODEL}" \
      -H "Authorization: Bearer {TOKEN}" \
      -H "Content-Type: application/json" \
      -d '{json.dumps({"prompt": prompt})}' > /tmp/cf_response.json'''

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The presence of a hardcoded third-party endpoint confirms outbound network capability to a remote service. In this skill context, that increases risk because a seemingly local content-generation skill actually sends content off-platform, which may expose user inputs and expand the attack surface.

Content

Scanner excerpt · scripts/generate_image.py (reported line 25)May include surrounding context.

python
output_path = f"{prompt.replace(' ', '_')[:30]}.png"
    
    # Call Cloudflare API
    cmd = f'''curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/run/{MODEL}" \
      -H "Authorization: Bearer {TOKEN}" \
      -H "Content-Type: application/json" \
      -d '{json.dumps({"prompt": prompt})}' > /tmp/cf_response.json'''

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

The script constructs a shell command using attacker-controlled input derived from the prompt and executes it with shell=True. Although json.dumps escapes double quotes for JSON, the payload is embedded inside single quotes in the shell command, so a prompt containing a single quote can break out of the quoted context and trigger command injection.

Content

Scanner excerpt · scripts/generate_image.py (reported line 30)May include surrounding context.

python
-H "Content-Type: application/json" \
      -d '{json.dumps({"prompt": prompt})}' > /tmp/cf_response.json'''
    
    subprocess.run(cmd, shell=True)
    
    with open('/tmp/cf_response.json', 'r') as f:
        data = json.load(f)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script writes API output to /tmp/cf_response.json and writes the generated image to an output file path, but it only informs the user after completion. There is no prior warning or confirmation that local files will be created or overwritten as part of execution.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The comment on L82 states the key label is drawn outside the top-left of the image. However, the actual coordinates on L83 use (x - 40, y - 40) while the image occupies a 300x300 area, so the text begins 40 pixels above and left of the image origin and extends into the image region rather than clearly outside it; this contradicts the stated intent of the comment.

Content

No source excerpt is available for this finding.