{"record":{"id":"2b85d94587d41f52","repo":"ComposioHQ/composio","slug":"forbidden","errorCode":null,"errorMessage":"Forbidden","messagePattern":"Forbidden","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"ts/packages/cli/src/services/tool-permissions.ts","lineNumber":979,"sourceCode":"  readonly toolSlug: string;\n  readonly accountLabel?: string;\n  readonly agent: NativeUiCallerAgent;\n}): Promise<PermissionDecision> =>\n  new Promise((resolve, reject) => {\n    const token = crypto.randomUUID();\n    let settled = false;\n\n    const settle = (decision: PermissionDecision) => {\n      if (settled) return;\n      settled = true;\n      server.close();\n      resolve(decision);\n    };\n\n    const server = http.createServer((req, res) => {\n      const url = new URL(req.url ?? '/', 'http://127.0.0.1');\n      if (url.searchParams.get('token') !== token) {\n        res.writeHead(403, { 'Content-Type': 'text/plain; charset=utf-8' }).end('Forbidden');\n        return;\n      }\n\n      if (url.pathname === '/') {\n        res\n          .writeHead(200, {\n            'Content-Type': 'text/html; charset=utf-8',\n            'Cache-Control': 'no-store',\n          })\n          .end(approvalHtml({ ...params, token }));\n        return;\n      }\n\n      const decision =\n        url.pathname === '/allow-session'\n          ? 'allow_session'\n          : url.pathname === '/allow-once'\n            ? 'allow_once'","sourceCodeStart":961,"sourceCodeEnd":997,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/cli/src/services/tool-permissions.ts#L961-L997","documentation":"In the local permissions HTTP server, requests whose token query parameter does not match the expected per-session token receive a 403 response body 'Forbidden'. This is a plain HTTP response, not a thrown error, and exists to prevent unauthorized local processes from approving/denying tool permissions.","triggerScenarios":"A browser or local process hitting the permission callback server URL with a missing, wrong, or stale ?token= value — e.g. opening an old approval link after the server restarted (new token), or a mangled URL copy.","commonSituations":"Reusing a stale approval link from a previous run, URL truncation when copying, or another local app probing the port. The server binds locally and gates every path behind the token check.","solutions":["Use the fresh approval URL printed by the current CLI run","If the link came from an older session, restart the run to get a new link/token","Ensure the URL, including the token query parameter, is copied intact"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use the approval URL emitted by the current run","Copy the full URL including ?token=...","Discard approval links from prior sessions"],"tags":["permissions","localhost","http","auth-token"],"backgroundTag":"request-token-mismatch","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}