T09 · Insecure Skill Coding Practices
- Location
scripts/imap.js:16- Finding
Symbolic-Link Bypass of the Attachment Write Allowlist
- Content
View full analysis
path.resolve(d.trim().replace(/^~/, os.homedir())) ); const allowed = allowedDirs.some(dir => resolved === dir || resolved.startsWith(dir + path.sep) ); if (!allowed) { throw new Error(`Access denied: '${dirPath}' is outside allowed write directories`); } return resolved; } ``` The validated path is subsequently used to write attachment data: ```javascript const resolvedDir = validateWritePath(outputDir); if (!fs.existsSync(resolvedDir)) { fs.mkdirSync(resolvedDir, { recursive: true }); } const downloaded = []; for (const attachment of parsed.attachments) { if (specificFilename && attachment.filename !== specificFilename) { continue; } if (attachment.content) { const filePath = path.join(resolvedDir, sanitizeFilename(attachment.filename)); fs.writeFileSync(filePath, attachment.content); ``` ### Technical Analysis The write allowlist compares lexically normalized paths produced by `path.resolve()`. This removes relative components but does not resolve symbolic links or establish that the final filesystem destination remains beneath a canonical allowed root. Consequently, an allowed directory, one of its descendants, or an existing destination file can be a symbolic link to a location outside `ALLOWED_WRITE_DIRS`. `fs.writeFileSync()` follows symbolic links by default. Filename sanitization prevents direct `../` traversal in attachment names, but i ...[truncated 1471 chars]- Remediation
View remediation
