feat(server): add bearer-token auth and safe host exposure#1006
Open
sailist wants to merge 29 commits into
Open
feat(server): add bearer-token auth and safe host exposure#1006sailist wants to merge 29 commits into
sailist wants to merge 29 commits into
Conversation
Boot startServer on port 0 and snapshot the documented v1 route table derived from /openapi.json paths, plus the reachability of doc/meta endpoints (/healthz, /openapi.json, /asyncapi.json, /). Gives later auth/--host phases an intentional diff when routes change. M0 makes no production behavior change.
Add test/helpers/serverHarness.ts: boot() wraps startServer with an isolated lock + home dir and returns a handle (server, address, baseUrl, wsUrl, token, close) plus authedFetch/authedWs that carry Authorization: Bearer <token> (and the kimi-code.bearer.<token> WS subprotocol). serviceOverrides is the generic DI seam later phases use to inject a fixed-token auth service; IAuthTokenService is not referenced yet. closeAll() tears down every booted server and socket. M0 makes no production behavior change; typecheck-only gate.
🦋 Changeset detectedLatest commit: f9fff11 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
- Replace native @node-rs/bcrypt with pure-JS bcryptjs so the ESM CLI bundle and the SEA native bundle both build without native-addon require issues (node-rs/bcrypt broke the ESM smoke and the SEA check-bundle allowlist). - Remove dead cleanup references (stopSpinner, authLogoBlinkTimer) in apps/kimi-web App.vue that failed vue-tsc. - Fix lint: drop empty spread fallbacks in the e2e auth-header merge, void the intentionally-async WS upgrade listener, add missing assertions to satisfy jest/expect-expect, and convert a ternary statement to if/else. - Send the bearer token in the snapshot perf/smoke tests so they pass under the new global auth hook. - Refresh the pnpmDeps hash in flake.nix for the updated lockfile.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR makes the local Kimi Code server safe to authenticate and expose. The server now requires a per-start bearer token on every REST and WebSocket call (the CLI and web UI pick it up automatically), validates
Host/Originheaders, and gains a--hostflag with a dedicated hardening tier for non-loopback (LAN / public) binds — mandatory password + TLS, auth-failure rate limiting, disabled remote shutdown/terminals, and security response headers. Seepackages/server/SECURITY.mdfor the threat model.1. Bearer-token authentication for the server
Problem: The local server exposed its full REST + WebSocket API with no authentication — anything that could reach the port could drive the agent, read the filesystem, and run terminals.
What was done:
tokenStore) and a globalonRequestauth hook enforcing it on all API routes, with bypass and redaction support.IAuthTokenServiceDI seam and an env-based bcrypt password-hash utility for password-derived auth.WS bearersubprotocol and parser.Authorizationon its own calls; the/webURL carries the token in its fragment so the browser UI can authenticate.2. kimi-web authentication flow
Problem: The browser UI had no way to present credentials, so it could not talk to an authenticated server.
What was done:
ServerAuthDialogand aserverAuthAPI client module to prompt for and store the token / password.3. Host / Origin request validation
Problem: Without Host/Origin checks, a DNS-rebinding or cross-origin browser request could target the local server even when it is authenticated.
What was done:
Hostheader in/asyncapi.json.4. Safe non-loopback (
--host) exposureProblem: Binding the server beyond loopback dramatically increases the attack surface and was previously unguarded.
What was done:
bindClassifyto classify binds as loopback / LAN / public, and registered a--hostflag passed through the daemon.KIMI_CODE_PASSWORDand TLS (or explicit--insecure-no-tls), rate-limit repeated auth failures, disable remote shutdown and terminals by default, add security response headers, and suppress debug routes.0600permissions.5. Tests, docs, and changeset
What was done:
packages/server/SECURITY.mddocumenting the deployment security model and threat model.minorchangeset for@moonshot-ai/kimi-code.Checklist
gen-changesetsskill, or this PR needs no changeset. (Changeset:.changeset/server-auth-and-host-exposure.md)gen-docsskill, or this PR needs no doc update. (Addspackages/server/SECURITY.md; user-facing CLI docs update to be confirmed.)