Back to skill

Security audit

CAD

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate CAD generation and inspection skill, with expected but important risks from running local CAD generator code and installing unpinned dependencies.

Install and run this in a project-scoped virtual environment or container, pin dependencies if reproducibility matters, and only run CAD Python generators or .step.js sidecars from sources you trust. Expect it to create or update STEP files, hidden GLB/topology artifacts, snapshots, and requested mesh sidecars in the project. Avoid non-default render themes in restricted/offline environments unless you accept the remote HDRI image fetches.

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

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependencies Permit Unreviewed Supply-Chain Changes

Content
View full analysis
=68"] build-backend = "setuptools.build_meta" [project] name = "cadpy" version = "0.3.5" description = "Shared STEP/GLB topology artifact generation runtime for CAD skills." requires-python = ">=3.11" dependencies = [ "build123d", "cadquery-ocp", ] ``` ### Technical Analysis The project does not constrain `playwright`, `build123d`, or `cadquery-ocp` to reviewed versions. Its isolated build environment also accepts any `setuptools` release at or above version 68. Consequently, separate installations performed at different times can resolve materially different code despite using the same project source. Package installation and imports execute third-party code under the installing or running user's account. If an upstream package, maintainer account, build pipeline, or package distribution channel is compromised, a subsequently published release could be selected without any change to this repository. No dependency was confirmed to be malicious during this static audit. The vulnerability is the absence of version and integrity controls, which leaves future dependency selection outside the reviewed source boundary. ### Attack Path 1. An attacker compromises an upstream dependency release process, maintainer account, or package distribution channel for one of the unconstrained packages. 2. The attacker publishes a malicious version that still satisfies the declarations, such as any version of `playwright`, `build123d`, or `cadquery-ocp`, or a future `setuptools` version greater than or equal to 68. 3. A user or ...[truncated 1103 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for a high-level CAD skill centered on STEP-first parametric modeling, inspection, validation, and export workflows. The actual code shown is not CAD logic; it is rendering/runtime infrastructure, apparently a bundled Three.js-based snapshot renderer. It defines graphics primitives, WebGL state management, shader compilation, textures, environment mapping, clipping, uniforms, PMREM generation, and rendering helpers. This could plausibly support the 'snapshots' or GLB visualization portion of a CAD tool, so it is related as a supporting component. However, taken on its own, the chunk does not implement the declared primary capabilities such as STEP manipulation, CAD part/assembly creation, parametric editing, inspection, validation, or export to CAD formats. Therefore the code chunk's actual behavior is materially narrower and different from the declared purpose, making this a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises a CAD-focused skill centered on STEP-first parametric part and assembly creation, modification, inspection, validation, measurement, and export. The supplied code instead consists of low-level graphics/rendering infrastructure: shader materials, perspective and cube cameras, render targets, cubemap conversion, lighting models, shadows, UV handling, transmission, depth packing, tone mapping, and related GLSL shader fragments. This is consistent with a snapshot/rendering subsystem, likely for visualizing scenes, not with a CAD engine or STEP-processing tool. While rendering could be a supporting detail for CAD snapshots, this chunk shows only rendering behavior and does not demonstrate the core declared CAD capabilities. Therefore the code chunk materially differs from the declared primary purpose.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/packages/cadpy/src/cadpy/catalog.py (reported line 24)May include surrounding context.

python
"__pycache__",
    ".cache",
    ".eggs",
    ".env",
    ".git",
    ".hg",
    ".mypy_cache",

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/snapshot/runtime/snapshot-render.js (reported line 182)May include surrounding context.

js
points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"};function y(S){return S===0?"uv":`uv${S}`}function g(S,M,N,U,G){let P=U.fog,D=G.geometry,z=S.isMeshStandardMaterial?U.environment:null,X=(S.isMeshStandardMaterial?t:e).get(S.envMap||z),q=X&&X.mapping===_o?X.image.height:null,Y=m[S.type];S.precision!==null&&(d=r.getMaxPrecision(S.precision),d!==S.precision&&console.warn("THREE.WebGLProgram.getParameters:",S.precision,"not supported, using",d,"instead."));let j=D.morphAttributes.position||D.morphAttributes.normal||D.morphAttributes.color,J=j!==void 0?j.length:0,le=0;D.morphAttributes.position!==void 0&&(le=1),D.morphAttributes.normal!==void 0&&(le=2),D.morphAttributes.color!==void 0&&(le=3);let W,Q,ue,xe;if(Y){let an=rn[Y];W=an.vertexShader,Q=an.fragmentShader}else W=S.vertexShader,Q=S.fragmentShader,c.update(S),ue=c.getVertexShaderID(S),xe=c.getFragmentShaderID(S);let he=n.getRenderTarget(),Ce=G.isInstancedMesh===!0,De=G.isBatchedMesh===!0,ve=!!S.map,Ue=!!S.matcap,L=!!X,ae=!!S.aoMa

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill describes workflows that require command execution, filesystem access, and potentially external component lookup, but it does not declare any explicit tool scope or permissions boundaries. In practice, this creates an overbroad trust surface where an agent may use ambient capabilities such as file, environment, or network access without a least-privilege contract, increasing the risk of unintended file access, data leakage, or unsafe command use.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/cad-brief.md (reported line 3)May include surrounding context.

md
# CAD brief

Read this file when converting a user's request — prose, reference images, technical drawings, or a combination — into a CAD brief. The brief is an internal note-taking scaffold; do not ask the user to fill it out, and do not require the user to provide JSON. If the user supplied JSON voluntarily, extract the same information but continue the workflow in prose notes and build123d source.

