Secure defaults
このコンテンツはまだ日本語訳がありません。
New installations start secure. Existing installations keep the behaviour they were set up
with and are told, by kurahi doctor and at gateway startup, which settings still use an old
permissive default. Nothing changes silently and nothing crashes.
What a new installation gets
Section titled “What a new installation gets”kurahi init, kurahi setup and onboarding write these values when they create a fresh config
(kurahi init --force counts as fresh). They never override a value that is already set.
| Setting | Old default (still the fallback when unset) | New installations | OWASP |
|---|---|---|---|
auth.isolation |
inherit: every agent sees the main agent’s credentials |
explicit; the identity agent kurahi init creates gets auth.grants.<id>: ["*"], every other agent only what it is granted |
ASI03 |
agents.defaults.sandbox.mode |
off: no session runs in a container |
non-main with workspaceAccess: "rw": groups, channels, sub-agents and cron run in the container sandbox |
ASI05 |
tools.exec.unsandboxed |
host: where no sandbox is active, commands run on the host with no approvals |
approve: commands outside a sandbox go through exec approvals (allowlist, ask on miss) |
ASI05 |
| Policy file (budgets, job limits) | none: no budgets, no job limits | the starter policy, signed with a local owner key (kurahi policy init) |
ASI08 |
integrity.supplyChain.mode |
warn: unpinned or modified skills and plugins load with a warning |
enforce: a non-bundled skill or plugin loads only when its SHA-256 is pinned in the signed lock (details) |
ASI04 |
memory.provenance.mode |
warn: memory writes are tagged and flagged, but writes after untrusted input still land |
enforce: memory writes after untrusted input (or that look like injected instructions) are held for review, see Memory provenance |
ASI06 |
agents.messaging.signing.mode |
warn: unsigned, forged, replayed or malformed inter-agent messages are delivered, flagged |
enforce: they are rejected (see Agent message signing) |
ASI07 |
console.terminal |
off: the console terminal methods refuse every request | enabled: true, actApprovals: "always": every act-mode command that is not read-only waits for an approval (details) |
ASI05 |
Always on, for every installation: the destructive-command guard (below).
Starter budgets and job limits
Section titled “Starter budgets and job limits”The starter policy (<KOLO_HOME>/policy/policy.yaml, source src/policy/starter.ts) sets:
| Limit | Value | On breach |
|---|---|---|
| Concurrent jobs per agent | 4 | the next job is refused |
| Wall clock per job | 30 minutes (1,800,000 ms) | the job is stopped |
| Tool steps per job | 200 | the job is stopped |
| Tokens per agent per day | 5,000,000 | pause |
| Tool calls per agent per hour | 1,200 | pause |
| Fleet tokens per day | 20,000,000 | pause |
| Fleet tool calls per hour | 5,000 | pause |
A pause holds new work for that agent (or the fleet) until the window resets, or until an
operator runs kurahi policy release --agent <id> (or --all). Change the numbers by editing
the policy and running kurahi policy sign; the gateway reloads it on save. Day windows reset at
budgets.resetHourUtc (00:00 UTC by default).
Starter data, network and integrity rules
Section titled “Starter data, network and integrity rules”The same starter policy also sets (checked on a fresh kurahi init, 24 October 2026):
| Rule | Value |
|---|---|
data.neverRead |
~/.ssh/**, **/.env, **/*.pem, **/id_rsa* and, since 2.1.0, <KOLO_HOME>/secrets/** (gateway token, owner key, secret store) |
data.neverWrite |
~/.ssh/**, /etc/** and, since 2.1.0, <KOLO_HOME>/secrets/**, <KOLO_HOME>/policy/**, <KOLO_HOME>/kolo.json, <KOLO_HOME>/audit/** |
data.secretPatterns |
private-key headers and AWS access key ids refuse a call that carries them |
network.egress.deny |
cloud metadata endpoints (169.254.169.254, metadata.google.internal); no allow list |
shield.mode |
stop: decoy files and mass-encryption detection stop every agent |
attestation.required |
true: an unsigned policy is refused in enforce mode |
approvals.timeoutMs |
120,000; an unanswered approval is a denial |
~/ is the operating-system user’s home. The data lists apply to the file tools (read,
write, edit, apply_patch, including the file_path alias) and the legacy analyser; commands
are covered by exec approvals and the sandbox. A fresh kurahi init also writes the gateway token
and the owner key with mode 0600 in 0700 folders, binds the gateway to loopback with token
authentication, and grants the identity agent every credential (auth.grants.<id>: ["*"]).
Installations created before 2.1.0 keep their policy file. Add the <KOLO_HOME> entries above to
data.neverRead and data.neverWrite, then run kurahi policy sign.
When a protection needs something that is not installed
Section titled “When a protection needs something that is not installed”The sandbox needs a container runtime (Docker) and the sandbox image (scripts/sandbox-setup.sh).
When a session must be sandboxed and the container cannot start:
- the run continues; it does not fail;
execis refused with the reason and the fix (install Docker, or setagents.defaults.sandbox.mode: offto run commands on the host through approvals);- file tools stay inside the agent workspace;
- browser host control is off.
Exec never falls back to running on the host unprotected. kurahi init and kurahi doctor
report a missing container runtime.
Project sessions (Desktop projects) are not put in the container: the project scope already
confines them (files only in the project folder, writes only to its writable folders, exec never
granted, see src/projects/scope.ts), and a container would hide the project folder.
Destructive-command guard
Section titled “Destructive-command guard”Every path that turns agent output into a shell command checks it first against an
unconditional blocklist (src/security/hardline-guard.ts): recursive deletes of /, system
folders or the home folder, deleting KOLO_HOME or its vault, mkfs, dd or redirects to a
raw block device, fork bombs, kill -1, shutdown and reboot, wsl --shutdown, killing the
gateway, and sudo -S password guessing. The check normalises fullwidth characters, ANSI
escapes and shell escape tricks first.
A blocked command is refused, never queued for approval. No allowlist, approval, elevated mode
or security: full can run it. Every decision is written to the hash-chained audit log as
exec.guard, denied with the pattern, or allowed (kurahi audit tail).
Wired into: the exec tool (sandbox, gateway and node hosts), process write, send-keys and
paste, the nodes tool run action, system.run on node hosts, and the lobster plugin.
Existing installations
Section titled “Existing installations”An installation whose config predates these defaults keeps working exactly as before. It gets:
- a Secure defaults section in
kurahi doctor, one item per unset setting with the fix; secure-defaults.*,policy.presentandsupply-chain.lockchecks inkurahi doctor --json;secure defaults:warnings in the gateway log at startup;- a one-time warning the first time exec runs on the host without a sandbox and without
tools.exec.unsandboxedset.
A setting that is set explicitly, even to the old value (for example
tools.exec.unsandboxed: "host"), is treated as a decision and not warned about.
To adopt the secure defaults on an existing installation:
kurahi config set auth.isolation explicitkurahi config set auth.grants.<your-agent-id> '["*"]' # the owner's own agent keeps all credentialskurahi config set agents.defaults.sandbox.mode non-mainkurahi config set agents.defaults.sandbox.workspaceAccess rwkurahi config set tools.exec.unsandboxed approvekurahi config set agents.messaging.signing.mode enforcekurahi policy init # signed starter policykurahi skills pin --all && kurahi plugins pin --all # review first: this approves what is on diskkurahi config set integrity.supplyChain.mode enforceGrant every other agent the profile ids it needs in auth.grants.<agent-id> before switching
isolation on; an agent without a grant has no credentials under explicit.