Skip to content

Sandbox escape: Playwright path APIs let scripts read/write arbitrary host files #109

@kimjune01

Description

@kimjune01

Summary

The QuickJS sandbox exposes raw Playwright client objects to guest scripts, and HostBridge.receiveFromSandbox() dispatches any protocol message to the host-side Playwright dispatcher with no method/parameter allowlist. Because several normal Playwright APIs accept host filesystem paths, a guest script can read or write arbitrary host files — directly contradicting the README's "no fs / no direct filesystem access" promise.

⚠️ This is a sandbox-escape security issue. You may prefer to convert this into a private GitHub security advisory rather than leave it public.

Where

  • daemon/src/sandbox/quickjs-sandbox.ts:422waitForConnectionObject() returns unrestricted Playwright Page objects.
  • daemon/src/sandbox/host-bridge.ts:54receiveFromSandbox() dispatches any JSON protocol message to DispatcherConnection.
  • README.md:181 — advertises these as "full Playwright Page objects".

Reproducer (read arbitrary host file)

const page = await browser.newPage();
await page.setContent('<input type="file" id="f">');
await page.setInputFiles('#f', '/etc/passwd');
const text = await page.evaluate(async () => {
  return await document.querySelector('#f').files[0].text();
});
console.log(text);

Other affected APIs (write paths)

  • page.screenshot({ path: '...' })
  • locator.screenshot({ path: '...' })
  • page.context().storageState({ path: '...' })
  • any Playwright option that takes a host path

Suggested fix

Don't expose raw Playwright client objects directly. Wrap or filter the API surface so only vetted methods are reachable, and explicitly reject any Playwright call that takes a host-side path or resource handle. If you keep the protocol bridge, add a method/parameter allowlist on the host side before dispatching.


Found via /bug-hunt (codex / gpt-5.4) round 1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions