fix(core): reject invalid UTF-8 directory paths in serve#38314
Open
extencil wants to merge 1 commit into
Open
Conversation
base64Decode silently produced U+FFFD replacement characters for invalid UTF-8 bytes, which then poisoned workspace directories and broke the web UI. Use TextDecoder fatal mode and fall back to cwd when paths contain U+FFFD.
Contributor
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
Contributor
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
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.
Issue for this PR
Closes #38235
Closes #37764
Type of change
What does this PR do?
While running
opencode serve, I got a session whose directory ended with two U+FFFD replacement characters:.../bin/��. The file picker rejected that path, andprompt_asyncfailed becauseFileSystem.realPathtried to resolve it and gotENOENT.I could reproduce the same path shape with a malformed route segment. For example,
__8decodes to the bytesFF FF, and the non-fatalTextDecoderturns those into��. The app uses that as the directory, and the SDK sends it as%EF%BF%BD%EF%BF%BDinx-opencode-directory.InstanceContextMiddlewaredecodes the header, thenInstanceStorecallspath.resolve()on the relative��value and ends up with<cwd>/��. That matches what showed up in my log.I do not have the original browser URL from that run, so
__8is only a minimal reproduction of the bug, not a claim that it was the exact route segment. The database also had older session directories with literal U+FFFD characters, so values like this had already been persisted before.The fix makes
base64Decodeuse a fatal UTF-8 decoder. The app'sdecode64wrapper already handles decode errors, so malformed route segments now go through the existing invalid-route behavior. For values that already contain U+FFFD, the HTTP routing, location, decoded instance context, andInstanceStore.load/reloadpaths fall back toprocess.cwd()instead of initializing that directory.How did you verify your code works?
bun test test/server/httpapi-workspace-routing.test.ts test/project/instance.test.ts: 18 passed, 0 failedbun turbo typecheck: 30 tasks passedbun run script/build.ts --single --skip-embed-web-ui --skip-install: built the Linux x64 binary and passed its--versionsmoke test__8->��->%EF%BF%BD%EF%BF%BD-><cwd>/��with the old decoder, then confirmed the fatal decoder rejects the same bytesI reproduced the original failure with
./opencode serve --log-level DEBUG --pure --print-logs. I have not rerun that browser flow after adding the final instance-loading guard.Screenshots / recordings
N/A
Checklist