Repository navigation
Description
Summary
With pure default permissions (no permissions key in config), writes to paths outside the session Location/worktree (e.g. /tmp from a ~/Desktop session) complete silently with no permission dialog, even though the built-in base policy resolves external_directory to ask. Adding an identical explicit global rule (external_directory * -> ask) makes the TUI prompt correctly. deny rules are enforced correctly.
Environment
- opencode version: 2.0.25
- OS: Linux 7.2.9-1-cachyos (linux x64)
- Terminal: kitty (TERM=xterm-256color, COLORTERM=truecolor)
- Shell: /usr/bin/fish
- Install/channel: latest
- Active plugins: none found in config
Reproduction
- Use default config with no
permissionskey. Open a session in~/Desktop(non-git dir, project worktree =~/Desktop, verified inprojecttable). - Have the agent create a file in
/tmp(outside Location and worktree). - Observe: no "Permission required" dialog appears; the file is created.
- Add a global explicit rule:
{ "action": "external_directory", "resource": "*", "effect": "ask" }. - Retry the same write. Observe: the TUI now shows "Permission required / Access external directory /tmp" with Allow once / Always allow / Reject. Choosing "Allow once" lets the write proceed.
- Remove the explicit rule and retry: silently allowed again, no dialog.
- Sanity checks:
{ "action": "external_directory", "resource": "/tmp/*", "effect": "deny" }blocks the write immediately withpermission.rejected: external_directory, so rule loading and enforcement work.
Expected Behavior
Per the V2 permissions docs, a path outside the active Location and project worktree needs external_directory approval, and the built-in default for it is ask — so step 3 should have shown a permission dialog.
Actual Behavior
The built-in default ask for external_directory never surfaces a dialog; the operation proceeds as if allowed. Only user-configured ask rules prompt. Verified consistently across multiple attempts, including after opencode service restart (rules out a stale-service artifact).
Additional Context
- TUI is configured with
session.permissions: "prompt"incli.json, and interactive dialogs render fine (thequestiontool dialog appears normally), so this is not a client rendering problem. - No saved "Always allow" approvals covered the tested paths (checked the
permissiontable; test-created approvals were deleted afterwards). - Even with
OPENCODE_LOG_LEVEL=DEBUG, the server log contains noevaluated permissionlines for these tool calls in 2.0.25, so the evaluation decision itself is not observable from logs. - Related: External directory permission does not work on Windows #11042 (same symptom class on Windows, closed).
- Workaround: add an explicit global
{ "action": "external_directory", "resource": "*", "effect": "ask" }rule so all external access prompts as documented.
Activity
opencode-agent commentedon Oct 11, 2026
Thanks for the detailed report and the careful sanity checks!
The behaviour you're seeing is intentional as of 2.0.25. #53585 ("stop asking for external directory access by default") removed the built-in
external_directory * → askrule. The default agent ruleset is now* → allowplus the.envread prompts, so paths outside the Location and worktree are allowed without a prompt. Versions 2.0.23 and 2.0.24 still had the ask rule, which is why the docs describe it.The permissions docs weren't updated with that change, and they still list
external_directory → askas a default. Sorry for the confusion. I've flagged the outdated docs for the maintainers.The rule you're using as a workaround is the supported way to get prompts back:
{ "permissions": [ { "action": "external_directory", "resource": "*", "effect": "ask" } ] }I'm treating this as a request to go back to prompting by default. Maintainers will consider it alongside the docs fix.
Related issues:
external_directorycould not be overriddenexternal_directory: "deny"is bypassed by thebashtool (macOS) #54465: shell commands getting aroundexternal_directoryruleskovaacs commentedon Oct 12, 2026
Adding the communication gap to this report, since it's the other half of the problem.
The behaviour change (PR #53585, shipped in v2.0.25) wasn't surfaced anywhere a user would see it:
CHANGELOG.md(the "reviewed V2 release notes" file) starts at v2.0.26, created in feat(release): write reviewed V2 release notes to CHANGELOG.md #53964 — after 2.0.25 shipped. There is no 2.0.25 entry, and the file never mentionspermission/external_directory.v2.0.25tag exists, but there is no GitHub release object for it (gh release view v2.0.25→ "release not found")./v2/docs/changelogis a 404.external_directorydefaults toask).So the only place the new default existed was the PR itself. Flipping a filesystem-access default from
ask→allowwithout a release note is what made this a surprise: users have no way to learn that the prompts they relied on are gone.Request: alongside the docs fix, please add a changelog/release note for the 2.0.25 default change — external paths are now read/written without a prompt, and
{ "action": "external_directory", "resource": "*", "effect": "ask" }restores the old behaviour. For a security-relevant default flip, a release note is the minimum, not just a docs correction.(Confirmed on 2.0.26/macOS: a read of
/etc/hostsand a read of a*.envfile behave differently — the external path proceeds silently, the.envread still prompts.)John-Gee commentedon Oct 13, 2026
This is absolutely an unacceptable change, because we only learned of it when that security failed... and since it does not match the doc (which says it's current) we're left wondering what is happening.
@kovaacs I think even if this was in the release note it'd be too big of a change to be acceptable. It'd have to be really shown in front of people's face. Imagine your computer not requiring a password for run0 anymore without telling you apart from the release note...
I've never complained, or thought to, about any kind of change that was not well advertised, even less when you consider the cost of OpenCode's harness... but I have to change my stance for this one. Even worse that bug was created 2 days ago, which means more people than needed had to suffer from this. In the previous context sure, humans can't always go triage bugs quickly enough to know what needs urgency and what does not, but why didn't the bot flag this?
Forgetting that, I do not understand the change in default, even with a proper announcement it's weird, security should always be an opt-in change not opt-out.
sysstemlord commentedon Oct 13, 2026
Confirming on 2.0.28 with default config (TUI prompt mode, empty global config, no project config): reads of files outside the project (/etc/hosts, ~/.ssh/id_rsa, files under ~/.config) succeed silently — no prompt, empty permission queues, empty saved-approvals table. Reading a .env file inside the project DID prompt, so delivery works; only the external_directory gate is affected. Reproduced in both non-git and git-backed project dirs (fresh sessions). Adding the explicit rule {"action": "external_directory", "resource": "", "effect": "ask"} was suggested on my dupe #55207 as the workaround.
bryndin commentedon Oct 25, 2026
FYI: A model went to another repository on my devbox outside the current directory and modified and committed code there.
In the model output, I saw a mention of a commit that I couldn't find in my current repo, so I decided to investigate. If I'd missed that mention, I wouldn't have figured out my other repo is broken.
so BEWARE
@OpenCode, please revert your change. This is dangerous and unacceptable!
John-Gee commentedon Oct 25, 2026
I don't think you tagged who you wanted to, so I'll add a few.
@thdxr @kitlangton @vimtor @rekram1-node @anomalyco (I don't know if we can tag a group though)