Engineering

Playwright MCP: your agent's browser is older than you think, and the sandbox is off

Karim Jouini

TLDR

  • Playwright bundles its own Chromium, which only updates when Playwright ships a release. Playwright 1.64.1 likely misses two recent Chrome security updates, including five Critical fixes.
  • Playwright's chromiumSandbox launch option defaults to false, so a single browser exploit can run code as you, on the machine that holds your credentials.
  • Playwright MCP is not a security boundary, and the official Docker image runs browsers as root, where the sandbox isn't available.
  • The fix: update Playwright, use installed Chrome with the sandbox on for open-web browsing, isolate browsing agents, and pin your MCP server to 0.0.40 or newer.

If your coding agent drives Playwright on your own laptop, directly or through Playwright MCP, its browser is probably missing last week's Chrome security fixes. And it's running with Chromium's sandbox switched off.

That's the short version of a PSA from @nisten on November 2. The headline advice, "delete Playwright now," is louder than it needs to be. The facts underneath it hold up.

We checked each claim against Playwright's own docs, Google's Chrome release notes and the CVE records. Here's what's true, what's overstated, and what to change before your agent's next "quick look at the docs."

‍

"Up to date" Playwright still ships an older Chromium

Playwright 1.64.1, the newest release, bundles Chromium 156.0.8078.4. Google has shipped two security updates to Chrome 156 since then: 156.0.8078.73 on October 27 with 52 fixes, and 156.0.8078.79 on October 29.

Playwright's browser only moves when Playwright cuts a release. Your npm outdated can be clean while your agent browses on a build that predates both patches. Between them, those two updates fixed five bugs Google rated Critical:

CVEComponentBug typeFixed in Chrome
CVE-2026-118306FileSystemMemory corruption156.0.8078.73
CVE-2026-118331FileAPIImproper input validation156.0.8078.73
CVE-2026-118348SkiaImproper input validation156.0.8078.73
CVE-2026-118344LayoutUse-after-free156.0.8078.73
CVE-2026-76024MediaStreamMemory corruption156.0.8078.79

The first one is the headline. Its NVD entry says a crafted HTML page could let an attacker run code outside the browser sandbox. Hold that thought for the next section.

One caveat, stated plainly: this comes from comparing version numbers, not from testing each CVE against Playwright's build. Google doesn't publish which fixes landed in which pre-release Chromium build, so "likely unpatched" is the honest label.

Older Playwright versions are worse

If you pinned Playwright a while back, the gap includes bugs attackers have actually used. Playwright 1.63 ships Chromium 153.0.8010.12. CVE-2026-87491, a V8 out-of-bounds write that Google confirmed was exploited in the wild, was fixed in 153.0.8010.36. CISA added it to its Known Exploited Vulnerabilities catalog on September 9.

Versions before 1.63 very likely also miss CVE-2026-85046, another exploited V8 bug patched September 3. For 1.64.x, we found no Chrome bug with confirmed in-the-wild exploitation in the gap.

‍

The default that should actually worry you

A few weeks of version lag is normal for any bundled browser. The bigger issue is one line in Playwright's launch options: chromiumSandbox defaults to false.

Chromium's sandbox is the wall between a compromised renderer and your operating system. Most browser exploits land in the renderer first. With the sandbox on, the attacker then needs a second bug to get out. With it off, the first bug is enough, and the attacker's code runs as you.

On a developer laptop, "as you" means your .env files, your SSH keys, your cloud CLI tokens and every session cookie in reach.

This default wasn't careless. Playwright switched it off years ago because CI environments kept failing to launch Chromium with the sandbox on. For end-to-end tests against your own staging app, that trade made sense. The page is yours. The code on it is yours.

The trade stops making sense the moment the browser visits pages you didn't write.

‍

Playwright MCP security: agents point a test tool at the open web

A test suite visits a known list of URLs. An agent visits whatever the task, a search result or a line of injected text tells it to. That's the open web, on a lagging browser, with no sandbox, on the machine that holds your credentials.

Playwright's maintainers are upfront about this. The Playwright MCP README says the server is not a security boundary. Its --allowed-origins flag allows every origin by default, and the docs say it doesn't affect redirects either. It's a guardrail for keeping an agent on task, not a wall against a hostile page.

