Skip to content

Notes from testing: TUI workspace init, SSE cleanup, path handling, and stub edge cases #2

Description

@adi-IL

Hey! I was looking around for a remote SSH workspace setup for OpenCode, partly because omp (oh-my-pi) has its own built-in remote SSH flow and I figured OpenCode should have something similar. I didn't see anything official in core, so finding this project was really cool. The architecture with the Go stub is super clean.

I spent some time reading through the codebase and testing it out, and ran into a few snags and edge cases between the Go stub and the TypeScript plugin that seemed worth sharing:

  1. TUI workspace creation: When creating a workspace from OpenCode's TUI (/warp), extra.provider is not passed in, so resolveProvider currently throws right away. Falling back to the default or first configured provider when extra.provider is omitted gets it through cleanly.
  2. Stub binary path: stubPath is resolved relative to process.cwd(). Unless OpenCode happens to be launched directly inside plugin/, it cannot find the binary to upload.
  3. SSE connection cleanup in the stub: Events calls h.events.Subscribe(), but there is no unsubscribe mechanism when the client disconnects, and <-ch in defer can block indefinitely. Over multiple reconnects, that can leave channels registered and goroutines hanging.
  4. Empty pattern check: In PermissionReply, accessing p.Patterns[0] will panic if Patterns is empty. Adding a quick length check avoids crashing the stub.
  5. Path traversal and normalization: In matchPattern, prefix matching happens on raw strings without filepath.Clean or resolving symlinks, so something like /approved/dir/../../etc could match an approved prefix. Also, session and workspace deletion and creation use client-provided IDs directly in filepath.Join, which could allow navigating outside the state directory if an ID has ../.
  6. Token file in /tmp: Both ssh.ts and setup-host.sh write auth tokens to static /tmp paths with default permissions. On shared machines, using 0600 permissions or piping the token directly over SSH stdin avoids leaving world-readable token files around.
  7. Token trailing newline: os.ReadFile(tokenFile) is not trimmed of whitespace, so if the token file has a trailing newline, authorization headers end up returning 401.

Would you be open to a pull request, or a couple smaller ones, to fix these up? Happy to contribute and test them out if you would like.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions