You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Auth.all() bypasses schema validation for OPENCODE_AUTH_CONTENT and silently swallows JSON parse errors #34075
In packages/opencode/src/auth/index.ts, the Auth.all() function has two code paths for loading auth data: a file-based path that applies schema validation via Record.filterMap(decode), and an env-var path (OPENCODE_AUTH_CONTENT) that returns JSON.parse(...) directly without validation. JSON parse errors are also silently swallowed by an empty catch block, falling through to the file path even though the user explicitly set the env var. The result is that malformed OPENCODE_AUTH_CONTENT silently falls back to file-based auth, and invalid auth entries (wrong type, missing fields, non-object values) reach downstream provider code that switches on info.type.
Auth.all() in packages/opencode/src/auth/index.ts has two code paths for loading auth data: a file-based path and an env-var path (OPENCODE_AUTH_CONTENT). The file path applies schema validation via Record.filterMap(decode) to filter out entries that don't conform to the Auth.Info schema. The env-var path returns JSON.parse(...) directly without any validation, and JSON parse errors are silently swallowed by an empty catch block.
Reproduction:
import { Effect } from "effect"
import { Auth } from "../../src/auth"
// Case 1: invalid JSON is silently swallowed, falls through to file read
process.env.OPENCODE_AUTH_CONTENT = "{not valid json"
const data1 = await Effect.runPromise(Auth.all())
// Expected: AuthError indicating the env var is corrupt
// Actual: silently falls through to file-based auth, no error
// Case 2: invalid entry (wrong type) passes through unvalidated
process.env.OPENCODE_AUTH_CONTENT = JSON.stringify({
anthropic: { type: "api", key: "valid-key" },
bad: { type: "unknown_type", key: "x" }, // not a valid Auth.Info
notAnObject: "string",
})
const data2 = await Effect.runPromise(Auth.all())
// Expected: data2.bad and data2.notAnObject are filtered out (matching file-path behavior)
// Actual: data2.bad === { type: "unknown_type", key: "x" }, data2.notAnObject === "string"
// Downstream code that switches on info.type (e.g. provider/auth.ts:167) gets unexpected shapes
delete process.env.OPENCODE_AUTH_CONTENT
Screenshot and/or share link
No response
Operating System
N/A — pure TypeScript code in packages/opencode/src/auth/index.ts. Reproduces on any OS.0
The bug was in packages/opencode/src/auth/index.tsAuth.all(). The env-var path of OPENCODE_AUTH_CONTENT returned JSON.parse(...) directly, bypassing the Record.filterMap(decode) schema validation that the file path applies — so malformed entries (unknown_type, non-object values, missing fields) reached downstream provider code that switches on info.type. The empty catch block silently swallowed JSON parse errors, falling through to file-based auth even though the user had explicitly set the env var.
The fix replaces the bare try/catch with Effect.try({ try, catch }) to surface parse errors as AuthError, rejects non-object top-level JSON (arrays, primitives, null), and applies the same Record.filterMap(decode) validation that the file path already uses.
Activity
lexlian commentedon Jun 30, 2026
@1volt12 @StarpTech , I fixed the issue with PR #34654.
The bug was in
packages/opencode/src/auth/index.tsAuth.all(). The env-var path ofOPENCODE_AUTH_CONTENTreturnedJSON.parse(...)directly, bypassing theRecord.filterMap(decode)schema validation that the file path applies — so malformed entries (unknown_type, non-object values, missing fields) reached downstream provider code that switches oninfo.type. The emptycatchblock silently swallowed JSON parse errors, falling through to file-based auth even though the user had explicitly set the env var.The fix replaces the bare
try/catchwithEffect.try({ try, catch })to surface parse errors asAuthError, rejects non-object top-level JSON (arrays, primitives, null), and applies the sameRecord.filterMap(decode)validation that the file path already uses.github-actions commentedon Aug 30, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.