The MCP server has had its own bug, too. Versions before 0.0.40 didn't validate the Origin header, which let a malicious website use DNS rebinding to call local MCP tools (CVE-2025-9611).

‍

Playwright in Docker isn't sandboxed by default either

Containers help. The official image doesn't help as much as people assume.

Playwright's Docker image runs browsers as root by default, and Chromium's sandbox isn't available to root. The docs say the image is meant for testing and development, and not recommended for visiting untrusted websites. For crawling, they recommend a separate non-root user plus their seccomp profile, which adds the user-namespace permissions the sandbox needs.

A root container with your project folder mounted and your API keys in its environment is a thinner wall than it looks.

‍

What to change this week

You don't need to delete anything. You need to stop running an unsandboxed, lagging browser against untrusted pages on the machine that holds your secrets.

  1. Update Playwright. Especially if you're on 1.63 or older, where the gap includes exploited bugs.
  2. Use real Chrome, sandboxed, for anything that touches the open web. Installed Chrome auto-updates on Google's schedule, not Playwright's. The launch options are below.
  3. Isolate browsing agents. A VM or a non-root container with the seccomp profile. No real credentials, no mounted home folder, a throwaway browser profile.
  4. Pin your MCP server. npx @playwright/mcp@latest runs whatever was published most recently. Pin an exact version you've reviewed, and make sure it's 0.0.40 or newer.
  5. Separate test runs from agent browsing. Your test suite and your coding agent have different threat models. They shouldn't share a browser config by accident.

For step 2, launch Chromium like this:

const browser = await chromium.launch({
  channel: 'chrome',      // your installed, auto-updating Chrome
  chromiumSandbox: true,  // off by default in Playwright
});

‍

Check your machine in 30 seconds

These commands only read what's already installed:

ls ~/.cache/ms-playwright ~/Library/Caches/ms-playwright 2>/dev/null
npx --no-install playwright --version

On Windows, the browser cache lives in %USERPROFILE%\AppData\Local\ms-playwright.

Look for folders named chromium-NNNN. Playwright 1.64.1 uses revision 1248. Lower numbers are older builds, and old builds stay on disk after upgrades until you remove them.

Keep the --no-install flag. Plain npx playwright will download and run the package if it's missing, which is the opposite of what you want from a safety check.

‍

Keep it in proportion

Playwright isn't malware, and we found no report of these October bugs being exploited through it. Running your test suite against your own localhost, with content you control, is low risk. The defaults were built for exactly that job.

What changed is how many of us now hand the same tool to an agent and point it at the whole internet.

A follow-up in the thread suggested dropping Node and npx for Bun. Swap package managers if you like, but it doesn't touch this problem. The risk lives in which browser build runs, whether its sandbox is on, and what that process can reach. bunx @playwright/mcp@latest fetches the latest release just like npx does.

‍

Playwright + Thunders for your end-to-end suite

Everything above comes down to one split. A coding agent browsing the open web needs isolation, and the checklist covers that. Your end-to-end test suite is a different job: it visits your own app on every release, and it has to keep passing as your UI changes.

That second job is where most teams reach for Playwright, often through the same agent, on the same laptop. It's also where Thunders fits.

Playwright is a free, open-source browser automation library. It's the right pick when engineers want to script a browser in code and own everything around it: where it runs, when its browser updates, and how its sandbox and containers are configured.

Thunders is an end-to-end testing platform where AI Test Agents build, run and maintain tests across web, mobile, API and desktop, written in plain language. For web, it runs on Playwright's low-level browser engine with its own intent-based execution layer on top, so your team never maintains Playwright scripts. Tests run in Thunders' cloud, in a hybrid setup where you author in the cloud and run on your own infrastructure, or fully self-hosted.

