fix(config): guard env-var JSON parsing against invalid input#28250
Draft
kitlangton wants to merge 1 commit into
Draft
fix(config): guard env-var JSON parsing against invalid input#28250kitlangton wants to merge 1 commit into
kitlangton wants to merge 1 commit into
Conversation
d219b2e to
57e24bd
Compare
57e24bd to
1d2e75e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two unguarded
JSON.parse(<env var>)calls at config boundaries used to crash startup on malformed input. After a design pass we landed on a principled split:OPENCODE_PERMISSION). Silently defaulting to "no restrictions" when the user intended restrictions is dangerous.OPENCODE_ROUTE). Falling back to the home route is benign.Both behaviors now flow through a tiny shared helper module so future env-var-fed config boundaries pick the appropriate side without re-implementing JSON-parse + schema-decode + log-or-throw plumbing each time.
New helpers —
packages/opencode/src/util/json.tsInvalidConfigError—Schema.TaggedErrorClasscarrying{ source, value, reason }. Thereasonis the Schema issue's stringification, so the error always names which field is wrong.requireJsonConfig(raw, schema, source): S["Type"]— synchronously throwsInvalidConfigErroron malformed JSON or schema mismatch. Used at safety boundaries.tryJsonConfig(raw, schema, source): Option<S["Type"]>— returnsNonefor absent / empty / malformed / shape-mismatched input, logging a structuredwarnso the user can debug. Used at preference boundaries.Both share the same underlying decode pipeline (
Schema.UnknownFromJsonString→Schema.decodeUnknownResult(schema)); they only differ in how they signal failure.Surfaces updated
packages/opencode/src/config/config.ts—OPENCODE_PERMISSIONnow usesrequireJsonConfig(..., ConfigPermission.Info, "OPENCODE_PERMISSION"). The previous warn-and-skip path is gone; an invalid permission env-var halts startup. Closes OPENCODE_PERMISSION JSON parsing crashes on invalid input #28206.packages/opencode/src/cli/cmd/tui/context/route.tsx—OPENCODE_ROUTEnow usestryJsonConfig(..., RouteSchema, "OPENCODE_ROUTE")with a tightSchema.Unioncovering the three Route variants the env-var realistically carries. Falls back toHOME_ROUTEonNone.packages/opencode/src/cli/error.ts—FormatErrornow matchesInvalidConfigErrorand renders a multi-line friendly message beforeprocess.exit(1)instead of dumping a stack trace.The helpers are positioned to be used by #28172 (theme env var) and the future
OPENCODE_AUTH_CONTENTwork — both are UX-preference boundaries that fittryJsonConfigcleanly.Test coverage
packages/opencode/test/util/json.test.ts— 9 tests coveringrequireJsonConfig(success, malformed JSON, shape mismatch,_tagshape) andtryJsonConfig(success, undefined, empty, malformed JSON, shape mismatch) with a syntheticPointSchema.packages/opencode/test/config/permission-env.test.ts— 5 tests assertingInvalidConfigErrorcarries the right source/value/reason on malformed JSON and shape mismatch, plus success paths for Action shorthand, flat rules, and nested per-pattern bash rules.packages/opencode/test/cli/tui/route-env.test.ts— 7 tests coveringNonefor undefined / empty / malformed JSON / schema mismatch, andSomefor home / session / plugin routes.Test plan
bun typecheckinpackages/opencode(clean)bun run test test/util/json.test.ts(9 pass)bun run test test/config/permission-env.test.ts(5 pass)bun run test test/cli/tui/route-env.test.ts(7 pass)bun run test test/config/(168 pass, no regressions)OPENCODE_PERMISSION='not json'and confirm startup halts with the formattedInvalidConfigErrormessage (no stack trace)OPENCODE_PERMISSION='{"bash":"banana"}'and confirm the same friendly halt with a "banana is not a valid Action" reasonOPENCODE_ROUTE='not json'and confirm it falls back to the home route with a warn log