Ver Fonte

fix(config): tolerate invalid OPENCODE_PERMISSION JSON (#28388)

Kit Langton há 3 meses atrás
pai
commit
c035c35eba

+ 3 - 1
packages/core/src/flag/flag.ts

@@ -21,7 +21,6 @@ export const Flag = {
   OPENCODE_DISABLE_PRUNE: truthy("OPENCODE_DISABLE_PRUNE"),
   OPENCODE_DISABLE_TERMINAL_TITLE: truthy("OPENCODE_DISABLE_TERMINAL_TITLE"),
   OPENCODE_SHOW_TTFD: truthy("OPENCODE_SHOW_TTFD"),
-  OPENCODE_PERMISSION: process.env["OPENCODE_PERMISSION"],
   OPENCODE_DISABLE_AUTOCOMPACT: truthy("OPENCODE_DISABLE_AUTOCOMPACT"),
   OPENCODE_DISABLE_MODELS_FETCH: truthy("OPENCODE_DISABLE_MODELS_FETCH"),
   OPENCODE_DISABLE_MOUSE: truthy("OPENCODE_DISABLE_MOUSE"),
@@ -59,6 +58,9 @@ export const Flag = {
   get OPENCODE_PURE() {
     return truthy("OPENCODE_PURE")
   },
+  get OPENCODE_PERMISSION() {
+    return process.env["OPENCODE_PERMISSION"]
+  },
   get OPENCODE_PLUGIN_META_FILE() {
     return process.env["OPENCODE_PLUGIN_META_FILE"]
   },

+ 5 - 1
packages/opencode/src/config/config.ts

@@ -703,7 +703,11 @@ export const layer = Layer.effect(
         }
 
         if (Flag.OPENCODE_PERMISSION) {
-          result.permission = mergeDeep(result.permission ?? {}, JSON.parse(Flag.OPENCODE_PERMISSION))
+          try {
+            result.permission = mergeDeep(result.permission ?? {}, JSON.parse(Flag.OPENCODE_PERMISSION))
+          } catch (err) {
+            log.warn("OPENCODE_PERMISSION contains invalid JSON, skipping", { err })
+          }
         }
 
         if (result.tools) {

+ 28 - 0
packages/opencode/test/config/config.test.ts

@@ -2079,6 +2079,34 @@ describe("OPENCODE_DISABLE_PROJECT_CONFIG", () => {
   })
 })
 
+// Regression for #28206: malformed OPENCODE_PERMISSION JSON used to crash
+// the app on startup with an unhandled SyntaxError. Loading the config with
+// an invalid JSON value in this env var should not throw.
+describe("OPENCODE_PERMISSION env var", () => {
+  test("does not crash when OPENCODE_PERMISSION contains invalid JSON", async () => {
+    const original = process.env["OPENCODE_PERMISSION"]
+    process.env["OPENCODE_PERMISSION"] = "{invalid"
+    try {
+      await using tmp = await tmpdir()
+      await withTestInstance({
+        directory: tmp.path,
+        fn: async (ctx) => {
+          const config = await load(ctx)
+          // We don't assert on permission shape; the regression is that
+          // load() throws before returning anything.
+          expect(config).toBeDefined()
+        },
+      })
+    } finally {
+      if (original !== undefined) {
+        process.env["OPENCODE_PERMISSION"] = original
+      } else {
+        delete process.env["OPENCODE_PERMISSION"]
+      }
+    }
+  })
+})
+
 describe("OPENCODE_CONFIG_CONTENT token substitution", () => {
   test("substitutes {env:} tokens in OPENCODE_CONFIG_CONTENT", async () => {
     const originalEnv = process.env["OPENCODE_CONFIG_CONTENT"]