Skip to content

Instance.containsPath() compares mixed canonical/non-canonical paths #16660

Closed as not planned

Description

@brndnblck

Description

After #16651, Instance.directory is always the canonical (symlink-resolved) path. But the filepath argument to containsPath() comes from various tool callers (bash.ts, external-directory.ts, file/index.ts) and is not canonicalized. Similarly, Instance.worktree may not be canonical.

This means a symlinked path passed to containsPath() won't match the canonical Instance.directory, causing:

  • bash.ts:89,129 — false negatives on the boundary check, triggering unnecessary external_directory permission prompts for paths that are actually inside the project
  • external-directory.ts:17 — same false negative, prompting for permission when none is needed
  • file/index.ts:503,585 — File.read() and File.tree() incorrectly reject symlinked paths within the project

The existing TODO comments at file/index.ts:501 and :583 acknowledge this as a known limitation ("lexical containment check"). #16651 makes it slightly more pronounced because Instance.directory is now always canonical while inputs remain uncanonicalized.

A fix would be to canonicalize the filepath argument inside containsPath():

containsPath(filepath: string) {
  const resolved = Filesystem.resolve(filepath)
  if (Filesystem.contains(Instance.directory, resolved)) return true
  if (Instance.worktree === "/") return false
  return Filesystem.contains(Instance.worktree, resolved)
}

Steps to reproduce

  1. Create a symlink to a project directory: ln -s ~/myproject ~/myproject-link
  2. Run opencode from the symlinked path: cd ~/myproject-link && opencode
  3. Use a tool that accesses a file via its symlinked path (e.g., bash tool with cwd set to the symlink path, or file read via symlink)
  4. Observe unnecessary external_directory permission prompts for paths that are actually inside the project

Operating System

macOS, Linux (anywhere symlinks are common)

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 9, 2026
  2. github-actions commented on Mar 9, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of (or closely related to) existing issues. Please check:

    If #16660 is intentionally a more focused/actionable follow-up to #16647, it may be worth linking them explicitly or closing one in favor of the other.

  3. assigned and unassigned on Apr 26, 2026
  4. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  5. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions