{"record":{"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/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser/src/node/rpc.ts#L126-L162","documentation":"assertCdpAllowed requires both allowExec and allowWrite on BOTH project.config.api and project.vitest.config.api to be true. These flags default to false when the API server is exposed to the network (api.host set), as a security measure. CDP can execute arbitrary page actions and write files, so it is gated behind both flags.","triggerScenarios":"Running Vitest with --api.host (or api.host in config) so the API is exposed, which flips allowExec/allowWrite defaults to false, then attempting any CDP-based operation. Also fires if the user explicitly set allowExec/allowWrite to false.","commonSituations":"CI dashboards or shared machines exposing the Vitest API and then trying to use the browser devtools/CDP panel; setting api.host for monitoring and forgetting to opt back into write/exec; misreading the warning printed by resolveConfig.","solutions":["Set api.allowExec and api.allowWrite to true explicitly if you trust the network boundary and need CDP.","Do not expose the API to a public network; bind to a loopback or LAN address instead.","If CDP is not needed, suppress the warning by acknowledging the disabled feature rather than enabling it.","Confirm both project-level and root-level api configs agree (both must allow)."],"exampleFix":"// before\nexport default defineConfig({ test: { api: { host: '0.0.0.0' } } }) // exposes API, CDP blocked\n// after\nexport default defineConfig({ test: { api: { host: '127.0.0.1', allowExec: true, allowWrite: true } } })","handlingStrategy":"validation","validationCode":"function cdpIsAllowed(api: { allowExec?: boolean; allowWrite?: boolean }, rootApi: { allowExec?: boolean; allowWrite?: boolean }): boolean {\n  return !!(api.allowExec && api.allowWrite && rootApi.allowExec && rootApi.allowWrite)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Bind api.host to loopback unless you genuinely need LAN/public exposure.","Set allowExec and allowWrite explicitly only after evaluating the trust boundary.","Make both project-level and root-level api configs agree."],"tags":["security","cdp","api-config","access-control","browser"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}