Skip to content

fix(exec): exempt venv python interpreter from .goclaw/ path deny#1140

Open
codebit0 wants to merge 1 commit into
nextlevelbuilder:mainfrom
codebit0:fix/exec-venv-path-exempt
Open

fix(exec): exempt venv python interpreter from .goclaw/ path deny#1140
codebit0 wants to merge 1 commit into
nextlevelbuilder:mainfrom
codebit0:fix/exec-venv-path-exempt

Conversation

@codebit0
Copy link
Copy Markdown
Contributor

Summary

The ExecTool's .goclaw/ path-deny silently rejected legitimate invocations of the goclaw-managed Python interpreter via its absolute path:

```
/home/user/.goclaw/venv/bin/python3 .../script.py
```

The first token matched the deny pattern but no exemption, so the whole command was denied without a clear error path — agents either failed outright or worked only via fragile cwd-local symlink heuristics generated by the LLM.

A naive exemption (e.g. `.goclaw/venv/bin/`) does not help: `matchesAnyPathExemption` resolves both tokens and exemption candidates via `filepath.EvalSymlinks`, and `venv/bin/python3` is a symlink into the host's python cellar. The canonicalized token (`/home/linuxbrew/.../python3.14`) never matches a literal venv-relative prefix.

Fix

Resolve `venv/bin/python3` once at startup and exempt the directory of its real target:

```go
if real, err := filepath.EvalSymlinks(filepath.Join(filepath.Dir(dataDir), "venv", "bin", "python3")); err == nil {
et.AllowPathExemptions(filepath.Dir(real) + "/")
}
```

Falls through silently if no venv is present.

Behaviour change

Operators who invoke the pinned venv interpreter via its absolute path (the recommended pattern for ETL/cron scripts, since shell-PATH fallback can silently pick the wrong python) no longer get denied.

Test plan

  • `go build ./...` (PG build)
  • `go build -tags sqliteonly ./...` (Desktop build)
  • After deploy: cron with `/home/user/.goclaw/venv/bin/python3 /home/user/.goclaw/data/skills-store/.../script.py` completed in a single `mcp_goclaw-bridge_exec` call (`status=completed`), verified via the new `acp: tool_call_update` log + DB row check

The ExecTool path-deny rule blocks any token containing `.goclaw/` unless
it matches one of the AllowPathExemptions prefixes (skills-store, tenants).
This silently rejected legitimate commands invoking the goclaw-managed
Python interpreter via its absolute path:

    /home/user/.goclaw/venv/bin/python3 .../script.py

The first token `/home/user/.goclaw/venv/bin/python3` matched the deny
pattern but no exemption, so the entire command was denied.

Naive exemption (".goclaw/venv/bin/") does not work: matchesAnyPathExemption
resolves both tokens and exemption candidates via EvalSymlinks, and the
venv's python3 is a symlink into the host's python cellar (e.g. linuxbrew).
The token canonicalizes to /home/linuxbrew/.../python3.14 while a literal
".goclaw/venv/bin/" prefix never gets touched.

Fix: resolve venv/bin/python3 once at startup and exempt the dirname of
the resolved target. Failure to resolve (no venv present) silently falls
through.

Without this, ACP-driven agents either fail outright or work only via
fragile heuristics (cwd-local symlinks generated on the fly by the LLM).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codebit0 codebit0 closed this May 13, 2026
@codebit0 codebit0 reopened this May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant