3.4 KiB
3.4 KiB
External Directory Permission Auto-Deny Implementation
Summary
Automatically denies OpenCode external_directory permission requests when they don't match the current app's ID, preventing permission prompts from appearing in the builder UI.
Storage Impact
- Config file size: ~208 bytes per app
- Location:
{workspaceDir}/opencode.json(in each app's workspace directory) - Overhead: Negligible (< 0.3 KB per app)
Implementation Details
Files Modified
-
chat/server.js:
- Added
ENABLE_EXTERNAL_DIR_RESTRICTIONenvironment variable (line 102) - Added
ensureOpencodeConfig(session)function (lines 1960-2001) - Modified
ensureSessionPaths(session)to call the new function (line 1956)
- Added
-
.env.example:
- Added
ENABLE_EXTERNAL_DIR_RESTRICTIONdocumentation (line 35)
- Added
How It Works
-
When a session is created,
ensureSessionPaths()is called -
This function calls
ensureOpencodeConfig()which:- Extracts the app ID and user ID from the session
- Creates an
opencode.jsonconfig file in the workspace directory - Configures
external_directorypermission rules:- Deny all external directory access (
*: "deny") - Allow access only to current app's paths:
*/{appId}/*- Any path containing the app IDapps/{userId}/{appId}/*- The full workspace path pattern
- Deny all external directory access (
-
OpenCode automatically loads this config when running in the workspace directory
-
Permission requests for paths matching the current app ID are auto-allowed
-
Permission requests for other apps are auto-denied (no user prompt)
Example Config File
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"*": "deny",
"*/c7f9e5c6-e7c2-4258-a583-ccffcf9791c8/*": "allow",
"apps/user123/c7f9e5c6-e7c2-4258-a583-ccffcf9791c8/*": "allow"
}
}
}
Configuration
Environment Variable
ENABLE_EXTERNAL_DIR_RESTRICTION=1 # Default: enabled
To disable the feature:
ENABLE_EXTERNAL_DIR_RESTRICTION=false
Usage
- New sessions: Config is automatically created when session starts
- Existing sessions: Config is created next time
ensureSessionPaths()runs - Failed writes: Logged but doesn't block session creation
Security Benefits
- App isolation: Prevents one app from accessing another app's files
- No user prompts: Permission requests are handled automatically
- Minimal exposure: Only allows access to current app's workspace directory
- Fail-safe: If config creation fails, session continues (logs error)
Testing Checklist
- Verify config file created in workspace directory
- Confirm OpenCode loads config (no permission prompts for same app)
- Test access to different app ID → auto-denied
- Verify no permission dialogs appear in builder UI
- Test with both UUID and slug app IDs
- Test with anonymous users
- Verify
ENABLE_EXTERNAL_DIR_RESTRICTION=falsedisables feature - Check that config file is ~200-300 bytes (minimal storage)
Logs
On successful creation:
Created opencode config for session
sessionId: c7f9e5c6-e7c2-4258-a583-ccffcf9791c8
appId: my-shopify-app
userId: user123
On failure (non-blocking):
Failed to create opencode config
sessionId: c7f9e5c6-e7c2-4258-a583-ccffcf9791c8
error: EACCES: permission denied