What version of Kimi Code is running?
0.27.0
Which open platform/subscription were you using?
platform.kimi.ai
Which model were you using?
No response
What platform is your computer?
Linux 6.12.63-current-sunxi64 aarch64 unknown
What issue are you seeing?
When Kimi Web is accessed using the credential configured through KIMI_CODE_PASSWORD, authenticated REST requests and WebSocket initialization are noticeably slow, especially when kimi web is running on a slow machine, such as a Raspberry Pi.
Using the persistent server token against the same running server is fast.
The difference appears to be caused by password authentication performing a bcrypt comparison for every protected request. Server-token authentication uses a fast timing-safe comparison and short-circuits before reaching bcrypt.
Note: The password used for testing contained only letters, digits, -, _, and ., so this is separate from WebSocket subprotocol syntax or credential escaping issues.
What steps can reproduce the bug?
-
Start Kimi Web with password authentication enabled:
KIMI_CODE_PASSWORD='test-password_123' kimi web --foreground --no-open --host 127.0.0.1 --port 58627
-
Open the bare server URL without the generated token fragment: http://127.0.0.1:58627/ (without #token=)
-
Enter test-password_123 in the server credential dialog.
-
Observe the time required for the Web UI to initialize and for authenticated API operations to complete. Refresh the page, it can take 20 seconds (when served by a Raspberry Pi).
-
Open a new private browser window, or clear site data, open the same URL: http://127.0.0.1:58627/ (without #token=)
-
Enter the server-token printed from kimi web, not the password.
-
Observe that initialization and subsequent refreshes are significantly faster, even though this is the same server process.
What is the expected behavior?
Password authentication should not perform an expensive bcrypt comparison independently for every REST request and WebSocket authentication step.
Ideally, the password should be verified once and exchanged for a temporary session credential. Subsequent requests should use that credential and have performance comparable to the persistent server-token path.
Lowering the bcrypt cost does not seem like the preferred solution because it would weaken password hashing without addressing the repeated-verification design.
Additional information
The current source appears to explain the behavior.
KIMI_CODE_PASSWORD is hashed with bcrypt cost 12:
Credential validation tries the persistent token first and falls back to bcrypt password verification:
|
isValid: async (candidate) => |
|
deps.tokenStore.isValid(candidate) || |
|
(await verifyPassword(candidate, deps.passwordHash)), |
Consequently:
- A valid server token succeeds immediately and skips (the slow) bcrypt.
- A valid password first fails the token comparison and then performs bcrypt.
- The global authentication hook invokes this validation for every protected REST request.
- WebSocket upgrade authentication invokes the same validator.
Related sources:
A possible solution would be to authenticate the password once and issue a short-lived session token, rather than using the password itself as the bearer credential for every request.
What version of Kimi Code is running?
0.27.0
Which open platform/subscription were you using?
platform.kimi.ai
Which model were you using?
No response
What platform is your computer?
Linux 6.12.63-current-sunxi64 aarch64 unknown
What issue are you seeing?
When Kimi Web is accessed using the credential configured through
KIMI_CODE_PASSWORD, authenticated REST requests and WebSocket initialization are noticeably slow, especially whenkimi webis running on a slow machine, such as a Raspberry Pi.Using the persistent server token against the same running server is fast.
The difference appears to be caused by password authentication performing a
bcryptcomparison for every protected request. Server-token authentication uses a fast timing-safe comparison and short-circuits before reaching bcrypt.Note: The password used for testing contained only letters, digits, -, _, and ., so this is separate from WebSocket subprotocol syntax or credential escaping issues.
What steps can reproduce the bug?
Start Kimi Web with password authentication enabled:
KIMI_CODE_PASSWORD='test-password_123' kimi web --foreground --no-open --host 127.0.0.1 --port 58627
Open the bare server URL without the generated token fragment: http://127.0.0.1:58627/ (without
#token=)Enter
test-password_123in the server credential dialog.Observe the time required for the Web UI to initialize and for authenticated API operations to complete. Refresh the page, it can take 20 seconds (when served by a Raspberry Pi).
Open a new private browser window, or clear site data, open the same URL: http://127.0.0.1:58627/ (without
#token=)Enter the server-token printed from
kimi web, not the password.Observe that initialization and subsequent refreshes are significantly faster, even though this is the same server process.
What is the expected behavior?
Password authentication should not perform an expensive bcrypt comparison independently for every REST request and WebSocket authentication step.
Ideally, the password should be verified once and exchanged for a temporary session credential. Subsequent requests should use that credential and have performance comparable to the persistent server-token path.
Lowering the bcrypt cost does not seem like the preferred solution because it would weaken password hashing without addressing the repeated-verification design.
Additional information
The current source appears to explain the behavior.
KIMI_CODE_PASSWORD is hashed with bcrypt cost 12:
kimi-code/packages/kap-server/src/services/auth/password.ts
Line 5 in a41a09c
Credential validation tries the persistent token first and falls back to bcrypt password verification:
kimi-code/packages/kap-server/src/services/auth/authTokenService.ts
Lines 52 to 54 in a41a09c
Consequently:
Related sources:
kimi-code/packages/kap-server/src/start.ts
Lines 421 to 427 in a41a09c
A possible solution would be to authenticate the password once and issue a short-lived session token, rather than using the password itself as the bearer credential for every request.