Skip to content

fix(ui)!: harden UI API access#10583

Merged
sheremet-va merged 32 commits into
vitest-dev:mainfrom
hi-ogawa:fix/ui-api-capability-url
Jun 19, 2026
Merged

fix(ui)!: harden UI API access#10583
sheremet-va merged 32 commits into
vitest-dev:mainfrom
hi-ogawa:fix/ui-api-capability-url

Conversation

@hi-ogawa

@hi-ogawa hi-ogawa commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Description

As described in v5 breaking change doc, this changes so that Vitest UI now requires authentication for accessing /__vitest__/. First time user authenticates through accessing /__vitest__/?token=..., then middleware check token and persists it as cookie, then later /__vitest__/ access will check that cookie. To make required token stable between vitest invocation, it's now generated once in .local/share/vitest/.vitest-secret-token (and alike on macos and windows).

The rational of the change is that, even though the Vitest API usage is purely for devtools, what's available on the network through localhost:51204/__vitest__/ is immediately RCE (remote code execution) and it's reasonable to protect from arbitrary network access as a basic security posture. In retrospect, if we were to have this (together with #10522), the past vulnerabilities related to API didn't exist.

This is also partly because, intended or not, our security policy frames this way https://github.com/vitest-dev/vitest/blob/main/SECURITY.md#what-vitest-does-not-trust

What Vitest Does Not Trust:
Network data and untrusted clients The integration built on top of Vite's dev server must treat all inbound network requests as potentially hostile. This includes malformed requests. Clients may be outside the developer's intended environment because of port-forwarding, shared networks, or accidental exposure to the internet.

(Not sure yet though if I want to go through all vulnerability patch process. We can say this is a matter of interpretation since we do call out exposing allowExec/allowWrite in non localhost shouldn't be done in documentation.)

TODO

  • test
  • docs
  • cleanup

Example:

Screen.Recording.2026-06-18.at.17.41.03.mov

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. If the feature is substantial or introduces breaking changes without a discussion, PR might be closed.
  • Ideally, include a test that fails without this PR but passes with it.
  • Please, don't make changes to pnpm-lock.yaml unless you introduce a new test example.
  • Please check Allow edits by maintainers to make review process faster. Note that this option is not available for repositories that are owned by Github organizations.

Tests

  • Run the tests with pnpm test:ci.

Documentation

  • If you introduce new functionality, document it. You can run documentation with pnpm run docs command.

Changesets

  • Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with feat:, fix:, perf:, docs:, or chore:.

@netlify

netlify Bot commented Jun 12, 2026

Copy link
Copy Markdown

Deploy Preview for vitest-dev ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 760ce21
🔍 Latest deploy log https://app.netlify.com/projects/vitest-dev/deploys/6a34bc6cb5bbdf000893344f
😎 Deploy Preview https://deploy-preview-10583--vitest-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@hi-ogawa hi-ogawa changed the title fix(ui)!: validate UI API request fix(ui)!: harden UI API access Jun 12, 2026
@hi-ogawa

Copy link
Copy Markdown
Collaborator Author

Still brainstorming and cookie might indeed work alright. Here is possible flow:

  1. Vitest prints an auth URL once:
    UI auth URL: http://localhost:51204/__vitest__/?token=...
  2. Browser/open behavior still targets plain:
    http://localhost:51204/__vitest__/
  3. Plain UI without cookie shows a small blocked page:
    “Vitest UI is protected. Open the auth URL printed in the terminal to continue.”
  4. Visiting ?token=... validates token, sets an HttpOnly-ish session cookie, then redirects to plain /__vitest__/.
  5. Subsequent access uses cookie, so bookmarks/history/devtools mostly show the clean URL.

@hi-ogawa hi-ogawa added the p2-to-be-discussed Enhancement under consideration (priority) label Jun 17, 2026
@hi-ogawa hi-ogawa moved this to P2 - 3 in Team Board Jun 17, 2026
Comment thread test/ui/test/ui.spec.ts
Comment thread packages/vitest/src/node/create.ts
When the API token is generated for the first time, no browser holds the
auth cookie yet, so open `/__vitest__/?token=...` to authenticate. On
subsequent runs, open the clean URL so macOS tab reuse keeps working.

AI-Agent: Opencode
Comment thread packages/browser/src/node/plugin.ts Outdated
hi-ogawa and others added 5 commits June 19, 2026 11:50
`resolveApiToken` now returns the resolved `tokenPath` so the test can
target the actual on-disk token file, assert it exists, and confirm the
Vite dev server blocks serving it (403).

AI-Agent: Opencode
Drop the duplicated '.vitest-secret-token' literal in the browser plugin
and import the single source of truth from vitest's apiToken module via a
relative-src import, keeping the constant internal (no public vitest/node
API surface).

AI-Agent: Opencode
Comment thread packages/ui/node/index.ts Outdated
Comment thread packages/ui/node/index.ts Outdated
hi-ogawa added 3 commits June 19, 2026 12:34
Rename the constant to reflect it is the token filename, and reuse it
when building the token file paths instead of repeating the literal.

AI-Agent: Opencode
Replace the hand-rolled cookie parse/serialize with the jshttp `cookie`
library (bundled via devDependency). This makes encode/decode symmetric
and removes the bespoke parsing.

AI-Agent: Opencode
@hi-ogawa
hi-ogawa marked this pull request as ready for review June 19, 2026 03:55
@sheremet-va
sheremet-va merged commit 4c26d76 into vitest-dev:main Jun 19, 2026
15 of 18 checks passed
@hi-ogawa
hi-ogawa deleted the fix/ui-api-capability-url branch June 19, 2026 08:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p2-to-be-discussed Enhancement under consideration (priority)

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Harden browser mode and UI API access

2 participants