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
psand in shell history. - Do not commit
.mini-ork/.state.dbholds prompts, source snippets and model responses;secrets.local.shholds credentials. mini-ork doctorreports 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:
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.yamlrun 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
PROVENverdict; 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_failandno_runare 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 servebinds127.0.0.1:7090by default. It exposes read-only observability routes.--host 0.0.0.0exposes 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.share gitignored and not committed. - Credentials resolve through the vault;
mini-ork vault statusshows 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: security@sourceshift.io. Do not open a public issue for a
vulnerability.