Back to skill

Security audit

3d Print Model Splitting

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its 3D-printing purpose, but review is warranted because some helper scripts can overwrite files outside the intended project folders if given path-like part names.

Install only if you are comfortable reviewing the helper script arguments before use. Keep work in a disposable project folder, run Blender helpers in a fresh/background session, avoid path separators or absolute paths in part names and filenames, and do not run the scripts with elevated privileges.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/split_by_material.py:265
Finding

Path Traversal Through Unvalidated Output Slug

Content
View full analysis

Vulnerability Details

File Location: scripts/split_by_material.py, lines 38-44 and 265-266
Vulnerability Type: Path traversal and arbitrary file overwrite
Risk Level: Medium

Vulnerable Code

python
def parse_parts(specs):
    out = []
    for spec in specs:
        if '=' not in spec:
            raise SystemExit(f'Bad --part spec {spec!r}; expected MATERIAL=slug')
        mat, slug = spec.split('=', 1)
        out.append((mat, slug))
    return out
python
stl = os.path.join(args.outdir, slug + '.stl')
export_binary_stl(obj, stl)

Technical Analysis

The slug component of each --part MATERIAL=slug argument is used as part of an output path without validation. The code does not reject absolute paths, parent-directory components such as .., or path separators.

os.path.join() does not guarantee that the resulting path remains beneath args.outdir. Parent-directory components can escape the intended output directory, and an absolute slug can cause the base directory to be discarded entirely.

The resulting path is passed to export_binary_stl(), which opens the path in binary write mode. Consequently, the script can create or overwrite an accessible file outside the selected output directory.

Attack Path

  1. An attacker or untrusted automation influences a --part argument passed to the Blender script.

  2. The supplied output slug contains traversal components or an absolute path, for example:

    text
    --part PART_01_HAT=../../outside/result
    
  3. The parser accepts the value without checking its path semantics.

  4. os.path.join(args.outdir, slug + '.stl') resolves to a location outside the intended output directory.

  5. export_binary_stl() writes generated STL data to that location.

  6. If the destination already exists and is writable, it is overwritten.

Exploitation requires the attacker to influence script arguments and is lim ...[truncated 592 chars]

Remediation
View remediation

Remediation Suggestions

  • Restrict output slugs to a conservative filename pattern, such as:

    python
    import re
    
    if not re.fullmatch(r'[A-Za-z0-9][A-Za-z0-9._-]*', slug):
        raise SystemExit(f'Invalid output slug: {slug!r}')
    
  • Explicitly reject empty values, absolute paths, .. components, and both POSIX and Windows path separators.

  • Resolve and verify the final destination before writing:

    python
    base = os.path.realpath(args.outdir)
    candidate = os.path.realpath(os.path.join(base, slug + '.stl'))
    
    if os.path.commonpath([base, candidate]) != base:
        raise SystemExit('Output path escapes the configured output directory')
    
  • Consider rejecting existing destination files by default or requiring an explicit overwrite option.

  • Add tests for ../name, absolute paths, Windows-style separators, empty slugs, nested paths, symbolic-link escapes, and valid simple slugs.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/apply_interface_clearance.py:141
Finding

Arbitrary Mesh File Read and Write Through Unvalidated Part Filename

Content
View full analysis

Vulnerability Details

File Location: scripts/apply_interface_clearance.py, lines 35-42, 112-114, and 139-142
Vulnerability Type: Path traversal allowing unintended file access and overwrite
Risk Level: Medium

Vulnerable Code

python
def parse_key_value(items, flag):
    out = {}
    for item in items:
        if '=' not in item:
            raise SystemExit(f'Bad {flag} {item!r}; expected key=value')
        k, v = item.split('=', 1)
        out[k] = v
    return out
python
parts = {}
for key, filename in part_files.items():
    path = os.path.join(args.input_dir, filename)
    parts[key] = orient(trimesh.load(path, force='mesh', process=True))
python
output_files = {}
for key, filename in part_files.items():
    out = os.path.join(args.outdir, filename)
    parts[key].export(out)
    output_files[key] = out

Technical Analysis

Values supplied through --part key=filename are used for both input and output path construction without filename validation or containment checks.

A filename containing .. can escape args.input_dir when the mesh is loaded and escape args.outdir when the processed mesh is exported. If the supplied filename is absolute, os.path.join() ignores the configured base directory.

Although trimesh.load(..., force='mesh') limits useful input to data that the library can interpret as a mesh, the script can still access unintended mesh files available to the current process. More importantly, parts[key].export(out) can overwrite an unintended writable destination with generated mesh data.

Attack Path

  1. An attacker influences a --part argument, such as:

    text
    --part body=../../shared/model.stl
    
  2. parse_key_value() accepts the filename without rejecting traversal components.

  3. The input path escapes --input-dir, allowing the script to attempt to load an unintended mesh file.

  4. Af ...[truncated 1017 chars]

Remediation
View remediation

Remediation Suggestions

  • Treat every filename from --part as an untrusted basename.

  • Reject absolute paths and require:

    python
    if filename != os.path.basename(filename):
        raise SystemExit(f'Part filename must be a basename: {filename!r}')
    
  • Allow only expected STL filenames with a conservative character policy and a case-insensitive .stl extension.

  • Independently verify input and output containment using canonical paths and os.path.commonpath().

  • Resolve the configured base directories before processing and account for symbolic links when enforcing containment.

  • Use distinct input and output names rather than automatically reusing an untrusted input filename for export.

  • Refuse to overwrite existing output files unless the caller supplies an explicit overwrite flag.

  • Add regression tests covering relative traversal, absolute paths, mixed path separators, symbolic-link escapes, malformed extensions, and normal STL basenames.

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

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description centers on 3D model preparation and validation for multipart printing and assembly. The provided code does not manipulate STL files, meshes, CAD/3D-print data, or assembly interfaces. Instead, it only creates a labeled contact sheet from preview PNGs. That is a materially different primary purpose and an unrelated capability compared with the declared skill behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description presents a broad multipart 3D-model splitting and assembly-preparation skill, with workflows spanning STL splitting, Blender/Bambu integration, geometry repair, fit/interface adjustment, and assembly validation. The supplied code only validates mesh objects inside a 3MF archive and reports geometric/manifold-style statistics plus warnings about unsupported 3MF constructs. While '3MF object validation' is one small element mentioned in the description, the implemented behavior is much narrower and materially different from the stated primary purpose. Therefore this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill declares file read/write-capable behavior but does not define any explicit tool scope or permissions boundaries. In an agent environment, missing scope declarations can lead to broader-than-necessary filesystem access, increasing the chance of unintended file exposure or overwrite if the skill is invoked on untrusted tasks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script unconditionally selects and deletes all objects in the currently open Blender scene before importing STL files. If run against an unsaved or user-populated scene, this causes destructive data loss outside the intended imported workspace, and the skill context does not guarantee isolation unless Blender is always launched on a fresh temporary file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code deletes all existing objects in the current Blender scene and then saves a new mainfile to the requested output path. While the module docstring describes the script's purpose, it does not explicitly warn users about the destructive scene reset or the file-writing behavior, and there is no runtime confirmation or user-facing disclosure before these actions occur.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The usage examples on L07-L08 use Chinese-only labels, and the note on L12 plus font choices on L34-L36 suggest the script is oriented toward a Chinese locale. Because there is no natural-language statement that this is region-specific or that users may choose their own language/labels, this can be read as a locale preference baked into the skill without opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.