Back to skill

Security audit

3D Molecule Ray-tracer

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent molecular-rendering purpose, but Review is warranted because its script generator can overwrite arbitrary writable paths and embeds unvalidated inputs into generated PyMOL/ChimeraX commands despite claiming workspace restrictions.

Review before installing or running. Use only trusted molecular inputs, keep output filenames simple and inside the current project directory, and inspect generated .pml or .cxc files before opening them in PyMOL or ChimeraX. The publisher should add strict validation, command escaping, output-path containment, and overwrite protection before this is treated as low-risk.

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

Error
Location
scripts/main.py:154
Finding

Unescaped User Input Enables Command Injection in Generated Rendering Scripts

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py:154-160, scripts/main.py:283-295, scripts/main.py:412-417, scripts/main.py:480-494, and scripts/main.py:514-535
Vulnerability Type: Command injection through generated PyMOL and ChimeraX scripts
Risk Level: High

Vulnerable Code

python
def _generate_load(self) -> List[str]:
    """Generate structure loading commands."""
    pdb = self.config['pdb']
    lines = ["# Load structure"]
    
    # Check if PDB ID or file path
    if len(pdb) == 4 and pdb.isalnum() and not Path(pdb).exists():
        lines.append(f"fetch {pdb}, async=0")
    else:
        lines.append(f"load {pdb}")
    
    lines.append("")
    return lines
python
else:
    # Specific residue
    lines.extend([
        f"# Focus on {dof_focus}",
        f"select dof_target, {dof_focus}",
        "center dof_target",
        "set dof_focus, 0",
    ])
python
def _generate_load(self) -> List[str]:
    """Generate structure loading commands."""
    pdb = self.config['pdb']
    lines = ["# Load structure"]
    
    if len(pdb) == 4 and pdb.isalnum() and not Path(pdb).exists():
        lines.append(f"open {pdb}")
    else:
        lines.append(f"open {pdb}")
    
    lines.append("")
    return lines
python
dof_focus = self.config.get('dof_focus', 'center')
if dof_focus == "center":
    lines.append("# Focus on center (default)")
elif dof_focus != "selection":
    lines.extend([
        f"# Focus on {dof_focus}",
        f"select {dof_focus}",
        "view selection",
    ])
python
def _generate_render(self) -> List[str]:
    """Generate render and save commands."""
    resolution = self.config.get('resolution', 2400)
    output = self.config.get('output', 'output.png')
    
    # Change extension if needed
    if output.endswith('.cxc'):
        output = output.rep
...[truncated 3332 chars]
Remediation
View remediation

Remediation Suggestions

  1. Define strict allow-list grammars for every value embedded in generated commands:
    • Accept remote PDB identifiers only when they match a precise pattern such as ^[A-Za-z0-9]{4}$.
    • Validate residue selectors against a documented, minimal selector grammar.
    • Restrict background colors to known color names or validated numeric color formats.
  2. Reject carriage returns, line feeds, null bytes, quotes, and target-language command delimiters in all command-bound values.
  3. Use target-specific quoting and escaping functions for local input and output paths. Do not rely on generic shell quoting because PyMOL and ChimeraX use their own command syntaxes.
  4. Keep the script output filename separate from the rendered image filename. Validate each independently and enforce the expected extension.
  5. Prefer APIs or structured script-generation interfaces over concatenating command strings where the target software supports them.
  6. Add automated tests using values containing newlines, quotes, spaces, separators, and Unicode control characters. Generation must either escape them safely or fail closed.
  7. Clearly indicate whether a generated script can perform network access, particularly when a remote PDB identifier produces fetch or open.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:615
Finding

Unrestricted Output Path Allows Arbitrary File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py:615-649
Vulnerability Type: Path traversal and unrestricted file overwrite
Risk Level: Medium

Vulnerable Code

python
# Output
parser.add_argument("--output", default=None,
                    help="Output script filename (default: auto-generated)")
python
# Generate output filename
if args.output is None:
    ext = ".pml" if args.software == "pymol" else ".cxc"
    args.output = f"{args.preset}_render{ext}"
config['output'] = args.output
python
script = renderer.generate_script()

# Save script
output_path = Path(args.output)
output_path.write_text(script)

Technical Analysis

The --output value is converted directly to a Path and passed to write_text() without constraining it to a designated workspace. Absolute paths and paths containing parent-directory components such as .. are accepted.

Path.write_text() opens an existing destination for replacement, so a writable file can be overwritten with generated script content. No extension enforcement, canonical-path containment check, exclusive creation mode, or overwrite confirmation is present.

This behavior contradicts the statements in SKILL.md that input paths are validated and the output directory is restricted to the workspace. The implementation does not provide either protection.

Attack Path

  1. An attacker controls or influences the --output argument.
  2. The attacker supplies an absolute path or a relative path containing .. that resolves outside the intended project directory.
  3. The selected destination already exists and is writable by the user running the Skill.
  4. Path(args.output).write_text(script) opens the destination and replaces its contents.
  5. The original file is lost or altered, potentially disrupting another application or project workflow.

Impact Assessment

The vulnerability permits creati ...[truncated 440 chars]

Remediation
View remediation

Remediation Suggestions

  1. Establish an approved output root and resolve the requested path against it:
    python
    output_root = Path.cwd().resolve()
    output_path = (output_root / args.output).resolve()
    if output_path.parent != output_root:
        raise ValueError("Output must remain in the workspace root")
    
    If subdirectories are allowed, use a robust containment check such as output_path.is_relative_to(output_root) on supported Python versions.
  2. Reject absolute paths and any path that resolves outside the approved workspace.
  3. Enforce .pml for PyMOL output and .cxc for ChimeraX output.
  4. Avoid silently overwriting existing files. Use exclusive creation mode or require an explicit --force option.
  5. Keep generated image destinations independently validated and restricted because the script filename is also reused when constructing image-save commands.
  6. Update SKILL.md so its security claims accurately reflect implemented controls.
  7. Add tests for absolute paths, ../ traversal, existing destinations, invalid extensions, and nested output directories.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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 (2)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill documents executable behavior and script generation that writes output files, but it does not declare an explicit tool/permission scope such as allowed-tools or permissions. That omission weakens enforcement and review because an agent may be granted broader file-write capability than the skill actually needs, increasing the chance of unintended or unsafe filesystem effects.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation guidance is broader than the stated purpose, including generic 'data analysis tasks' language unrelated to molecular rendering. Overbroad triggers can cause the wrong skill to be invoked for unrelated requests, exposing users to unnecessary code execution, file writes, or network fetches in contexts where this skill should not run.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.