Introduction
In a reddit-app Node.js project, Trivy scanner flagged a high-severity path traversal vulnerability in the reddit-app/package-lock.json file. The culprit? The tmp package version 0.0.33, which contained CVE-2026-44705—a vulnerability that allows attackers to escape temporary directory boundaries through unsanitized prefix and postfix parameters. When an application using tmp accepts user-controlled input for temporary file naming, attackers could inject directory traversal sequences like ../../etc/ to write files anywhere on the filesystem, potentially compromising the entire system.
The vulnerability resided in how tmp 0.0.33 handled the optional prefix and postfix parameters when creating temporary files and directories. Without proper sanitization, these parameters could contain path traversal sequences that would be directly concatenated into the final filesystem path, bypassing the intended temporary directory isolation.
The Vulnerability Explained
The tmp package is widely used in Node.js applications to create temporary files and directories. In version 0.0.33, the package accepted prefix and postfix options that would be incorporated into the temporary file path. However, these parameters were not sanitized for directory traversal sequences.
Here's what the vulnerable dependency tree looked like in package-lock.json:
"node_modules/tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"license": "MIT",
"dependencies": {
"os-tmpdir": "~1.0.2"
},
"engines": {
"node": ">=0.6.0"
}
}
The vulnerability manifests when application code uses tmp with user-influenced input. Consider this attack scenario:
const tmp = require('tmp'); // version 0.0.33
// Attacker controls the prefix through an HTTP parameter
const userPrefix = req.query.prefix; // Contains: "../../etc/cron.d/"
tmp.file({ prefix: userPrefix, postfix: '.sh' }, (err, path, fd) => {
// Intended: /tmp/tmp-XYZ.sh
// Actual: /etc/cron.d/tmp-XYZ.sh
fs.writeFileSync(path, maliciousScript);
});
In this example, an attacker could:
1. Supply ../../etc/cron.d/ as the prefix parameter
2. The tmp library would create a file at /etc/cron.d/tmp-randomID.sh instead of in /tmp/
3. Write a malicious cron job that executes with elevated privileges
4. Achieve arbitrary code execution on the server
The real-world impact for the reddit-app application is severe. If any route handler or background job uses tmp with data derived from Reddit API responses, user comments, or configuration files, an attacker could:
- Overwrite application configuration files to change behavior
- Write to the web server's document root to serve malicious content
- Create files in system directories to escalate privileges
- Delete or corrupt critical application data
The Fix
The security team upgraded tmp from version 0.0.33 to 0.2.7, which includes comprehensive input sanitization. Here's what changed in package-lock.json:
Before (vulnerable):
"node_modules/tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"license": "MIT",
"dependencies": {
"os-tmpdir": "~1.0.2"
},
"engines": {
"node": ">=0.6.0"
}
}
After (secure):
"node_modules/tmp": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz",
"integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==",
"license": "MIT",
"engines": {
"node": ">=14.14"
}
}
Notice several critical improvements:
- Version upgrade: From 0.0.33 to 0.2.7, which includes the CVE-2026-44705 fix
- Dependency removal: The deprecated
os-tmpdirdependency is completely removed, as tmp 0.2.x uses Node.js's built-inos.tmpdir()method - Modern Node.js requirement: The minimum Node.js version increased from 0.6.0 to 14.14, ensuring access to modern security features
The fix was enforced through an npm override in package.json:
"overrides": {
"tmp": "0.2.7"
}
This override ensures that even if other dependencies in the project require older versions of tmp, npm will force the use of the secure 0.2.7 version throughout the entire dependency tree.
How this specific change solves the problem:
The tmp 0.2.7 version implements strict validation of prefix and postfix parameters:
- Path traversal sequences (../, ..\\) are detected and rejected
- Absolute paths are not permitted in prefix/postfix
- Only safe filename characters are allowed
- The temporary directory boundary is enforced at the library level
This means that even if application code passes unsanitized user input to tmp, the library itself will prevent directory escape attempts. The attack scenario shown earlier would now fail safely:
const tmp = require('tmp'); // version 0.2.7
const userPrefix = req.query.prefix; // Contains: "../../etc/cron.d/"
tmp.file({ prefix: userPrefix, postfix: '.sh' }, (err, path, fd) => {
// tmp 0.2.7 sanitizes the prefix, stripping traversal sequences
// Result: /tmp/.._.._etc_cron.d_tmp-XYZ.sh (safe)
// Or throws an error, depending on configuration
});
Prevention & Best Practices
To avoid path traversal vulnerabilities in Node.js applications:
1. Keep Dependencies Updated
Regularly audit and update npm packages, especially security-critical libraries like tmp. Use tools like npm audit or npm outdated to identify vulnerable dependencies:
npm audit
npm audit fix
2. Validate File Path Components
Never pass user input directly as file path components without validation:
// BAD: Direct use of user input
tmp.file({ prefix: req.query.prefix });
// GOOD: Validate against allowlist
const ALLOWED_PREFIXES = ['user-upload', 'cache', 'session'];
const prefix = ALLOWED_PREFIXES.includes(req.query.type)
? req.query.type
: 'default';
tmp.file({ prefix });
3. Use Path Normalization
Always normalize and validate paths before file operations:
const path = require('path');
function isSafePath(userPath, baseDir) {
const normalized = path.normalize(userPath);
const resolved = path.resolve(baseDir, normalized);
return resolved.startsWith(path.resolve(baseDir));
}
4. Implement Defense in Depth
Even with library fixes, implement application-level controls:
- Use chroot jails or containers to limit filesystem access
- Run Node.js processes with minimal file system permissions
- Log all file creation operations for audit trails
- Implement rate limiting on file creation endpoints
5. Static Analysis Integration
Integrate security scanners into your CI/CD pipeline:
- Trivy: Scans package-lock.json for known CVEs (as used here)
- Snyk: Monitors dependencies and suggests fixes
- npm audit: Built-in vulnerability scanner
- Semgrep: Detects insecure code patterns
OWASP and CWE References
This vulnerability maps to:
- CWE-22: Improper Limitation of a Pathname to a Restricted Directory
- OWASP Top 10 2021: A01:2021 – Broken Access Control
The OWASP Path Traversal prevention cheat sheet recommends:
- Input validation with allowlists
- Path canonicalization before validation
- Sandboxing file operations
- Principle of least privilege for file system access
Key Takeaways
- tmp 0.0.33's unsanitized prefix/postfix parameters allowed directory traversal through
../sequences, enabling arbitrary file writes outside temporary directories - The os-tmpdir dependency was completely removed in tmp 0.2.x, reducing the attack surface and eliminating a deprecated dependency
- npm overrides in package.json ensure consistent security across the entire dependency tree, even when transitive dependencies require older versions
- Trivy scanner successfully detected CVE-2026-44705 in package-lock.json before the vulnerability could be exploited in production
- Upgrading from Node.js 0.6.0 to 14.14 minimum requirement ensures access to modern security features and better filesystem isolation primitives
How Orbis AppSec Detected This
- Source: The vulnerability exists in the tmp package's handling of prefix and postfix parameters, which can be influenced by user input through HTTP requests, API responses, or configuration files
- Sink: The unsafe path construction in tmp 0.0.33's
file()anddir()methods at the point where prefix/postfix are concatenated into filesystem paths without sanitization - Missing control: Input validation and path traversal sequence filtering for the prefix and postfix parameters before filesystem path construction
- CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
- Fix: Upgraded tmp from 0.0.33 to 0.2.7, which implements comprehensive input sanitization and removes the deprecated os-tmpdir dependency
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
CVE-2026-44705 demonstrates how even widely-used utility libraries can contain critical security flaws that persist across years and thousands of dependent projects. The path traversal vulnerability in tmp 0.0.33 could have allowed attackers to write files anywhere on the filesystem, leading to complete system compromise. By upgrading to tmp 0.2.7 and using npm overrides to enforce this version across the dependency tree, the reddit-app project eliminated this attack vector.
The key lesson: dependency security requires continuous monitoring and rapid response. Automated tools like Trivy can detect these vulnerabilities, but the real security improvement comes from acting on those findings—upgrading vulnerable packages, testing the changes, and deploying fixes quickly. Make dependency auditing a regular part of your development workflow, not a once-a-year security review.