Back to skill

Security audit

PrintPal 3D Generation

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated 3D/SEO generation purpose, but it has real review-worthy risks around arbitrary file writes, unbounded URL fetching, automatic local file serving, and broad process cleanup.

Review before installing. Do not use this skill with confidential designs unless you are comfortable sending prompts and images to PrintPal, WaveSpeed, and OpenRouter. Avoid URL inputs from untrusted sources, avoid custom filenames, and be aware the SEO workflow starts a localhost download server. Treat the optional Bambu printer commands as hardware-control actions requiring deliberate user confirmation.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/save_image.py:83
Finding

Arbitrary File Write Through Unsanitized Output Filename

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_3d.py:35
Finding

Server-Side Request Forgery and Unbounded Download Through User-Controlled Image URLs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/seo_product_photos.py:73
Finding

Unnecessary Disclosure of Local Filesystem Paths to OpenRouter

Content
View full analysis
dict: """Generate SEO-optimized title, description, and tags using OpenRouter.""" system_prompt = """You are an expert SEO copywriter specializing in 3D printed products for marketplaces like Etsy, TikTok Shop, and similar platforms. Generate compelling, search-optimized metadata that will help products rank well and convert sales. Output ONLY valid JSON, no markdown formatting.""" prompt = f"""Generate SEO-optimized metadata for a 3D print product based on the following information: Image: {image_path} Product Description: {description} Product Purpose/Use: {purpose} Target Audience: {audience} Generate a JSON object with these exact fields: {{ "title": "SEO-optimized product title (max 140 characters, include relevant keywords)", "short_title": "Short catchy title for thumbnails (max 40 characters)", "description": "Detailed product description for listing (500-1000 words, include keywords naturally, highlight features and benefits)", "tags": ["tag1", "tag2", "tag3", "tag4", "tag5", "tag6", "tag7", "tag8", "tag9", "tag10", "tag11", "tag12", "tag13", "tag14", "tag15"], "category": "Primary marketplace category", "search_terms": ["term1", "term2", "term3", "term4", "term5"], "key_features": ["feature1", "feature2", "feature3", "feature4"], "target_marketplace": "Best marketplace for this product" }} Make the title and description compelling for buyers while being optimized for search. Include relevant 3D printing keywords like "3D printed", "STL file", "download", etc. as appropriate.""" result = call_openrouter(prompt, system_prompt) ``` ### Technical Analysis The local `image ...[truncated 1587 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/seo_product_photos.py:301
Finding

Shared Output Directory Exposure and Overbroad Process Termination

Content
View full analysis
subprocess.Popen: """Start HTTP server for file downloads.""" print(f"Starting file server on port {port}...") # Kill any existing server on this port try: subprocess.run(["pkill", "-f", f"serve_files.py.*{port}"], stderr=subprocess.DEVNULL) except: pass # Start new server server_script = os.path.join(os.path.dirname(__file__), "serve_files.py") proc = subprocess.Popen( [sys.executable, server_script, "-d", OUTPUT_DIR, "-p", str(port)], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) ``` The server is started after a package is created for the current session: ```python # Step 3: Create download package print("\n[3/3] Creating download package...") zip_path = create_download_package(session_dir) # Start file server server_proc = start_file_server(args.port) # Get download URL (hostname will need to be adjusted for actual access) import socket hostname = socket.gethostname() download_url = f"http://{hostname}:{args.port}/seo_product_listing.zip" results["download_url"] = download_url ``` ### Technical Analysis The script stores each run under a session-specific subdirectory but starts `serve_files.py` with the shared global `OUTPUT_DIR`. The underlying `SimpleHTTPRequestHandler` serves files recursively and supports directory listings. Any process capable of connecting to the server can therefore enumerate and retrieve prior session directories and their contents, not only the ZIP archive generated by the current invocation. The server binds to localhost by default, which limits remote exposure, but it still permits access by other applications and users with applicable local network acc ...[truncated 1801 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:24
Finding

Unpinned Third-Party Dependencies and Global CLI Installation

Content
View full analysis
` ``` ### Technical Analysis The installation commands do not pin reviewed package versions, verify hashes, use a lockfile, or constrain installation to an isolated environment. As a result, the code installed during future Skill setup can differ from the code that was originally reviewed. Python and npm packages can execute code during installation and at runtime. The imported PrintPal and WaveSpeed clients also operate in a process that has access to their corresponding API credentials and user-selected files. A compromised or unexpectedly changed package release could therefore access those resources. Installing `@versatly/bambu` globally unnecessarily broadens installation scope and makes the executable available across projects. No evidence was found that the listed packages are currently malicious; the issue is the unsafe, non-reproducible dependency acquisition process. ### Attack Path 1. A user follows the documented unpinned `pip install` or global `npm install` commands. 2. The package registry resolves the latest matching release at installation time. 3. A compromised maintainer account, malicious future release, registry compromise, or package-name takeover supplies altered code. 4. Installation hooks or imported runtime code execute with the installing user's privileges. 5. The dependency can access environ ...[truncated 795 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (20)

Tainted flow: 'headers' from os.environ.get (line 49, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/seo_product_photos.py (reported line 63)May include surrounding context.

python
}
    
    print("Calling OpenRouter MiniMax API...")
    response = requests.post(OPENROUTER_API_URL, headers=headers, json=data, timeout=60)
    response.raise_for_status()
    
    result = response.json()

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

This finding indicates the skill framing does not align with the apparent runtime behavior: it is presented as a 3D model generator, but the analyzed content suggests other functions such as serving downloadable files and using OpenRouter for SEO metadata. Such description-behavior gaps are a real security issue because users may authorize the skill for one purpose while it performs additional networked or exposed operations not clearly disclosed.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

This finding indicates the skill framing does not align with the apparent runtime behavior: it is presented as a 3D model generator, but the analyzed content suggests other functions such as serving downloadable files and using OpenRouter for SEO metadata. Such description-behavior gaps are a real security issue because users may authorize the skill for one purpose while it performs additional networked or exposed operations not clearly disclosed.

Content

No source excerpt is available for this finding.

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 247)May include surrounding context.

