diff --git a/packages/opencode/src/server/routes/instance/httpapi/server.ts b/packages/opencode/src/server/routes/instance/httpapi/server.ts index 731cfa087..aec1af7b4 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/server.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/server.ts @@ -1,10 +1,12 @@ import { Effect, Layer, Redacted, Schema } from "effect" +import nodePath from "path" import { HttpApiBuilder, HttpApiMiddleware, HttpApiSecurity } from "effect/unstable/httpapi" import { HttpRouter, HttpServer, HttpServerRequest } from "effect/unstable/http" import { AppRuntime } from "@/effect/app-runtime" import { InstanceRef, WorkspaceRef } from "@/effect/instance-ref" import { Observability } from "@/effect" import { Flag } from "@/flag/flag" +import { Global } from "@/global" import { InstanceBootstrap } from "@/project/bootstrap" import { Instance } from "@/project/instance" import { lazy } from "@/util/lazy" @@ -103,7 +105,8 @@ const instance = HttpRouter.middleware()( if (!Flag.MIMOCODE_SERVER_PASSWORD) { const cwd = Filesystem.resolve(process.cwd()) - if (!Filesystem.contains(cwd, directory)) { + const worktreeRoot = Filesystem.resolve(nodePath.join(Global.Path.data, "worktree")) + if (!Filesystem.contains(cwd, directory) && !Filesystem.contains(worktreeRoot, directory)) { return yield* new DirectoryAccessDenied({ message: "Access denied: directory must be within the server's working directory", }) diff --git a/packages/opencode/src/server/routes/instance/middleware.ts b/packages/opencode/src/server/routes/instance/middleware.ts index c0d454bfb..8cd49d956 100644 --- a/packages/opencode/src/server/routes/instance/middleware.ts +++ b/packages/opencode/src/server/routes/instance/middleware.ts @@ -1,4 +1,5 @@ import type { MiddlewareHandler } from "hono" +import path from "path" import { Instance } from "@/project/instance" import { InstanceBootstrap } from "@/project/bootstrap" import { AppRuntime } from "@/effect/app-runtime" @@ -6,6 +7,7 @@ import { AppFileSystem } from "@mimo-ai/shared/filesystem" import { WorkspaceContext } from "@/control-plane/workspace-context" import { WorkspaceID } from "@/control-plane/schema" import { Flag } from "@/flag/flag" +import { Global } from "@/global" import { Filesystem } from "@/util" export function InstanceMiddleware(workspaceID?: WorkspaceID): MiddlewareHandler { @@ -23,7 +25,8 @@ export function InstanceMiddleware(workspaceID?: WorkspaceID): MiddlewareHandler if (!Flag.MIMOCODE_SERVER_PASSWORD) { const cwd = Filesystem.resolve(process.cwd()) - if (!Filesystem.contains(cwd, directory)) { + const worktreeRoot = Filesystem.resolve(path.join(Global.Path.data, "worktree")) + if (!Filesystem.contains(cwd, directory) && !Filesystem.contains(worktreeRoot, directory)) { return c.json({ error: "Access denied: directory must be within the server's working directory" }, 403) } }