Skip to content

Security and trust boundaries

mini-ork orchestrates models that read your repository, run commands, and produce patches. The security model follows from that: the control plane (your checkout, configuration, credentials, state database) is trusted; the outputs (model text, fetched pages, issue text, test fixtures from a third-party repo) are data, never instructions. This page describes the boundaries, the defaults that enforce them, and the residual risks you own.

The trust model

flowchart TB
  subgraph T["Trusted: control plane"]
    CFG[agents.yaml / providers.yaml]
    VAULT[vault: env → owner-only file]
    DB[(state.db)]
  end
  subgraph U["Untrusted: inputs and outputs"]
    K[kickoff text]
    M[model outputs]
    R[repository under test]
  end
  T --> EX[executor]
  U --> EX
  EX --> C[Crucible: isolated runtime]
  C -->|ExecOutcome| G[gates]
  • Configuration and credentials are read from paths you control.
  • Kickoff text is passed verbatim to model APIs. Treat it as public.
  • Repository content, model output and fetched documents can contain instructions aimed at the agent. They are never elevated to configuration.
  • Verification decisions come from execution outcomes, not from model claims. A model can veto a pass; it cannot manufacture one.

Secrets

Resolve credentials through the vault rather than exporting them by hand. The default chain is the environment, then an owner-only secrets file:

mini-ork vault status          # backends in precedence order and readiness
mini-ork vault which NAME      # first backend holding NAME; never the value

Backends available: env, file, sops, command, openbao. With no config/vault.yaml, the chain is env then the owner-only config/secrets.local.sh — no daemon and no network round trip.

Configuration values written as ${NAME} are resolved through the chain. An unresolved name is an error naming the key and the backend that was tried; it never becomes a silent empty string.

Rules that matter in practice:

  • Never put a key in a kickoff. Kickoffs are sent to providers.
  • Never pass a key as a command-line argument. It appears in ps and in shell history.
  • Do not commit .mini-ork/. state.db holds prompts, source snippets and model responses; secrets.local.sh holds credentials.
  • mini-ork doctor reports the vault chain and names a protection gap when one exists (for example, a secrets file readable by other users).

providers configure prompts for a credential without echoing it. Use it, or write the value to the owner-only file — not to a shell variable that later appears in a log.

Credential indirection for MCP servers

MCP server definitions often carry a token in a command line or environment block that lands in a committed settings file. mini-ork avoids that by resolving servers through a registry and launching them indirectly:

mini-ork mcp launch <name>

The launcher resolves the registry entry and execs the server, so the editor's configuration names a command rather than a secret. If a name does not resolve, the launcher fails loudly instead of starting a server with a half-filled environment.

Execution isolation

Verification runs code. The runtime backend decides where:

Backend Isolation
subprocess Same user, same host; a working directory and environment, not a security boundary
docker Container filesystem and network namespace
docker-cli Docker through the CLI, for hosts without the SDK
prime / modal Remote sandbox providers

Select with RuntimeSpec(backend=...) or the corresponding environment configuration. subprocess is the convenience default; it does not contain a hostile patch. Use docker or a cloud sandbox when running code you do not trust.

Remote execution keeps secrets local to each lane: a remote node receives the names of the secrets it needs and resolves them on its side, rather than the control plane shipping every credential to every node.

Unattended agent permissions

A run is non-interactive: a node cannot stop to ask for approval. Whatever permission setting you give the agent harness is therefore in force for the whole run.

  • Scope the agent to a worktree or a dedicated checkout, not your primary tree.
  • Give the lane only the credentials it needs. A planning lane does not need a deployment token.
  • Audit hooks before enabling them. Hook scripts declared in agents.yaml run with your shell's permissions.
  • If you enable a bypass-permissions mode so the agent can edit unattended, understand that the boundary becomes the repository scope and the lane credentials — not the permission prompt.

Prompt injection

Untrusted text can try to steer an agent toward exfiltrating a file, weakening a test, or editing outside scope. mini-ork reduces the blast radius rather than claiming to detect every injection:

  • The verifier is anchored to execution. A model that "confirms" success does not produce a PROVEN verdict; a gate must have run and passed.
  • A judge is veto-only. It can reject a passing result, never create one.
  • Scope is declared in the kickoff and checked. Out-of-scope edits surface in the changes view and in gate failures.
  • Non-regression checks run after the change. A patch that disables tests is visible as a test-count or assertion delta.
  • A broken harness is distinguished from a real failure. test_defect, apply_fail and no_run are not read as "the patch failed", and they are not read as "the patch passed" either.

These controls limit damage; they do not make an agent safe against a determined adversary who controls the repository and the tests. Do not run an unattended loop against a repository you would not let a new contributor run arbitrary commands in.

Network surface

  • mini-ork serve binds 127.0.0.1:7090 by default. It exposes read-only observability routes. --host 0.0.0.0 exposes it to your network — there is no authentication layer in front of it.
  • Runs make outbound calls to the providers you configure, and to sandbox providers if selected. There is no telemetry call unless you set MO_OTEL.
  • The IDE integration talks to the same local API. Keep it on loopback.

Self-improvement

The apply/promote loop can change mini-ork's own prompts and workflows without a human in the loop. That is deliberate, and it is why the gate is measurement only: a candidate is promoted only on a real held-out measurement that beats the baseline, otherwise it is quarantined or rejected with a reason.

What this means for security: the backstop is rollback, not review. Keep a known-good version registered, and treat the loop as a privileged process. Read Safety and bounded autonomy and the warning in the repository README before enabling it. It ships off by default.

What mini-ork does not protect against

  • A compromised provider or inference endpoint.
  • Malicious code executed by your own tests — the sandbox contains it only if you selected an isolating backend.
  • A leaked credential with broad scope. Rotate keys that have appeared in a terminal, a log or a transcript.
  • A repository whose tests are wrong. Verification proves the change against the tests that ran; it cannot prove the tests encode the right intent.

Hardening checklist

  • .mini-ork/, .env, secrets.local.sh are gitignored and not committed.
  • Credentials resolve through the vault; mini-ork vault status shows no protection gap.
  • Each lane has only the secrets its role needs.
  • Untrusted verification runs use a container or cloud backend.
  • The observability server is on loopback unless you have put an authenticating proxy in front of it.
  • Hook scripts were read before they were enabled.
  • The self-improvement loop is off unless you intend to run it unattended.
  • Any credential that has appeared in output since setup has been rotated.

Reporting

Security issues: [email protected]. Do not open a public issue for a vulnerability.

Next