Repository navigation
Conversation
… as state machines (anomalyco#61886)
…line before applying them (anomalyco#61913)
…with explicit state machines (anomalyco#61917)
…rd as state machines (anomalyco#61923)
…cit state machines (anomalyco#61927)
…and zoom as state machines (anomalyco#61926)
Merges anomalyco/opencode dev at 64f2403 (merge base e1b3b05), which carries the v2.2.6 code including the fs.read/media download headers and cross-site API check (anomalyco#62422) and the session_move external_directory check (anomalyco#62204). Fork overlays re-applied at upstream's new owners: - run: #434 setup and admission deadlines wrap switchAgent, switchModel and prompt admission inside the new lifecycle; the first execution-end wait is captured before consuming events so a fast terminal event is not missed. - app: hidden-provider filters move into the connect controller and the directory cache getter; the Claude Agent setup view and its e2e test go. - plugin-browser: unretrieved-command replay, inventory wait and the retired-session ban move into the attachment machine. - core: subagent recovery reads and writes through part rows. - identity: shuvcode pairing commands; fork CI keeps its six workflows. bun.lock regenerated with bun install. Co-authored-by: Cursor <cursoragent@cursor.com>
…igins session_move now asks external_directory outside the project (anomalyco#62204): a rejection queues nothing, an approved move asks once, and a move into a project worktree does not ask. A child session cannot move past a parent agent's external_directory deny (#475). Cross-site API calls from lookalike localhost and opencode.ai hosts get 403 (anomalyco#62422). Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit 5f6460d568bf652363614016664f72d2f137da1c)
Subagent sessions sync their family root for permissions and forms (#429), so the upstream test needs the parent session. Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit bc84f066a39a3c644641147dbf7ac46807ee6646)
Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit 331c6a1ec3a07b0591bb6e81291c80be136060b5)
Metadata only. The upstream release commit dc2ffcf (v2.2.6) changes only version fields and CHANGELOG.md, and its parent 33f94fc is an ancestor of the merged upstream/dev 64f2403, so this tree already has every v2.2.6 code change. The release commit is not merged. Co-authored-by: Cursor <cursoragent@cursor.com>
The cross-site guard decided whether a request targeted the API with a case-sensitive WHATWG pathname prefix test, while the router folds case, decodes percent escapes and collapses duplicate slashes. `/API/...`, `/%61pi/...` and `//api/...` reached API handlers without the guard on ServerFetch and on ServerProcess without the CLI web shell in front. Classify the request URL with the router's own FindMyWay matcher in its default configuration instead, keeping the artifact view exemption as a route in the same matcher. Co-authored-by: Cursor <cursoragent@cursor.com>
Bring over upstream's v2.2.6 section from the release commit's changelog text only, and add a fork section for the cross-site guard hardening. Co-authored-by: Cursor <cursoragent@cursor.com>
Seed a session before the denied cross-site creates, updates and deletes and assert the list is unchanged, and cover plain /api reads, creates, updates and deletes from native clients and the same origin, through both ServerProcess and ServerFetch. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
The upstream dev merge adds files that fail the fleet hygiene job on PR #477: placeholder and story-fixture home paths, `@/home/<segment>` import aliases, an upstream developer's path in a services/site code comment, and intentional SC2043 single-value loops in services/site/script/press-media.sh. Allowlist them by exact string or single file instead of editing upstream files. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the whole-file exceptions from the previous commit: - press-media.sh: define `set=locked` once instead of looping over a single value, so shellcheck scans the file with no SC2043 warning and no allowlist entry. The commands the script runs are unchanged. - source-logo.ts: drop an upstream developer's worktree path from a code comment instead of exempting the file. - Allow the sidebar alias imports and the story fixture home as exact text tokens (`/home/projects`, `/home/sessions`, `/Users/alex`) instead of exempting whole files. Co-authored-by: Cursor <cursoragent@cursor.com>
Owner
Author
|
The ACP close path deletes a session when its message history is empty, but an accepted prompt can still be waiting in |
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.
chore(sync): merge upstream dev and audit v2.2.6 gaps
Base:
integration-v2· Head:sync/upstream-dev-audit-v2.2.6Summary
This brings
integration-v2up to upstream OpenCodedevwith one--no-ffmerge at a frozen pin that contains v2.2.6. Every Shuvcode overlay is kept. It also fixes a cross-site guard bypass that the review found in upstream's anomalyco/opencode#62422 guard, and it sets the fork version to2.2.6-shuv.1; this PR does not publish a release.The v2.2.6 release commit is an audit reference only and is not merged. It changes only version fields and
CHANGELOG.md, and this branch already contains every v2.2.6 code change.Two low-severity findings are disclosed and not fixed, by the owner's decision: R2-F1 (unresolved upstream bypass) and R2-F2 (deferred release-tooling gap). Details are below.
SHAs
origin/integration-v2c24144997b144545638085140ceb42f42a1a4998devpin, merged and frozen64f2403ffa55b8bbbd7c05f79b630f866f0ae66adevtip at the last fetch, not mergedc045c7cfdcac42db466b3559ea74d7cf02015126v2.2.6tag, audit reference, not mergeddc2ffcf8bf26f9e669b6aa22b95f50e12be15e064bb0ded8a7f2959f03199461be9bc18a28559d6afc9630a2b46083589a583cd7e0e5ba0095f98bfa37da03f164b3eb7273cfebc8d7d1b9e52068b8d8Reviewed SHA versus final head
fc9630a2b46083589a583cd7e0e5ba0095f98bfais the last commit that changes product code or docs. It is the SHA the second review round reviewed, and the SHA every build, compiled-binary probe, smoke test and full e2e run below ran on.37da03f164b3eb7273cfebc8d7d1b9e52068b8d8is the final head. It is one test-only commit on top of the reviewed SHA:git diff --name-status fc9630a2b4..37da03f164isM packages/server/test/request-site.test.ts(+53, −16), and nothing else: no fixture, snapshot, config, dependency, lockfile or production file.Commits (first parent)
9be458868bc90e440b3b219f064a62c2c5fca1aechore(sync): merge upstream dev through 64f2403 (v2.2.6)bed62da58721d9fcf26da18be28a3ad3ea698fcdtest(security): cover session_move authorization and lookalike API origins597dc63c6d78565bf526a9e12ec416244b09a5c5test(tui): serve the parent session in the subagent navigation fixtureb2428136a3c57d21a9c04d49182c7eeed2e9ceeedocs: note upstream removed the shuvcode/run exportb3a198c0a4b0b1cd4630d1ec1a037e39b54a46b6chore: set workspace versions to 2.2.6 and shuvcode to 2.2.6-shuv.14bb0ded8a7f2959f03199461be9bc18a28559d6afix(server): match cross-site API paths the way the router doesfc9630a2b46083589a583cd7e0e5ba0095f98bfadocs: add v2.2.6 and v2.2.6-shuv.1 release notes (reviewed SHA)37da03f164b3eb7273cfebc8d7d1b9e52068b8d8test(server): prove denied cross-site writes leave sessions unchanged (test-only, not reviewed)From the base to the final head this is 325 commits, 3,902 files, +401,148 and −68,565 lines, almost all of it upstream. The fork's whole delta over the upstream pin is 623 files, +36,302 and −6,550 lines. The hand-written merge resolution (
git show --remerge-diff 9be458868b) touches 28 files, +599 and −2,553 lines.What the merge brings
session_moveasks forexternal_directorybefore leaving the project.ClaudePluginas the Anthropic provider and the hidden Claude Agent provider;runwithautostart: false;devcommits after the pin, throughc045c7cfdcac42db466b3559ea74d7cf02015126. None is a security fix; 84 of their 96 files are underservices/site. Moving the pin needs a separate decision.Cross-site guard fix (commit 6)
The bug. The guard from anomalyco/opencode#62422 tested a case-sensitive, undecoded
/apiprefix on the WHATWG pathname. The router dispatches with FindMyWay, which folds case, decodes percent escapes once and collapses duplicate slashes. As a result, spellings such as/API,/Api,/%61piand//apireached API handlers without the cross-site check, on bothServerFetchandServerProcess. The CLI binary never returned API data for those spellings: it served the web shell, or 405 forPOST /API/session.The fix.
packages/server/src/request-site.tsnow classifies paths with the router's own matcher (FindMyWay.make(), the configurationHttpRouteruses), keeping the artifact-view exemption.Tests are in
packages/server/test/request-site.test.tsand run through bothServerProcessandServerFetch. This list describes the file at the final head; commit 8 changed the second and third items./apireads return the file. Native and same-origin creates, renames and deletes succeed, and the resulting session list is asserted exactly. This is the new normal-traffic test./APIand/%61pistill work, and the mixed-case artifact view is still exempt.ServerProcess, raw-socket request targets are classified the way the router reads them.Mutation check. The pre-fix guard (byte-identical to the pin's), a lowercase-only patch and an unwired guard each fail the cross-site tests. The legitimate-traffic tests pass under every mutant.
Known issues, disclosed and not fixed
R2-F1 (low, UNRESOLVED): an absolute-form request target bypasses the guard's Origin check
The owner accepted this for this sync and decided not to patch it. It is upstream behavior: the pin's own guard gives the same result.
Mechanism.
request.headers.host.headers.hostwith the target's authority.Repro, raw TCP to a
ServerProcess.startserver:ServerProcess.startServerProcess.startshuvcodebinary, a preview build offc9630a2b4, in a network namespace (the reviewer's run)ServerFetch.makeControls with the same headers:
POST /api/sessiongets 403;127.0.0.1gets 403;A request reaches it only if all of these hold:
ServerProcess, which every CLI mode uses) with an absolute-form target.Sec-Fetch-Site: cross-siteorsame-site, and it is not a navigation.Proxies and deployments:
packages/plugin-browser/src/proxy.ts). Tested: it rewrites absolute-form targets to origin-form before forwarding, so it did not deliver this request.Host(the page's target) equals its Origin was accepted (200, session created). This needs that hostname to resolve to the server's machine on the tunnel side.pair --remote(ShuvTunnel) and desktop SSH forwarding pass bytes through unchanged, according to the code. Neither was tested.This PR makes no claim that R2-F1 is unreachable from a browser. No browser was tested.
The
2.2.6-shuv.1changelog line saying the CLI was not exposed refers to the path spellings fixed in commit 6. R2-F1 is a different mechanism, and it does reach the CLI binary.A fix would have to stop trusting the rewritten
Hostfor this check;request.originalUrlkeeps the absolute form. No fix was designed or tested.R2-F2 (low, DEFERRED): bare upstream versions are accepted on
nextandbetaScript.version(packages/script/src/index.ts:39-62) enforces the<upstream>-shuv.<n>shape only on thelatestchannel:publish.ymlwithversion: 2.2.6andchannel: nextorbetaresolves and builds a bare2.2.6.latestrejects it: "Release versions must be -shuv., got 2.2.6".The gap has been unchanged since the base: no release-path file differs from it. It is deferred to separate release-tooling work, and
nextandbetabehavior is unchanged in this PR.Version:
2.2.6-shuv.12.2.6, andpackages/cli/package.jsonis2.2.6-shuv.1.CHANGELOG.mdcarries upstream's v2.2.6 section line for line. Av2.2.6-shuv.1section above it notes the fork release and the guard fix as fork-specific hardening. The upstream release commit is not cherry-picked.--version. The release-channel builds offc9630a2b4printshuvcode v2.2.6-shuv.1andshuvcode-node v2.2.6-shuv.1.OPENCODE_CHANNEL=latestresolves2.2.6-shuv.1; npmlatestis2.2.5-shuv.2.OPENCODE_VERSION=2.2.6-shuv.1resolves the same.build.tsandpack.tswrite versions only into stageddist/*/package.jsonmanifests, never into the sourcepackage.json.script/release.tsdispatchesrelease.yml, which does not exist in this fork.Verification
On the final head
37da03f164(test-only; targeted checks only)cd packages/server && bun test test/request-site.test.tscd packages/server && bun test test/request-site.test.ts --rerun-each 10cd packages/server && bun run testbun run checkcd packages/server && bun typechecktsccd packages/server && bun run typecheck:tscThe tests ran under a throwaway
HOMEand XDG roots.git status --shortwas empty afterwards. Builds, compiled-binary probes, smoke tests and e2e were not rerun on this commit. It changes only a server test file, which is not part of either build. For the app e2e, only two things were inspected:packages/app/e2e, and neither Playwright config, importsServerProcess,ServerFetch,@opencode/serverorRequestSite;packages/app/e2e/utils/mock-server.ts.On the reviewed SHA
fc9630a2b4jjis not installed), 0 failbun run check, a forced uncached typecheck, the CItsctypecheck, and the Effect rulespackages/clientbun run generate--versionis2.2.6-shuv.1runwithautostart: falseserve --stdiochild, no leftover process, no service registrationsession_move, shuv1337/shuvcode#475 deny inheritance)Every compiled binary ran in a private network namespace, so none could bind the default service port
0x1337.Package suites against the base (on round 1's
b3a198c0a4; onlyserverchanged after it)Every package suite has 0 failures on both sides, except these two, both judged pre-existing:
core: 11GitLabPlugin OAuthtests on each side. They need local port 8080, which an unrelated host process holds. In a private network namespace the file passes 19 of 19 on both sides.cli: "concurrent service processes elect one server", failed once on the final side under full-suite load. It is a readiness race that exists on the base by design: the registration is written about 66 ms before ready on both sides. Run alone it passes 10 of 10 on each side, and the fullclirerun passed on both.E2E
Full app e2e on
fc9630a2b4(bun --cwd packages/app test:e2e:built): 746 pass, 3 fail out of 749. None of the three failures is specific to this branch:review.spec.ts:539"file tree expands Windows paths and scrolls long names in both directions"b3a198c0a4, andpackages/appis unchanged between the two. The test body is identical on all three. A load flake.tabs.spec.ts:2068"the inbox waits for initial requests and orders attention by waiting age"inbox.tsxis identical to the pin. A load flake that predates this branch.terminal.spec.ts:45"after a reload, the close shortcut closes the restored terminal"--repeat-each=10rounds: final 16 of 20, upstream pin 16 of 20, with the same failing assertion (the secondpty_shellsocket never connects). The base fails it the same way: 3 of 5 alone. An upstream flake; no terminal or PTY source differs from the pin.In round 1 the final side had 748 pass and 1 fail, against 659 pass and 4 fail on the base. All four tests that failed there were separated the same way, as load or upstream flakes.
Unverified
runwith a model reply is UNVERIFIED.b3a198c0a4, the model call was refused with "OpenCode 1.18.0 or newer is required to use the free tier". The likely cause is the preview version string, but that is not proven.fc9630a2b4ran with loopback only, sorunretriedECONNREFUSEDuntil it was killed.Review
Two review rounds ran, with the same model choices in both: Claude Opus 5.5 and
composer-2.5-fast. In round 2 the Opus seat was the round-1 agent resumed with its context, and the composer seat was a fresh agent.b3a198c0a4, found the medium path-spelling bypass. Commit 6 fixes it, and both seats confirmed the fix in round 2.fc9630a2b46083589a583cd7e0e5ba0095f98bfa, found R2-F1 and R2-F2.37da03f164was not reviewed.Effort: the Opus seat inherited the parent's setting, whose exact value is unknown.
composer-2.5-fasthas no effort setting.Feature flag
None. This is an upstream sync plus a security fix, and fixes do not get flags.