Security

pactify runs harness CLIs on your machine under your own logins. This page says what each access mode actually enforces, and where the limits are.

What pactify is

pactify is a local process. It starts the harness CLI you installed, gives it a private configuration, records the job and checks the result. The harness talks to its own provider. pactify adds isolation and checks around the harness, but it does not add an OS sandbox to harnesses that lack one.

Access modes

Every harness has a write mode and a read-only mode. Each mode uses the harness's own controls:

HarnessWriteRead-onlyOS sandbox
codex
Default
Workspace-write sandbox with network access Read-only sandbox, no network Yes
kimi
Supported
Direct writes, no OS sandbox; pactify approves permission requests Private tool allowlist, verified tool snapshots, fail-closed repository baseline No
opencode
Supported
Per-type permissions and a directory guard for file tools; shell is not confined Read, glob, grep and list only, no shell; any repository change fails the job No
agy
Experimental
Full write access, no OS sandbox Plan mode, exact commands, managed hooks, fail-closed repository baseline No

kimi, opencode and agy write jobs run without an OS sandbox, and pactify approves their permission requests. The opencode directory guard covers file tools only; shell commands can reach files it cannot see. Treat these guards as guardrails, not isolation, and run write jobs in a worktree. Codex write mode has network access by default so tests can start local servers and download dependencies.

kimi, opencode and agy read-only jobs compare the repository before and after the run and fail if anything changed. kimi read-only rejects --with-user-config.

Worktrees

With --worktree, a job works in a detached git worktree under ~/.pactify/jobs, based on your current commit. Nothing reaches your checkout until you run pactify sub apply, which checks every affected path first and stops on conflicts without applying part of the change. pactify runs git only locally; it never fetches, pulls, pushes or clones.

Harnesses run with PACTIFY_JOB set, and pactify refuses to start a job or a doctor run inside a job, so a delegated agent does not delegate again by accident. This guards against recursion; it is not a security boundary.

Logins and config

  • Private harness homes link to your existing logins instead of copying them: a login directory, or a single file such as opencode's auth.json.
  • kimi read-only jobs are the exception. They render a private config (mode 0600) from your kimi config.toml, including its providers section and any API keys written there. Its contents are never logged, and the last job removes it.
  • opencode 2.x keeps its own login, made with pactify sub login opencode, inside ~/.pactify.
  • pactify never edits your own harness configuration. Jobs use a minimal generated configuration unless you opt in to yours.
  • If a harness refreshes a login that pactify cannot write back, the copy goes to ~/.pactify/credential-quarantine instead of being dropped.
  • Delegated sessions are kept out of the harness's own session list by default. With --with-user-config, agy and opencode sessions stay visible. Codex threads are archived, and Remote Control can still show archived threads.

Network

pactify sends no telemetry and does not check for updates. Network traffic comes from the harness CLIs: running, resuming and retrying jobs, signing in with pactify sub login opencode, and doctor probes, which also request https://example.com to test network access. The installer downloads the release from GitHub and verifies its checksum.

Local server

pactify serve listens on 127.0.0.1:7777 by default, and the read-only panel listens only on loopback. Every request must carry a matching Host header, and browser writes need an exact origin match. Binding to a non-loopback address requires PACTIFY_SERVE_TOKEN of at least 32 characters, sent as a bearer token on every API request. These checks do not authenticate users; put an authenticating reverse proxy in front for remote access. Details are in the dashboard guide.

Reporting issues

Report vulnerabilities privately through GitHub: open a security advisory. Please do not open a public issue or post exploit details publicly. The security policy lists what to include.