T09 · Insecure Skill Coding Practices
- Location
- scripts/alphafold_agent.py:38
- Finding
- Predictable Output Files Permit Local File Overwrite Through Symbolic Links<![CDATA[ ## Vulnerability Details **File Location**: `scripts/alphafold_agent.py:38-39`, `scripts/alphafold_agent.py:51-52`, and `scripts/alphafold_agent.py:68-70` **Vulnerability Type**: Unsafe predictable output files and symbolic-link following **Risk Level**: Medium ### Vulnerable Code ```python with open(f'{pdb_id}.pdb', 'w') as f: f.write(requests.get(pdb_url).text) ``` ```python with open('esm_fold.pdb', 'w') as f: f.write(pdb_mock) ``` ```python with open('docked.png', 'wb') as f: img = Draw.MolToImage(ligand) img.save(f, format='PNG') ``` ### Technical Analysis The script writes results to predictable filenames in its current working directory. The files are opened in truncating write mode without checking whether the destination already exists, is a symbolic link, or points outside an intended output directory. The fixed names `esm_fold.pdb` and `docked.png` are especially susceptible to pre-creation attacks. The downloaded PDB filename is less predictable but is still derived from a public remote identifier and is opened using the same unsafe pattern. On systems where an attacker can write to the working directory, Python follows a pre-existing symbolic link when these files are opened. The target is then truncated and replaced using the privileges of the process running the Skill. ### Attack Path 1. An attacker obtains write access to the directory from which the Skill will run. 2. The attacker creates a symbolic link such as: - `esm_fold.pdb` pointing to another file writable by the victim process; or - `docked.png` pointing to another file writable by the victim process. 3. The user invokes the Skill: - An unsuccessful RCSB lookup triggers `predict_esmfold()` and writes `esm_fold.pdb`; or - A query containing a SMILES value triggers `dock_ligand()` and writes `docked.png`. 4. The `open(..., 'w')` or `open(..., 'wb')` call follows the symbolic link. 5. The linked target is truncated and replaced with mock PDB o ...[truncated 529 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Create a private output directory using `tempfile.TemporaryDirectory()` or `tempfile.mkdtemp()` with restrictive permissions. - Generate unpredictable output filenames rather than using fixed names. - Avoid opening attacker-accessible paths with ordinary truncating write modes. - When persistent output is required, use exclusive creation such as mode `x` or low-level flags including `O_CREAT | O_EXCL`. - Verify that output paths remain inside an explicitly configured output directory. - Reject existing symbolic links and verify the opened file with `os.lstat()` or descriptor-based checks where applicable. - Run the Skill under a dedicated, least-privileged account and do not execute it from a shared writable directory. ]]>
