T09 · Insecure Skill Coding Practices
- Location
scripts/generate_report.js:359- Finding
Path Traversal and Arbitrary File Overwrite Through Unvalidated Report Filename
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_report.js, lines 359-368
Vulnerability Type: Path traversal and unsafe file overwrite
Risk Level: MediumVulnerable Code
javascript const data = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')); const outputPath = data.filename ? path.join(getDesktopPath(), `${data.filename}.docx`) : path.join(getDesktopPath(), '精读报告.docx'); const doc = generateDocument(data); const buffer = await Packer.toBuffer(doc); fs.writeFileSync(outputPath, buffer); console.log('Word document created: ' + outputPath);Technical Analysis
The
filenameproperty is read from an externally supplied JSON file and passed directly topath.joinwithout validation or canonical-path containment checks. Contrary to the intended behavior,path.joindoes not guarantee that the resulting path remains inside the Desktop directory. Traversal components such as../are normalized and can move the destination outside that directory.The destination is then passed to
fs.writeFileSync, which overwrites an existing file by default. The operation may also follow a symbolic link at the destination. Appending.docxlimits the resulting filename suffix but does not prevent directory traversal or replacement of an existing.docx-suffixed file.Attack Path
- An attacker supplies or influences the JSON analysis file consumed by
--data. - The attacker sets
filenameto a traversal value such as../../Documents/target. - The user or agent executes:
bash node scripts/generate_report.js --data attacker-controlled.json path.joinnormalizes the traversal components, producing a destination outside the Desktop directory.fs.writeFileSynccreates or overwritestarget.docxat that destination.- If the selected destination is a symbolic link, the process may overwrite the link target instead.
Exploitation is constrained b ...[truncated 720 chars]
- An attacker supplies or influences the JSON analysis file consumed by
- Remediation
View remediation
Remediation Suggestions
- Treat
data.filenameas an untrusted basename rather than a path. - Reject absolute paths, path separators,
.and..components, control characters, and platform-specific separator variants. - Apply a strict allowlist for report names, such as letters, numbers, spaces, underscores, and hyphens.
- Resolve both the Desktop directory and final destination with
path.resolve, then verify that the destination remains beneath the Desktop directory. - Detect existing files and request confirmation or generate a unique filename instead of overwriting them silently.
- Where overwrite behavior is unnecessary, use exclusive creation flags such as
{ flag: 'wx' }. - Consider checking for symbolic links before writing and using a safer file-creation strategy that minimizes time-of-check/time-of-use races.
Example hardening logic:
javascript const desktop = path.resolve(getDesktopPath()); const requestedName = String(data.filename || 'reading-report'); if ( requestedName !== path.basename(requestedName) || !/^[A-Za-z0-9 _-]+$/.test(requestedName) ) { throw new Error('Invalid report filename'); } const outputPath = path.resolve(desktop, `${requestedName}.docx`); if (!outputPath.startsWith(desktop + path.sep)) { throw new Error('Output path escapes the Desktop directory'); } fs.writeFileSync(outputPath, buffer, { flag: 'wx' });- Treat
