You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Symlink inside the project bypasses external_directory, and the permission prompt shows the wrong path #40160
The project containment check is pure path arithmetic and does not resolve symlinks, but the file read or write that follows does. A symlink inside the project pointing somewhere outside it passes the check, so external_directory never fires and the operation lands outside the project.
The prompt you do get is also misleading rather than just absent. read and edit show the path relative to the worktree, so you see the in-project link path while a different file is being opened.
Windows does not have this, because it already resolves the path at this point. It is POSIX only.
The part worth adding: the path that reaches the permission matcher is the relativized one, so an absolute deny rule on the real location cannot match it.
A rule like /tmp/symlink-probe/secret/**: deny is evaluated against link/creds.txt and does not match. So this is not only a missing external_directory prompt — an explicit deny rule covering the symlink's target is silently inert for access through the link. A user who has denied a sensitive directory still gets the read.
Verified on dev. permissionPath lives in packages/opencode/src/project/instance-context.ts; FSUtil.contains in packages/core/src/fs-util.ts.
Worth noting that realpath is not a free fix: resolving on every check costs a syscall per permission evaluation, and resolving only the containment check while leaving the emitted path lexical would fix the prompt-absence half but leave the deny-rule half broken. Both halves want the resolved path, which also changes what users see in prompts for legitimately symlinked project layouts.
Activity
github-actions commentedon Aug 2, 2026
This issue might be a duplicate of or closely related to existing issues. Please check:
external_directoryfor in-project symlinks pointing outside the project). Your bug report documents the current vulnerable behavior that [FEATURE]: allow external symlink targets via external_directory consent #30788 wants addressed — they may be resolved together.If you believe this is a distinct report worth tracking separately, please let a maintainer know.
iceteaSA commentedon Aug 9, 2026
Confirming this independently, and adding one detail about the second half — the misleading prompt path — because it is worse than cosmetic.
The containment check is
FSUtil.contains, which ispath.relativeplus a..test, so it is purely lexical:Same file, two paths, opposite verdicts.
The part worth adding: the path that reaches the permission matcher is the relativized one, so an absolute deny rule on the real location cannot match it.
A rule like
/tmp/symlink-probe/secret/**: denyis evaluated againstlink/creds.txtand does not match. So this is not only a missingexternal_directoryprompt — an explicit deny rule covering the symlink's target is silently inert for access through the link. A user who has denied a sensitive directory still gets the read.Verified on
dev.permissionPathlives inpackages/opencode/src/project/instance-context.ts;FSUtil.containsinpackages/core/src/fs-util.ts.Worth noting that
realpathis not a free fix: resolving on every check costs a syscall per permission evaluation, and resolving only the containment check while leaving the emitted path lexical would fix the prompt-absence half but leave the deny-rule half broken. Both halves want the resolved path, which also changes what users see in prompts for legitimately symlinked project layouts.0xSemizzz commentedon Oct 4, 2026
@iceteaSA Given the permission deny-rule bypass you pointed out, do you think #40160 warrants a CVE/security advisory?
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