anvilmcp: fallback to default sandbox on permission errors

When sandbox is not explicitly specified, retry with 'default' sandbox
if the initial execution fails with permission denied or missing file errors.
This allows third-party skills designed for execute_bash to work without
modification while preserving isolation when sandbox is explicitly set.
This commit is contained in:
Levi Neely 2026-03-06 10:03:01 +01:00
parent 0d847f96f3
commit 2046bc2513
2 changed files with 16 additions and 0 deletions

View File

@ -85,6 +85,15 @@ func recordValidationFailure() {
}
}
func isPermissionError(err error) bool {
if err == nil {
return false
}
msg := strings.ToLower(err.Error())
return strings.Contains(msg, "permission denied") ||
strings.Contains(msg, "no such file or directory")
}
func validateCode(code string) error {
if err := checkRateLimit(); err != nil {
return err

View File

@ -134,6 +134,7 @@ func handleToolCall(req MCPRequest) {
timeout = int(t)
}
sandbox, _ := params.Arguments["sandbox"].(string)
sandboxExplicit := sandbox != ""
if sandbox == "" {
sandbox = "anvilmcp"
}
@ -145,6 +146,12 @@ func handleToolCall(req MCPRequest) {
fmt.Fprintf(os.Stderr, "[anvilmcp] Executing bash code (timeout: %ds, sandbox: %s)\n", timeout, sandbox)
result, err := executeCode(code, language, timeout, sandbox)
// Fallback to default sandbox on permission errors (only if sandbox wasn't explicit)
if err != nil && !sandboxExplicit && isPermissionError(err) {
fmt.Fprintf(os.Stderr, "[anvilmcp] Permission error in %s sandbox, falling back to default\n", sandbox)
result, err = executeCode(code, language, timeout, "default")
}
// Log token comparison
codeTokens := estimateTokens(code)
outputTokens := estimateTokens(result)