T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/tts-converter.js:19
- Finding
- Unsafe Shared Temporary Directory for Generated Audio## Vulnerability Details **File Location**: `scripts/tts-converter.js`, lines 19, 52–72, and 126–129 **Vulnerability Type**: Unsafe temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```javascript const TEMP_DIR = path.join(os.tmpdir(), 'edge-tts-temp'); ``` ```javascript async function ensureTempDir() { try { await fs.access(TEMP_DIR); } catch (error) { await fs.mkdir(TEMP_DIR, { recursive: true }); } } /** * Generate unique temporary file path * @param {string} extension - File extension (e.g., '.mp3') * @returns {string} Temporary file path */ function generateTempPath(extension = '.mp3') { const timestamp = Date.now(); const random = Math.random().toString(36).substring(2, 8); const filename = `tts_${timestamp}_${random}${extension}`; return path.join(TEMP_DIR, filename); } ``` ```javascript // Ensure temp directory exists and use temp file if no output path specified await ensureTempDir(); const finalOutputPath = outputPath || generateTempPath('.mp3'); ``` ### Technical Analysis The application stores generated audio in a fixed directory under the operating system's shared temporary directory. It checks only whether that path is accessible; it does not verify that the directory is owned by the current user, has restrictive permissions, or is not a symbolic link. The `fs.access()` followed by `fs.mkdir()` sequence also introduces a time-of-check/time-of-use window. If the directory already exists, the application accepts it without validating its type or security properties. A local attacker may therefore pre-create or manipulate the shared path before the victim invokes the converter. Temporary filenames combine the current timestamp with six characters generated by `Math.random()`. This is not a cryptographically secure source of randomness. Although exploitation requires local access and successful prediction or racing, monitoring the ...[truncated 1937 chars]
- Remediation
- ## Remediation Suggestions 1. Create a private directory for each invocation using `fs.mkdtemp()` beneath `os.tmpdir()` rather than reusing a global directory. 2. Explicitly restrict the directory to the current user with mode `0700`. 3. Use `crypto.randomUUID()` or `crypto.randomBytes()` instead of `Math.random()` for output names. 4. Validate temporary paths with `fs.lstat()` and reject symbolic links or unexpected filesystem object types. 5. Where possible, create output files atomically with exclusive-create and no-follow semantics. 6. Apply restrictive file permissions such as `0600` to generated audio and subtitle files. 7. Delete temporary files and their per-run directory in a `finally` block after the calling application has delivered or copied the result. 8. If files must persist, require an explicit user-selected output path and document the retention and confidentiality implications. 9. Add tests that pre-create the temporary path as a symbolic link, directory owned by another user, and conflicting output file to ensure the converter fails securely.
