Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191
This commit is contained in:
106
EXTERNAL_DIR_PERMISSION_FIX.md
Normal file
106
EXTERNAL_DIR_PERMISSION_FIX.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# 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
|
||||
|
||||
1. **chat/server.js**:
|
||||
- Added `ENABLE_EXTERNAL_DIR_RESTRICTION` environment variable (line 102)
|
||||
- Added `ensureOpencodeConfig(session)` function (lines 1960-2001)
|
||||
- Modified `ensureSessionPaths(session)` to call the new function (line 1956)
|
||||
|
||||
2. **.env.example**:
|
||||
- Added `ENABLE_EXTERNAL_DIR_RESTRICTION` documentation (line 35)
|
||||
|
||||
### How It Works
|
||||
|
||||
1. When a session is created, `ensureSessionPaths()` is called
|
||||
2. This function calls `ensureOpencodeConfig()` which:
|
||||
- Extracts the app ID and user ID from the session
|
||||
- Creates an `opencode.json` config file in the workspace directory
|
||||
- Configures `external_directory` permission rules:
|
||||
- Deny all external directory access (`*`: "deny")
|
||||
- Allow access only to current app's paths:
|
||||
- `*/{appId}/*` - Any path containing the app ID
|
||||
- `apps/{userId}/{appId}/*` - The full workspace path pattern
|
||||
|
||||
3. OpenCode automatically loads this config when running in the workspace directory
|
||||
4. Permission requests for paths matching the current app ID are auto-allowed
|
||||
5. Permission requests for other apps are auto-denied (no user prompt)
|
||||
|
||||
### Example Config File
|
||||
|
||||
```json
|
||||
{
|
||||
"$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
|
||||
|
||||
1. **New sessions**: Config is automatically created when session starts
|
||||
2. **Existing sessions**: Config is created next time `ensureSessionPaths()` runs
|
||||
3. **Failed writes**: Logged but doesn't block session creation
|
||||
|
||||
## Security Benefits
|
||||
|
||||
1. **App isolation**: Prevents one app from accessing another app's files
|
||||
2. **No user prompts**: Permission requests are handled automatically
|
||||
3. **Minimal exposure**: Only allows access to current app's workspace directory
|
||||
4. **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=false` disables 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
|
||||
```
|
||||
Reference in New Issue
Block a user