## Goal

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code dynamically loads and executes the Python assembly file via importlib and then calls its gen_step() function. Because the loaded file is treated as executable code rather than inert data, any untrusted or user-supplied assembly spec can run arbitrary Python with the privileges of the current process, which can lead to code execution, file access, network access, or environment compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code path performs dynamic module loading and execution without any visible warning, consent gate, or trust check in the file itself. In a CAD skill that may process externally provided parts and assemblies, silent execution increases the chance that operators treat assembly files as data and unknowingly trigger arbitrary code execution.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

_load_generator_module() imports Python files from CAD sources via importlib and executes module top-level code during import. In this skill context, CAD source files are treated as inputs, so loading them grants arbitrary code execution with the privileges of the current process, which is broader and riskier than pure CAD parsing/inspection.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

After loading the module, the code directly calls gen_step() or gen_dxf() from the untrusted script. That function can perform arbitrary filesystem, subprocess, or network actions, so invoking it turns a CAD generation request into arbitrary code execution under the tool's privileges.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The execution point runs untrusted generator code with no explicit user-facing warning at that moment, so users may believe they are only generating CAD artifacts when they are actually executing arbitrary Python. This increases the chance of unsafe use and makes harmful side effects less foreseeable.

Content

No source excerpt is available for this finding.

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · scripts/packages/cadpy/src/cadpy/generation_status.py (reported line 101)May include surrounding context.

python
def _finish(self) -> None:
        self._stop.set()
        if self._thread is not None:
            self._thread.join(timeout=0.25)
        for status_path in self.status_paths:
            try:
                status_path.unlink()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

When the requested STEP target does not exist as a file, the code automatically falls back to locating a sibling Python file and, for generated sources, executes it via run_script_generator() to produce CAD scene data. In a CAD automation skill that processes repository files and user-selected targets, this creates an implicit code-execution path from file selection to Python execution without an explicit trust boundary or user-facing confirmation, which is dangerous if an attacker can introduce or influence CAD generator scripts in the workspace.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The bundled renderer contains hard-coded remote environment texture URLs and fetches them at runtime. That creates an external network dependency from a local rendering workflow, enabling privacy leakage, tracking, nondeterministic renders, SSRF-like policy bypass in restricted environments, and supply-chain risk if the remote assets change or are compromised.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency playwright is unpinned, so installs may resolve to different versions over time, reducing build reproducibility and potentially pulling in a newly introduced vulnerable or breaking release. In a skill that processes external inputs and may automate browser behavior, supply-chain drift is undesirable even if this file alone does not prove exploitation.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
--editable ./scripts/packages/cadpy
playwright

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module aliases ensure_step_topology_artifact and validate_step_topology_artifact as ensure_step_glb_artifact and validate_step_glb_artifact, then exports those GLB-named symbols. This documentation-by-API-surface suggests GLB artifact handling, while the actual implementation references STEP topology artifacts, creating an intent-level contradiction for callers.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/packages/cadpy/src/cadpy/assembly.py (reported line 282)May include surrounding context.

python
def add_joint_frame(part: Any, name: str, *, joint_type: str, **joint_options: Any) -> MateTarget:
    build123d = _import_build123d()
    joint_cls = getattr(build123d, joint_type)
    label = mate_label(name)
    joint_cls(
        label=label,

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/packages/cadpy/src/cadpy/assembly.py (reported line 368)May include surrounding context.

python
payload["orientation"] = orientation
    axes: dict[str, list[float]] = {}
    for axis_name, payload_key in (("x_axis", "x"), ("y_axis", "y"), ("z_axis", "z")):
        axis = getattr(location, axis_name, None)
        direction = _vector_payload(getattr(axis, "direction", None))
        if direction is not None:
            axes[payload_key] = direction

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/packages/cadpy/src/cadpy/assembly.py (reported line 383)May include surrounding context.

python
components: list[Any] = []
    for attr in ("X", "Y", "Z"):
        if hasattr(value, attr):
            components.append(getattr(value, attr))
    if len(components) != 3:
        for attr in ("x", "y", "z"):
            if hasattr(value, attr):

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/packages/cadpy/src/cadpy/assembly.py (reported line 387)May include surrounding context.

python
components: list[Any] = []
    for attr in ("X", "Y", "Z"):
        if hasattr(value, attr):
            components.append(getattr(value, attr))
    if len(components) != 3:
        for attr in ("x", "y", "z"):
            if hasattr(value, attr):

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

This function creates parent directories and writes a DXF file plus metadata, but only emits a debug-level log after the write completes. If verbose/debug logging is disabled, users may not receive any immediate disclosure from this code path that disk contents are being created or modified.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/packages/cadpy/src/cadpy/generation.py (reported line 1088)May include surrounding context.

python
generated_scene: LoadedStepScene | None = None
    with logger.timed(f"load generator {spec.source_ref}"):
        module = _load_generator_module(spec.script_path)
    generator = getattr(module, generator_name, None)
    if not callable(generator):
        raise RuntimeError(f"{_display_path(spec.script_path)} does not define callable {generator_name}()")
    with logger.timed(f"run {generator_name} {spec.source_ref}"):

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This function writes modified STEP content back to the provided path, changing user files in place. In this file there is no confirmation prompt, logging/print statement, or explanatory comment/docstring warning that the function mutates the target file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The tail-injection path opens the STEP file in read/write binary mode, overwrites content, and truncates the file, which is a safety-relevant file modification. This code path has no visible confirmation, logging, or inline documentation warning users that it performs an in-place rewrite.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/packages/cadpy/src/cadpy/assembly_spec.py:243

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/packages/cadpy/src/cadpy/generation.py:738