fix(cli): require auth for allow everything endpoint

This commit is contained in:
Mark IJbema
2026-07-02 14:17:57 +02:00
parent 2992e3e443
commit 51dc189682
6 changed files with 102 additions and 7 deletions
@@ -146,6 +146,31 @@ describe("daemon manager", () => {
).toStrictEqual(["/tmp/bun", "--conditions=browser", "/tmp/kilo/src/index.ts"])
})
test("does not reuse legacy fixed-password daemons", () => {
const input = {
hostname: "127.0.0.1",
port: 4097,
mdns: false,
mdnsDomain: "kilo.local",
cors: [],
}
const state: Daemon.State = {
pid: 1,
hostname: input.hostname,
port: input.port,
url: "http://127.0.0.1:4097",
username: "kilo",
password: "kilo",
token: Buffer.from("kilo:kilo").toString("base64"),
version: "test",
startedAt: new Date(0).toISOString(),
log: "/tmp/daemon.log",
options: input,
}
expect(Daemon.matches(state, input, [])).toBe(false)
})
test("reuses one daemon across caller directories", async () => {
await using tmp = await tmpdir()
const env = opts(tmp.path)
@@ -169,6 +194,8 @@ describe("daemon manager", () => {
expect(started.running).toBe(true)
expect(started.state?.pid).toBeGreaterThan(0)
expect(started.state?.token).toBeTruthy()
expect(started.state?.password).not.toBe("kilo")
expect(started.state?.token).not.toBe(Buffer.from("kilo:kilo").toString("base64"))
expect(started.state?.port).toBeGreaterThan(0)
const blocked = await fetch(`${started.state!.url}/config?directory=${encodeURIComponent(tmp.path)}`)
@@ -1,5 +1,6 @@
// kilocode_change - new file
import { describe, expect, test } from "bun:test"
import { afterEach, describe, expect, test } from "bun:test"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Cause, Effect, Exit, Fiber, Layer } from "effect"
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
import { Bus } from "../../../src/bus"
@@ -22,6 +23,30 @@ const env = Layer.mergeAll(
CrossSpawnSpawner.defaultLayer,
)
const it = testEffect(env)
const original = {
password: Flag.KILO_SERVER_PASSWORD,
username: Flag.KILO_SERVER_USERNAME,
envPassword: process.env.KILO_SERVER_PASSWORD,
envUsername: process.env.KILO_SERVER_USERNAME,
}
afterEach(() => {
Flag.KILO_SERVER_PASSWORD = original.password
Flag.KILO_SERVER_USERNAME = original.username
if (original.envPassword === undefined) delete process.env.KILO_SERVER_PASSWORD
else process.env.KILO_SERVER_PASSWORD = original.envPassword
if (original.envUsername === undefined) delete process.env.KILO_SERVER_USERNAME
else process.env.KILO_SERVER_USERNAME = original.envUsername
})
const auth = () => `Basic ${Buffer.from("kilo:secret").toString("base64")}`
const requireAuth = () => {
Flag.KILO_SERVER_PASSWORD = "secret"
Flag.KILO_SERVER_USERNAME = undefined
process.env.KILO_SERVER_PASSWORD = "secret"
delete process.env.KILO_SERVER_USERNAME
}
const ask = (input: Permission.AskInput) =>
Effect.gen(function* () {
@@ -47,20 +72,28 @@ const wait = () =>
describe("AllowEverythingPermission", () => {
test("handles disable requests through the HTTP endpoint", async () => {
requireAuth()
await using tmp = await tmpdir({ git: true })
await provideTestInstance({
directory: tmp.path,
fn: async () => {
const enable = await Server.Default().app.request("/permission/allow-everything", {
const blocked = await Server.Default().app.request("/permission/allow-everything", {
method: "POST",
headers: { "Content-Type": "application/json", "x-kilo-directory": tmp.path },
body: JSON.stringify({ enable: true }),
})
expect(blocked.status).toBe(401)
const enable = await Server.Default().app.request("/permission/allow-everything", {
method: "POST",
headers: { "Content-Type": "application/json", "x-kilo-directory": tmp.path, authorization: auth() },
body: JSON.stringify({ enable: true }),
})
expect(enable.status).toBe(200)
const disable = await Server.Default().app.request("/permission/allow-everything", {
method: "POST",
headers: { "Content-Type": "application/json", "x-kilo-directory": tmp.path },
headers: { "Content-Type": "application/json", "x-kilo-directory": tmp.path, authorization: auth() },
body: JSON.stringify({ enable: false }),
})
expect(disable.status).toBe(200)