T09 · Insecure Skill Coding Practices
- Location
scripts/tts-converter.js:19- Finding
Unsafe Shared Temporary Directory for Generated Audio
- Content
View full analysis
Vulnerability Details
File Location:
scripts/tts-converter.js, lines 19, 52–72, and 126–129
Vulnerability Type: Unsafe temporary-file handling
Risk Level: MediumVulnerable 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 byfs.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
View remediation
Remediation Suggestions
- Create a private directory for each invocation using
fs.mkdtemp()beneathos.tmpdir()rather than reusing a global directory. - Explicitly restrict the directory to the current user with mode
0700. - Use
crypto.randomUUID()orcrypto.randomBytes()instead ofMath.random()for output names. - Validate temporary paths with
fs.lstat()and reject symbolic links or unexpected filesystem object types. - Where possible, create output files atomically with exclusive-create and no-follow semantics.
- Apply restrictive file permissions such as
0600to generated audio and subtitle files. - Delete temporary files and their per-run directory in a
finallyblock after the calling application has delivered or copied the result. - If files must persist, require an explicit user-selected output path and document the retention and confidentiality implications.
- 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.
- Create a private directory for each invocation using
