T09 · Insecure Skill Coding Practices
- Location
src/speech-synthesizer.js:255- Finding
Unrestricted cleanup can delete unrelated files
- Content
View full analysis
maxAge) { await fs.unlink(filePath); } } } catch (error) { console.warn('Cleanup failed:', error); } } ``` ### Technical Analysis The constructor accepts an arbitrary writable directory as `outputDir`. The `cleanup()` method then enumerates that directory and deletes every entry older than the supplied threshold. It does not verify that: - The directory is a dedicated TTS output directory. - The target path is inside an approved application-owned root. - The file was created by this component. - The filename follows the generated TTS naming convention. - The target is a regular file rather than a symbolic link or another unexpected entry. The caller also controls `maxAge`. A value such as `0` makes virtually every existing file eligible for deletion. ### Attack Path 1. An attacker or untrusted configuration source sets `outputDir` to a sensitive writable directory. 2. The application constructs `SpeechSynthesizer` with that configuration. 3. The attacker or another reachable application path invokes `cleanup(0)`. 4. The method enumerates the configured directory. 5. Each eligible entry is passed to `fs.unlink()` without confirming that it is a generated TTS artifact. 6. Unrelated files are deleted using the privileges of the Node. ...[truncated 407 chars]- Remediation
View remediation
.mp3`. - Use `lstat()` and reject symbolic links and non-regular files. - Do not permit untrusted callers to provide arbitrary `maxAge` values. - Return cleanup errors to the caller or record them through structured security logging instead of silently continuing. ]]>
