ComposioHQ/composio · warning

Forbidden

Error message

Forbidden

What it means

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.

Source

Thrown at ts/packages/cli/src/services/tool-permissions.ts:979

  readonly toolSlug: string;
  readonly accountLabel?: string;
  readonly agent: NativeUiCallerAgent;
}): Promise<PermissionDecision> =>
  new Promise((resolve, reject) => {
    const token = crypto.randomUUID();
    let settled = false;

    const settle = (decision: PermissionDecision) => {
      if (settled) return;
      settled = true;
      server.close();
      resolve(decision);
    };

    const server = http.createServer((req, res) => {
      const url = new URL(req.url ?? '/', 'http://127.0.0.1');
      if (url.searchParams.get('token') !== token) {
        res.writeHead(403, { 'Content-Type': 'text/plain; charset=utf-8' }).end('Forbidden');
        return;
      }

      if (url.pathname === '/') {
        res
          .writeHead(200, {
            'Content-Type': 'text/html; charset=utf-8',
            'Cache-Control': 'no-store',
          })
          .end(approvalHtml({ ...params, token }));
        return;
      }

      const decision =
        url.pathname === '/allow-session'
          ? 'allow_session'
          : url.pathname === '/allow-once'
            ? 'allow_once'

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Use the fresh approval URL printed by the current CLI run
  2. If the link came from an older session, restart the run to get a new link/token
  3. Ensure the URL, including the token query parameter, is copied intact
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/2b85d94587d41f52. Report an issue: GitHub.