Skip to content

[Web/Auth] Password-backed bearer credentials trigger bcrypt(cost=12) on every API request #4727

Open

Description

@ooopsec

Summary

Kimi Code 2.5.1 on macOS arm64.

When KIMI_CODE_PASSWORD is configured and the Web UI uses the password as its bearer credential, every authenticated API request performs a bcrypt(cost=12) comparison. Since bcryptjs runs on the Node.js main thread, concurrent requests queue behind repeated password hashes, making the initial Web load take 4–5 seconds.

Reproduction and Evidence

  1. Start kimi web with KIMI_CODE_PASSWORD configured.
  2. Authenticate the Web UI using the password rather than the generated server token.
  3. Reload the page and measure authenticated API requests.

Observed results:

  • Public /api/v1/healthz: approximately 5 ms
  • Authenticated /api/v1/meta, /models, and /config: approximately 176–212 ms
  • Ten sequential /api/v1/meta requests: 175–181 ms each, increasing the Kimi process CPU time by 1.84 seconds
  • /api/v1/client_configs: 226–234 ms, while direct upstream requests took only 55–61 ms
  • /api/v1/catalog/providers with a warm cache: 191–197 ms

This indicates that the dominant latency is authentication overhead rather than the business endpoints or their upstream services.

Root Cause

packages/kap-server/src/services/auth/authTokenService.ts contains:

isValid: async (candidate) =>
  deps.tokenStore.isValid(candidate) ||
  await verifyPassword(candidate, deps.passwordHash)

With a password-backed bearer credential, tokenStore.isValid() always fails, so every request falls back to verifyPassword(). packages/kap-server/src/services/auth/password.ts sets BCRYPT_COST = 12.

The generated-token path uses timingSafeEqual() and does not have this overhead.

Suggested Fix

Verify the password once and issue a generated/session token for subsequent REST and WebSocket requests. Alternatively, cache successful password verification in memory and invalidate it when the password configuration changes.

Keep cost 12 for interactive password verification; the goal is to avoid repeated verification, not to weaken password security.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions