{"id":"12250d8cd47e40d8","repo":"vitest-dev/vitest","slug":"cannot-use-cdp-because-browser-api-write-or-exec-o","errorCode":null,"errorMessage":"Cannot use CDP because browser API write or exec operations are disabled. See https://vitest.dev/config/api.","messagePattern":"Cannot use CDP because browser API write or exec operations are disabled\\. See https://vitest\\.dev/config/api\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/node/rpc.ts","lineNumber":144,"sourceCode":"  function canWrite(project: TestProject) {\n    return (\n      project.config.api.allowWrite\n      && project.vitest.config.api.allowWrite\n    )\n  }\n\n  function isCdpAllowed(project: TestProject) {\n    return (\n      project.config.api.allowExec\n      && project.vitest.config.api.allowExec\n      && project.config.api.allowWrite\n      && project.vitest.config.api.allowWrite\n    )\n  }\n\n  function assertCdpAllowed(project: TestProject) {\n    if (!isCdpAllowed(project)) {\n      throw new Error(\n        `Cannot use CDP because browser API write or exec operations are disabled. See https://vitest.dev/config/api.`,\n      )\n    }\n  }\n\n  function setupClient(\n    project: TestProject,\n    rpcId: string,\n    ws: WebSocket,\n    options: {\n      sessionId: string\n    },\n  ) {\n    const mockResolver = new ServerMockResolver(globalServer.vite, {\n      moduleDirectories: project.config?.deps?.moduleDirectories,\n    })\n    const mocker = project.browser?.provider.mocker\n","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/node/rpc.ts#L126-L162","documentation":"`assertCdpAllowed` requires `api.allowExec && api.allowWrite` on both the project-level and top-level Vitest config. When Vitest's API is exposed to the network (host set to non-localhost), `allowExec` and `allowWrite` default to false to prevent remote code execution; CDP can execute browser/OS commands, so it's gated behind both flags.","triggerScenarios":"Calling `cdp.send` / `cdp.on` (which route to `sendCdpEvent` / `trackCdpEvent` → `assertCdpAllowed`) while the API server is exposed (e.g. `--api.host 0.0.0.0`) and `api.allowExec`/`api.allowWrite` are at their default false.","commonSituations":"Running Vitest browser mode in a remote/CI dashboard setup with the API on a network interface; shared dev server; containerized Vitest with port forwarded.","solutions":["If you trust the network, opt in explicitly: `test: { api: { allowExec: true, allowWrite: true } }` (understand this permits remote code execution).","Prefer binding the API to localhost: `test: { api: { host: '127.0.0.1' } }` — defaults then permit CDP.","Use Vitest's API token authentication and limit network exposure."],"exampleFix":"// before\nexport default defineConfig({\n  test: { api: { host: '0.0.0.0', port: 9090 } },\n})\n\n// after — opt into CDP on a network-exposed server\nexport default defineConfig({\n  test: { api: { host: '0.0.0.0', port: 9090, allowExec: true, allowWrite: true } },\n})","handlingStrategy":"validation","validationCode":"function cdpAllowed(project: { config: { api: { allowExec?: boolean; allowWrite?: boolean } } },\n                                  vitest: { config: { api: { allowExec?: boolean; allowWrite?: boolean } } }): boolean {\n  return !!(\n    project.config.api.allowExec && project.config.api.allowWrite\n    && vitest.config.api.allowExec && vitest.config.api.allowWrite\n  )\n}","typeGuard":null,"tryCatchPattern":"try {\n  await cdp.send('Page.reload')\n} catch (err) {\n  if (err instanceof Error && /Cannot use CDP/.test(err.message)) {\n    // set api.allowExec / api.allowWrite, or bind to localhost\n  }\n  throw err\n}","preventionTips":["Prefer binding the API to localhost; the defaults then allow CDP.","Only enable allowExec/allowWrite on a trusted network.","Use API token auth and limit network exposure when hosting remotely."],"tags":["cdp","security","configuration","api"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}