md
## Prerequisites

- Printer must have **Developer Mode** enabled (Settings → LAN Only → Enable Developer Mode)
- Required info: printer IP address, serial number, LAN access code (shown on the touchscreen)
- CLI tool: `@versatly/bambu` installed globally (`npm i -g @versatly/bambu`)

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · references/bambu-printer-guide.md (reported line 7)May include surrounding context.

md
## Prerequisites

- Printer must have **Developer Mode** enabled (Settings → LAN Only → Enable Developer Mode)
- Required info: printer IP address, serial number, LAN access code (shown on the touchscreen)
- CLI tool: `@versatly/bambu` installed globally (`npm i -g @versatly/bambu`)

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
75% confidence
Finding

Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Content

Scanner excerpt · references/bambu-printer-guide.md (reported line 123)May include surrounding context.

md
## Troubleshooting

- **Connection timeout** → Developer Mode enabled? Correct IP? Printer powered on?
- **Auth failed** → Re-check the LAN access code (it changes if Developer Mode is toggled off/on)
- **FTP error** → Port 990 with implicit TLS; printer must be in LAN-only mode
- **No AMS data** → Verify AMS is physically connected and detected on the touchscreen

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents capabilities that require shell execution, network access, environment variables, and file read/write, but it does not declare any explicit tool scope such as permissions or allowed-tools. That increases the chance an agent runtime will grant broader access than users expect, making risky operations like downloading URLs, serving files, or invoking external CLIs less transparent and less constrained.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends raw user prompt text to the external WaveSpeed API to generate an image, but it does not clearly disclose to the user that their text will leave the local environment and be processed by a third party. In a skill that may be used with proprietary product ideas, personal data, or confidential descriptions, this creates a real privacy and data-governance risk even though the transmission is functionally required for the feature.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script uploads user-supplied image files to the external PrintPal API in order to generate a 3D model, but it does not explicitly disclose that local files may be transmitted to a third-party service. This is a meaningful privacy and confidentiality issue because users may provide private designs, customer assets, or sensitive images assuming processing is local.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The script description understates the behavior by saying it provides a download URL, while the implementation actually launches an HTTP server that exposes generated artifacts. That mismatch reduces informed consent and makes the network exposure more dangerous in an agent setting where users may not expect local services to be opened.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/seo_product_photos.py (reported line 63)May include surrounding context.

python
}
    
    print("Calling OpenRouter MiniMax API...")
    response = requests.post(OPENROUTER_API_URL, headers=headers, json=data, timeout=60)
    response.raise_for_status()
    
    result = response.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

User-supplied description, purpose, audience, and image reference are sent to OpenRouter without an explicit privacy warning or opt-in beyond progress logs. In this skill context, users may provide proprietary designs or sensitive product concepts, so silent third-party transmission creates a meaningful data-disclosure risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

When a local file path is provided, the script may upload the image to WaveSpeed to obtain a URL, but this behavior is only mentioned in logs after execution begins. Uploading local images to a third party without explicit warning is dangerous because input files may contain private designs, copyrighted material, or metadata users did not intend to disclose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script starts and manages a local HTTP server to expose generated files over the network, which is beyond the minimally necessary behavior for generating SEO text and images. In a skill environment this creates unintended network exposure of artifacts and potentially any misconfigured served directory contents.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Using pkill introduces host-level process-control behavior unrelated to the advertised listing-generation function. This can interfere with unrelated services and is especially risky in shared or multi-tenant environments where broad process matching may cause denial of service.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
87% confidence
Finding

The script runs pkill with a pattern derived from the port and suppresses errors, which can terminate unintended matching processes on the host. In an agent skill context, killing processes is unrelated to core content generation and can disrupt other workloads or be abused if port selection is influenced by a user.

Content

Scanner excerpt · scripts/seo_product_photos.py (reported line 307)May include surrounding context.

python
# Kill any existing server on this port
    try:
        subprocess.run(["pkill", "-f", f"serve_files.py.*{port}"], stderr=subprocess.DEVNULL)
    except:
        pass

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/seo_product_photos.py (reported line 314)May include surrounding context.

python
# Start new server
    server_script = os.path.join(os.path.dirname(__file__), "serve_files.py")
    
    proc = subprocess.Popen(
        [sys.executable, server_script, "-d", OUTPUT_DIR, "-p", str(port)],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script automatically starts an HTTP server exposing generated output and then prints a URL, without clearly warning the user that files will be network-accessible. In environments where hostname resolution or interface binding is broad, this can unintentionally share generated artifacts beyond the local machine.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file includes instructions for exporting a live API key into an environment variable, which affects credential handling and could expose secrets through shell history, process inspection, or accidental sharing. The documentation provides no user-facing warning about protecting the key or avoiding committing or logging it.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The markdown instructs users to export an API key but does not disclose any privacy or security implications of storing and using the credential. Because this is documentation for handling secrets, a basic warning is warranted to reduce the risk of accidental exposure.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.