PlaywrightThunders
What it isOpen-source browser automation libraryEnd-to-end testing platform with AI Test Agents
Who writes testsEngineers, in TypeScript, Python, Java or .NETAnyone on the team, in plain language
Who fixes tests when the UI changesYour teamThunders, with every heal visible and auditable
Where test browsers runWherever you install it: laptops, CI runners, containersThunders' cloud, hybrid or self-hosted
Browser updates and sandbox settingsYour team's job (chromiumSandbox defaults to false)Managed by Thunders, off your machines
CI/CDAny CI, through its test runnerGitHub, Jenkins and Jira integrations; can block merges when a critical flow fails
CostFree; paid in engineering time and infrastructurePaid plans
Best forTeams with automation engineers who want full controlTeams that want E2E coverage without owning a test framework

If you're running Playwright, or Playwright MCP, mainly to keep an end-to-end suite alive, that's where Thunders comes in. Keep asking Claude to write tests. Thunders takes on everything after: running them, triaging failures, fixing selectors when the UI changes, reporting and keeping the evidence. And your test runs stop sharing a machine with your SSH keys.

Using Thunders and Playwright together

Most teams already have Playwright tests, and many now write them with Claude. Keep both. Thunders is built on Playwright for web testing, and it connects to Playwright at both ends of a test suite's life.

  • Bring your existing Playwright suite. Connect your AI assistant (Claude, Copilot or Cursor) to your repo and to the Thunders MCP server, and it converts each Playwright test into a plain-language Thunders test, folder by folder. The same works for Cypress and Selenium. You keep the coverage you've built, and anyone on the team can read and edit every test.
  • Take your tests back out, any time. Thunders exports your web tests as a standard Playwright TypeScript project that runs with npm ci and npx playwright test, with no dependency on Thunders. Each step becomes a named test.step with your original plain-language instruction kept as a comment above it, and secrets are never exported. On a real project of about 200 test cases, 95% of steps exported as fully runnable code. What stays behind is what needs AI at run time: plain-language checks, self-healing selectors and generated data. Mobile tests export as a WebdriverIO and Appium project.
  • Same engine underneath. Thunders uses Playwright's low-level browser automation for web, but it never generates Playwright scripts to run. It executes the test's intent and remembers what it learned about each page, so AI only steps in when your app changes.
  • Same coding assistant. If your developers already ask GitHub Copilot or Claude to write Playwright tests, they can connect Thunders through MCP and ask for Thunders tests instead, generated alongside each pull request.
  • Code when you need it. Power users can drop custom JavaScript steps into any Thunders test.

Run your first Thunders test free

FAQs

Whether you're getting started or scaling advanced workflows, here are the answers to the most common questions we hear from QA, DevOps, and product teams.

Is Playwright safe to use?

Yes, for its intended job: testing your own application with content you control. The risk appears when Playwright browses untrusted sites, because its bundled Chromium can lag Chrome's security patches and its Chromium sandbox is off by default.

Is Playwright MCP secure?

Playwright MCP's own README says it is not a security boundary, and its --allowed-origins option allows every origin by default. Use version 0.0.40 or newer, which fixes the CVE-2025-9611 DNS rebinding bug, and run it in an isolated VM or non-root container with no real credentials.

Does Playwright enable the Chromium sandbox by default?

No. Playwright's chromiumSandbox launch option defaults to false. Set chromiumSandbox: true to turn it on, and avoid running as root in Docker, where the sandbox isn't available.

How do I check which Chromium version Playwright uses?

Run npx --no-install playwright --version and list your ms-playwright cache folder. Playwright 1.64.1 uses Chromium 156.0.8078.4, stored as chromium-1248.

What do teams add to Playwright for end-to-end testing at scale?

Many teams keep Playwright for developer-level checks and add Thunders for the end-to-end journeys the whole team owns. Thunders is an end-to-end testing platform where AI Test Agents build, run and maintain tests in plain language. It imports existing Playwright suites, runs them in its cloud, hybrid or self-hosted, and exports back to a Playwright project at any time.

Can you use Thunders and Playwright together?

Yes. Thunders uses Playwright's browser engine for web testing, can import existing Playwright test files and convert them into plain-language tests, and can export Thunders web tests back to Playwright code. Teams can migrate an existing Playwright suite without starting over, and keep a code exit if they ever need one.

Ready to ship faster with smarter testing?

Screenshot of the Thunders app Test Cases list, showing test sets, labels and last run status, with a label picker open