T09 · Insecure Skill Coding Practices
- Location
scripts/imap.js:311- Finding
Path Traversal and Arbitrary File Overwrite Through Attachment Filenames
- Content
View full analysis
Vulnerability Details
File Location:
scripts/imap.js, lines 311–312
Vulnerability Type: Path traversal and unsafe file overwrite
Risk Level: HighVulnerable Code
js const filePath = path.join(outputDir, attachment.filename); fs.writeFileSync(filePath, attachment.content);Technical Analysis
The attachment filename originates from email MIME metadata and is therefore controlled by the email sender. It is passed directly to
path.join()without first rejecting absolute paths, traversal components such as../, or other unsafe filename forms.path.join()constructs a path but does not guarantee that the resulting path remains insideoutputDir. A malicious filename can consequently resolve outside the intended attachment directory. Moreover,fs.writeFileSync()overwrites an existing destination by default and can follow symbolic links.Downloading attachments is part of the Skill's declared functionality, but allowing an email sender to select arbitrary filesystem destinations exceeds the minimum filesystem privileges required for that functionality.
Attack Path
- An attacker sends an email containing an attachment whose MIME filename includes traversal components, such as
../../target-file. - The victim or an AI Agent invokes
node scripts/imap.js download <uid>for that message. - The Skill parses the attacker-controlled attachment filename.
path.join(outputDir, attachment.filename)constructs a path outside the intended output directory.fs.writeFileSync()writes the attacker-controlled attachment content to that path.- If the destination already exists, it is overwritten; if the path references a symbolic link, the linked target may be modified.
Impact Assessment
An attacker can write or overwrite files accessible to the operating-system account running the Skill. The exact scope is limited by that account's filesystem permissions, but pote ...[truncated 486 chars]
- An attacker sends an email containing an attachment whose MIME filename includes traversal components, such as
- Remediation
View remediation
Remediation Suggestions
- Treat every attachment filename as untrusted input.
- Reduce the supplied filename to a safe leaf name with
path.basename(). - Reject absolute paths,
.and..path components, null bytes, empty filenames, and platform-specific path separators. - Resolve both the output directory and destination path, then verify that the destination remains beneath the output directory.
- Refuse to overwrite existing files by using an exclusive creation flag such as
{ flag: 'wx' }, unless overwrite behavior is explicitly requested and confirmed. - Detect and reject symbolic-link destinations.
- Generate a safe fallback filename when MIME metadata is absent or invalid.
- Consider setting restrictive permissions on downloaded files.
Example hardening pattern:
js const baseDir = path.resolve(outputDir); const safeName = path.basename(attachment.filename || 'attachment.bin'); if (!safeName || safeName === '.' || safeName === '..') { throw new Error('Invalid attachment filename'); } const filePath = path.resolve(baseDir, safeName); if (!filePath.startsWith(baseDir + path.sep)) { throw new Error('Attachment path escapes output directory'); } fs.writeFileSync(filePath, attachment.content, { flag: 'wx', mode: 0o600, });
