T09 · Insecure Skill Coding Practices
Warning
- Location
- handler.js:47
- Finding
- Predictable, Non-Exclusive Temporary Files Permit Arbitrary File Overwrite## Vulnerability Details **File Location**: `handler.js`, lines 47–57 **Vulnerability Type**: Insecure temporary-file creation **Risk Level**: Medium ### Vulnerable Code ```js const tempDir = os.tmpdir(); const timestamp = Date.now(); const jsxPath = path.join(tempDir, `ps_script_${timestamp}.jsx`); fs.writeFileSync(jsxPath, ctx.params.script); let result; if (isWin) { const vbsPath = path.join(tempDir, `ps_bridge_${timestamp}.vbs`); fs.writeFileSync(vbsPath, VBS_CONTENT); ``` ### Technical Analysis The Skill constructs temporary JSX and VBS paths from `Date.now()`, making their names predictable to another process on the same host. It then creates or truncates these files using `fs.writeFileSync` without exclusive creation. Because the operating-system temporary directory may be shared among users or processes, a local attacker can predict candidate filenames and pre-create symbolic links at those paths. When the Skill writes the temporary content, the write operation can follow the symbolic link and overwrite its target with the privileges of the Agent process. This is a time-of-check/time-of-use-style temporary-file vulnerability; no separate validation step prevents link traversal or an existing path from being reused. ### Attack Path 1. A local attacker monitors the clock and predicts upcoming names such as `ps_script_<timestamp>.jsx` or `ps_bridge_<timestamp>.vbs`. 2. The attacker creates candidate symbolic links in the shared temporary directory before the Skill writes its files. 3. Each symbolic link points to a file the Agent process can modify. 4. A user or automated workflow invokes `runScript`. 5. `fs.writeFileSync` follows the attacker-created link and truncates or overwrites the selected target. 6. Depending on the target, the attacker can cause data loss, configuration manipulation, or execution of attacker-influenced content by another component. The exploit requires ...[truncated 724 chars]
- Remediation
- ## Remediation Suggestions 1. Create a uniquely named private temporary directory with `fs.mkdtempSync(path.join(os.tmpdir(), 'photoshop-automator-'))`. 2. Store the JSX and VBS files inside that private directory using fixed internal names. 3. Create files exclusively with `flag: 'wx'` so existing paths are rejected rather than truncated. 4. Apply restrictive permissions, such as mode `0o600` for files and `0o700` for the directory where supported. 5. Place execution and cleanup in a `try`/`finally` block so all temporary artifacts are removed on success, process-launch failure, or unexpected exceptions. 6. Reject symbolic links or unexpected pre-existing entries if compatibility constraints prevent use of a private directory. 7. Avoid relying on timestamps alone for uniqueness; use operating-system-backed secure temporary creation. Example hardening pattern: ```js const tempRoot = fs.mkdtempSync( path.join(os.tmpdir(), 'photoshop-automator-') ); try { const jsxPath = path.join(tempRoot, 'script.jsx'); fs.writeFileSync(jsxPath, ctx.params.script, { flag: 'wx', mode: 0o600 }); // Create the bridge with the same exclusive and restrictive options. // Execute Photoshop automation here. } finally { fs.rmSync(tempRoot, { recursive: true, force: true }); } ```
