summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBuck Evan <[email protected]>2025-12-22 08:37:43 -0600
committerGitHub <[email protected]>2025-12-22 08:37:43 -0600
commit60db171b44193041348bfc00623c7a56e645a0d4 (patch)
tree56587bd26b153ad6089fcf8281c82a781608c221
parentc6e9a5c800f7b65f5e7138628443248bed88ecd2 (diff)
downloadopencode-60db171b44193041348bfc00623c7a56e645a0d4.tar.gz
opencode-60db171b44193041348bfc00623c7a56e645a0d4.zip
fix(read): narrow .env file blocking to not block .envrc (#5654)
Co-authored-by: Claude <[email protected]>
-rw-r--r--packages/opencode/src/tool/read.ts8
-rw-r--r--packages/opencode/test/tool/read.test.ts42
2 files changed, 47 insertions, 3 deletions
diff --git a/packages/opencode/src/tool/read.ts b/packages/opencode/src/tool/read.ts
index 27426ad24..fd81c4864 100644
--- a/packages/opencode/src/tool/read.ts
+++ b/packages/opencode/src/tool/read.ts
@@ -60,10 +60,12 @@ export const ReadTool = Tool.define("read", {
}
const block = iife(() => {
- const whitelist = [".env.sample", ".example"]
+ const basename = path.basename(filepath)
+ const whitelist = [".env.sample", ".env.example", ".example", ".env.template"]
- if (whitelist.some((w) => filepath.endsWith(w))) return false
- if (filepath.includes(".env")) return true
+ if (whitelist.some((w) => basename.endsWith(w))) return false
+ // Block .env, .env.local, .env.production, etc. but not .envrc
+ if (/^\.env(\.|$)/.test(basename)) return true
return false
})
diff --git a/packages/opencode/test/tool/read.test.ts b/packages/opencode/test/tool/read.test.ts
new file mode 100644
index 000000000..47a7aee2a
--- /dev/null
+++ b/packages/opencode/test/tool/read.test.ts
@@ -0,0 +1,42 @@
+import { describe, expect, test } from "bun:test"
+import path from "path"
+import { ReadTool } from "../../src/tool/read"
+import { Instance } from "../../src/project/instance"
+import { tmpdir } from "../fixture/fixture"
+
+const ctx = {
+ sessionID: "test",
+ messageID: "",
+ callID: "",
+ agent: "build",
+ abort: AbortSignal.any([]),
+ metadata: () => {},
+}
+
+describe("tool.read env file blocking", () => {
+ test.each([
+ [".env", true],
+ [".env.local", true],
+ [".env.production", true],
+ [".env.sample", false],
+ [".env.example", false],
+ [".envrc", false],
+ ["environment.ts", false],
+ ])("%s blocked=%s", async (filename, blocked) => {
+ await using tmp = await tmpdir({
+ init: (dir) => Bun.write(path.join(dir, filename), "content"),
+ })
+ await Instance.provide({
+ directory: tmp.path,
+ fn: async () => {
+ const read = await ReadTool.init()
+ const promise = read.execute({ filePath: path.join(tmp.path, filename) }, ctx)
+ if (blocked) {
+ await expect(promise).rejects.toThrow("blocked")
+ } else {
+ expect((await promise).output).toContain("content")
+ }
+ },
+ })
+ })
+})