Skip to content

Mac os sandboxing akr#26

Open
akr-odoo wants to merge 3 commits into
odoo-odev:mainfrom
akr-odoo:mac-os-sandboxing-akr
Open

Mac os sandboxing akr#26
akr-odoo wants to merge 3 commits into
odoo-odev:mainfrom
akr-odoo:mac-os-sandboxing-akr

Conversation

@akr-odoo
Copy link
Copy Markdown

@akr-odoo akr-odoo commented May 6, 2026

Description

Briefly describe your changes and the reasoning behind them so that other contributors and reviewers can easily grasp the goal of your PR.

Linked Issues

Link the issues that this PR solves, if any:

  • #[issue number or URL]
  • ...

Compliance

  • I have read the contribution guide
  • I made sure the documentation is up-to-date both in doctrings and the docs directory
  • I have added or modified unit tests where necessary
  • I have added new libraries to the requirements.txt file, if any
  • I have incremented the version number according the versioning guide
  • The PR contains my changes only and no other external commit

akr-odoo added 3 commits May 6, 2026 13:07
`start_new_session=True` makes the ephemeral `postgres` leader head its own
process group so callers can kill the whole tree via `os.killpg()`. Without
it, postgres' worker backends survive a SIGTERM to the leader and linger
after the parent exits — which compounded over Ctrl+C'd `odev ai` runs into
half a dozen orphan postgres processes per session.
Previously, if the chosen CLI (claude/gemini/copilot/opencode-cli) wasn't
on PATH, the agent was launched inside the sandbox anyway and either
crashed silently or returned an opaque "command not found". Detect the
missing binary up front and surface a clear install hint so the user can
recover without digging through sandbox logs.
Extracts the AI sandbox layer into a backend-agnostic abstraction and adds
a macOS Seatbelt (sandbox-exec) backend alongside the existing Linux bwrap
backend. The right backend is selected automatically by sys.platform.

Layout:
- common/sandbox/base.py     - Sandbox ABC + ExecutionSpec dataclass
- common/sandbox/bwrap.py    - Linux backend (moved from common/bwrap.py)
- common/sandbox/seatbelt.py - macOS backend (new)
- common/sandbox/__init__.py - get_sandbox() factory by sys.platform

Sandbox policy on macOS:
- Permissive baseline (matches Codex CLI's model). Strict deny-default
  causes Cocoa-using apps (claude, gemini, node tools) to silently
  hang on mach_msg to system daemons. The security boundary is enforced
  on file WRITES via two module-level constants in seatbelt.py:
    - DENY_SYSTEM_SUBPATHS   - the OS, Apple frameworks, Homebrew, etc.
    - DENY_USER_SECRETS_RELATIVE - ~/.ssh, ~/.aws, ~/.gnupg, Library/Cookies, ...
  ALWAYS_RW_SUBPATHS / ALWAYS_RW_LITERALS list the paths that always
  remain writable (sandbox tmp, /tmp, /dev/null & friends).
- Reads are allowed everywhere — Seatbelt cannot truly hide files
  anyway; non-allowed paths only return EPERM.

Other adjustments needed for parity with the Linux backend:
- common/postgres.py: pg_bin discovery extended for macOS (Homebrew
  postgresql@N formulae, Postgres.app); host socket dir discovery
  extended to /tmp & /private/tmp; setup() decoupled from bwrap argv
  (caller exposes proxy_dir to the sandbox).
- common/postgres.py: PostgresSandbox.cleanup_orphans() reaps leftover
  ephemeral clusters from previous Ctrl+C'd runs at the start of each
  agent.run().
- common/agent.py: AgentCLI no longer extends BwrapSandbox; composes a
  Sandbox backend and feeds it an ExecutionSpec.
- common/mixins.py: get_ai_agent() runs Sandbox.check_support() up
  front so unsupported hosts get a clear error before any setup runs.

Linux behaviour is unchanged: bwrap argv assembly is bit-for-bit the
same, just relocated into common/sandbox/bwrap.py.
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