Back to skill

Security audit

Protein Struct Viz

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it generates executable PyMOL scripts from weakly validated input and can write them to arbitrary paths.

Review generated .pml files before opening them in PyMOL, use only trusted PDB IDs/paths and residue/color inputs, and direct output to a known workspace filename. This skill should add strict input validation and output path containment before broad use.

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
` or the PyMOL `@ <file>` command, as instructed by the application. 6. The injected command runs in the victim's PyMOL process. ### Impact Assessment Successful exploitation permits execution of arbitrary PyMOL commands with the permissions of the user running PyMOL. Depending on the commands and PyMOL features available in the environment, this could enable: - Unauthorized loading, reading, or writing of local files - Unintended network requests - Modification of visualization output or scientific resu ...[truncated 424 chars]:76
Finding

Unvalidated input allows injection into generated PyMOL scripts

Content
View full analysis
Tuple[Optional[str], str, Optional[str]]: """ Parse residue specification. Formats supported: - chain:resnum:resname (A:145:ASP) - chain:resnum (A:145) - resnum (145 - assumes chain A or first chain) Returns: Tuple of (chain, resnum, resname) """ parts = residue_spec.split(":") if len(parts) == 3: return parts[0], parts[1], parts[2] elif len(parts) == 2: return parts[0], parts[1], None elif len(parts) == 1: return None, parts[0], None else: raise ValueError(f"Invalid residue specification: {residue_spec}") def _generate_selection_string(self, chain: Optional[str], resnum: str, resname: Optional[str]) -> str: """Generate PyMOL selection string for a residue.""" parts = [] if chain: parts.append(f"chain {chain}") parts.append(f"resi {resnum}") if resname: parts.append(f"resn {resname}") return " and ".join(parts) def _get_load_command(self) -> str: """Generate structure loading command.""" # Check if pdb_source is a PDB ID (4 characters, alphanumeric) if len(self.pdb_source) == 4 and self.pdb_source.isalnum(): return f"fetch {self.pdb_source}, async=0" else: return f"load {self.pdb_source}" ``` ```python # Header lines.append("# PyMOL script generated by protein-struct-viz") lines.append(f"# Target: {self.pdb_source}") lines.append(f"# Highlighted residues: {', '.join(self.residues)}") lines.append("") # Load structure lines.append("# Load structure") lines.append(self._get_load_command()) lines.append("") ``` ```python # Apply color scheme lines.append("# Color scheme") if self.color_scheme in ...[truncated 3270 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:177
Finding

Unrestricted output path permits arbitrary file overwrite

Content
View full analysis
str: """Generate and save the script to file.""" script_content = self.generate_script() output_path = Path(self.output) output_path.write_text(script_content) return str(output_path.absolute()) ``` ```python parser.add_argument("--output", default="output.pml", help="Output script filename (default: output.pml)") ``` ```python generator = PyMOLScriptGenerator( pdb_source=args.pdb, residues=residue_list, style=args.style, color_scheme=args.color_scheme, output=args.output, ray_trace=args.ray_trace ) ``` ### Technical Analysis The `--output` parameter is passed directly to `Path()` and written with `write_text()`. No validation restricts the destination to the project workspace or another approved output directory. Absolute paths and path traversal sequences are accepted. If the target already exists and is writable, `write_text()` truncates and replaces it. There is also no explicit protection against symbolic-link targets, no required `.pml` extension, and no exclusive-creation behavior. This implementation contradicts the security objective stated in `SKILL.md` that output should be restricted to the workspace. ### Attack Path 1. An attacker controls or influences the `--output` argument. 2. The attacker supplies an absolute path, a path containing traversal components, or a path that resolves through a symbolic link. 3. The process resolves the supplied destination without checking whether it remains inside an approved workspace. 4. `Path.write_text()` creates or truncates the destination. 5. A file writable by the current process is replaced with generated PyMOL content. ### Impact Assessment The vulnerability permits creation or overwrite of arb ...[truncated 583 chars]
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (3)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises file-writing behavior and high-risk execution characteristics, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where an agent or orchestrator may permit broader tool use than intended, increasing the chance of unintended file writes or policy bypass. In this context, generating executable .pml scripts makes the omission more concerning because outputs are meant to be run by another application.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest describes a visualization/script-generation skill, but _get_load_command emits fetch <id> for 4-character inputs, instructing PyMOL to retrieve data from a remote source. Network retrieval is not mentioned in the manifest and is not necessary for a skill framed purely as generating highlighting scripts from provided structures.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The usage text explains that the skill generates .pml files, but it does not prominently warn users that data will be written to disk and later executed by PyMOL. This can lead to unsafe assumptions about side effects, especially in environments where file creation is sensitive or where generated scripts may be trusted and run without review. The bioinformatics context lowers the likelihood of abuse somewhat, but executable script generation still makes transparency important.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.