Description
I do not like that an agent is able to read all filesystem outside a project directory in Plan mode without asking for permission. I was surprised when I saw it first time.
OpenCode/LLM say that I can trust them, it is safe. As if! (c) Big Bro
So I investigated what was going on under the hood.
And I found following troubles:
| # |
Severity |
Issue |
Location |
Status |
| 1 |
CRITICAL |
WriteTool had NO external_directory check |
write.ts:25-30 |
✅ Fixed |
| 2 |
CRITICAL |
Bash tool only checked write commands, not read commands (ls, cat, etc.) |
bash.ts:111 |
✅ Fixed |
| 3 |
CRITICAL |
Filesystem.contains() was lexical-only (symlinks could escape) |
filesystem.ts:25 |
✅ Fixed |
| 4 |
HIGH |
GrepTool - no path boundary check |
grep.ts |
✅ Fixed |
| 5 |
HIGH |
GlobTool - no path boundary check |
glob.ts |
✅ Fixed |
| 6 |
HIGH |
ListTool - no path boundary check |
ls.ts |
✅ Fixed |
| 7 |
HIGH |
ReadTool - used sync contains() instead of containsSafe() |
read.ts:30 |
✅ Fixed |
| 8 |
HIGH |
EditTool - used sync contains() |
edit.ts:43 |
✅ Fixed |
| 9 |
HIGH |
PatchTool - used sync contains() |
patch.ts:53 |
✅ Fixed |
| 10 |
HIGH |
File.read() and File.list() - symlink bypass |
file/index.ts |
✅ Fixed |
| 11 |
HIGH |
bypassCwdCheck flag could skip all checks |
read.ts:30 |
Documented |
| 12 |
MEDIUM |
Env.all() exposes all environment variables |
env/index.ts |
Not fixed (optional) |
| 13 |
MEDIUM |
Plugin system - arbitrary code execution via config |
plugin/index.ts |
Documented |
| 14 |
MEDIUM |
MCP server command injection via config |
mcp/index.ts |
Documented |
I'm ok with bypassCwdCheck, but others do not make happy.
A containsSafe function resolves symlinks before checking if a path is inside the project directory.
I applied fixes above locally and I could not test it because bun dev and bun dev . commands failed constantly.
I had to go to packages/opencode and run a bun src/index.ts command.
Also I found that some tools may exit from Plan mode on their own without any confirmation.
I got what I expected in result, and then I found an ui bug.
A question is everything above is intended behavior?
I would like to know about possible following steps.
p.s.: I used Opus 4.5 and GLM 4.7 models, both provided almost similar results.
Plugins
Standard installation
OpenCode version
1.1.8
Steps to reproduce
send a prompt: list content of ../ dir
Screenshot and/or share link
No response
Operating System
macOS 15.7.3 (Intel)
Terminal
Terminal
Description
I do not like that an agent is able to read all filesystem outside a project directory in Plan mode without asking for permission. I was surprised when I saw it first time.
OpenCode/LLM say that I can trust them, it is safe. As if! (c) Big Bro
So I investigated what was going on under the hood.
And I found following troubles:
write.ts:25-30ls,cat, etc.)bash.ts:111Filesystem.contains()was lexical-only (symlinks could escape)filesystem.ts:25grep.tsglob.tsls.tscontains()instead ofcontainsSafe()read.ts:30contains()edit.ts:43contains()patch.ts:53file/index.tsbypassCwdCheckflag could skip all checksread.ts:30env/index.tsplugin/index.tsmcp/index.tsI'm ok with bypassCwdCheck, but others do not make happy.
A containsSafe function resolves symlinks before checking if a path is inside the project directory.
I applied fixes above locally and I could not test it because
bun devandbun dev .commands failed constantly.I had to go to
packages/opencodeand run abun src/index.tscommand.Also I found that some tools may exit from Plan mode on their own without any confirmation.
I got what I expected in result, and then I found an ui bug.
A question is everything above is intended behavior?
I would like to know about possible following steps.
p.s.: I used Opus 4.5 and GLM 4.7 models, both provided almost similar results.
Plugins
Standard installation
OpenCode version
1.1.8
Steps to reproduce
send a prompt: list content of ../ dir
Screenshot and/or share link
No response
Operating System
macOS 15.7.3 (Intel)
Terminal
Terminal