Trust & security centre
Answer the question before it is asked.
Koop holds standing permission to execute actions on employee laptops. For a product like that the security posture is the product, so this page is built to the same standard as the home page and answers with mechanisms rather than assurances.
Everything below describes something implemented. Anything on the roadmap is labelled as roadmap, with a date. Where the honest answer is no — air-gapped deployment, self-hosted inference, a SOC 2 report we do not yet hold — it says no.
- SOC 2 Type II
- In progress — window open
- Penetration test
- Annual, summary under NDA
- Data residency
- US · EU-IE · EU-DE
- Air-gapped
- Not supported
01
The architecture of restraint
Four things the system cannot do, stated as absent capabilities rather than promised policies.
Last reviewed 2026-07-22 · Security engineering
Koop holds standing permission to execute code on employee laptops. That is a serious thing to ask for, so the first section of this page is not what we promise — it is what the system is structurally incapable of. A policy can be changed by whoever holds the admin account. A missing capability cannot.
1. The model cannot emit code
The language model’s only output that reaches the rest of the system is a tool call: one action identifier drawn from Playbook, plus parameters validated against that action’s JSON schema. There is no field in that structure that carries free text to a shell. If the model returns an identifier that does not exist, the call fails schema validation and is logged as a rejected recommendation.
{
"action": "koop.printspool.restart", // must exist in the signed bundle
"parameters": { "clear_queue": true }, // validated against the action schema
"rationale": "...", // stored verbatim, never executed
"confidence": 0.94
}2. The authorization decision is deterministic code
Guardrail — the autonomy engine — is plain, testable, reviewable logic with no model in its path. It takes the proposed action, the device, the resolved policy and the current time, and returns one of four outcomes. The same inputs always produce the same outcome. It is the artifact we expect your security team, our auditors and our insurer to read, and we will hand you the test suite.
3. The agent refuses anything not in its own signed bundle
The cloud sends Agent an action identifier. It cannot send an action body. Agent verifies the identifier against the Playbook bundle installed on that machine, whose signature it checks against a pinned certificate chain at load time. If the identifier is absent or the signature does not verify, the agent refuses, reports, and continues running. A compromised control plane cannot introduce a new capability to an endpoint; it can only ask for capabilities that are already there and already authorized.
4. Nothing is autonomous by default
Every tenant, every device group, every action starts Observing (observe only). Autonomy is granted explicitly, per action, per risk tier, per device group, per time window. It is never inherited from a parent group and never enabled by an upgrade, a migration or a support action. There is no “enable all” control, in the UI or the API.
02
Data handling
Exactly what Agent collects, exactly what it does not, retention per class, and what is redacted before anything reaches a model provider.
Last reviewed 2026-07-22 · Security engineering
What Agent collects
- Running process list — image name, PID, parent, CPU and memory, signature status. Not command-line arguments, which routinely contain credentials.
- Service and daemon states, start type, last exit code, and dependency status.
- Windows Event Log slices scoped to System, Application and the specific provider relevant to an open incident. Time-bounded to the incident window.
- Disk capacity and free space per volume, memory pressure, uptime, and thermal state.
- Installed software inventory: name, version, publisher, install date.
- Network adapter state: adapter presence, link status, IP configuration, DNS servers, default route, VPN tunnel state.
- Recent change events: package installs, driver updates, OS patch history, and Koop’s own prior actions on the device.
- Hardware and OS identity: model, serial, OS build, architecture, domain or MDM enrollment state.
What Agent does not collect
This list is enforced by what the agent implements, not by a configuration setting. There is no collector for any of it.
- Keystrokes. There is no keyboard hook.
- Screen contents. There is no capture path, and no remote-view feature.
- File contents. Agent reads file metadata for diagnostics — size, timestamp, path — and never the bytes.
- Browser history, bookmarks, cookies, or stored credentials.
- Clipboard contents.
- Microphone or camera. The agent requests no such permission and holds no such entitlement, which is verifiable in the notarised macOS bundle and the Windows manifest.
- Personal document metadata outside diagnostic scope. The agent does not enumerate user home directories.
- Geolocation beyond the network egress region already visible to your own infrastructure.
Retention
| Data class | Default retention | Configurable | Where |
|---|---|---|---|
| Signals telemetry | 30 days | Yes, 7–180 days | Regional Postgres |
| Frozen observation snapshots | Life of the Ledger entry | Follows audit retention | Object store, encrypted |
| Ledger audit records | 1 year (Fleet), 90 days (Flight) | Yes, up to 7 years | ClickHouse, append-only |
| Ticket content | 90 days after resolution | Yes, or zero-retention mode | Regional Postgres |
| Model prompts and completions | Stored in Ledger verbatim; not retained by the provider | Follows audit retention | ClickHouse |
| Device inventory | Current state plus 12 months of diffs | Yes | Regional Postgres |
Data residency
Tenant data is pinned to one region at creation and does not move. Available: us-east, eu-west (Ireland), and eu-central (Frankfurt). ap-southeast is on the roadmap for Q1 2027 and is not available today — if you need it now, we are not the right vendor yet and would rather say so.
What leaves your region for the model provider
Diagnosis runs against Claude via the Anthropic API. Before any payload leaves our infrastructure it passes through a redaction stage we call the scrub pass, which runs on every field without exception and cannot be disabled per-tenant.
- Usernames and email addresses are replaced with stable per-tenant pseudonyms. The mapping never leaves your region.
- Hostnames are pseudonymised while preserving their naming-convention shape, because the shape is diagnostically useful and the name is not.
- IP addresses, MAC addresses and serial numbers are replaced with stable tokens.
- Anything matching credential, key, token or connection-string patterns is dropped rather than tokenised — a redacted secret is still a secret in a log.
- Free-text ticket bodies are passed through, because the requester’s own words are the highest-value diagnostic signal. Zero-retention mode is available if your policy forbids this, at a measurable cost to diagnosis quality that we will quantify for your fleet.
03
What runs on your endpoints
Two processes, one of which is privileged and deliberately tiny. The measured footprint, the local Stop control that works offline, and what uninstall leaves behind.
Last reviewed 2026-08-08 · Security engineering
Koop asks to run software as SYSTEM on every machine you own. That is the largest thing we ask for, so this section is about the shape of what lands rather than about our intentions for it. The numbers below are produced by a harness that runs on every deploy; if any of them regresses, the deploy stops.
Two processes, and the asymmetry between them
Everything with an attack surface runs as the logged-in user. Everything with privilege runs in a separate process that has no network stack, no TLS library, no JSON parser and no telemetry collectors — not “does not use one”, but does not contain one. The process holding the privilege is the process that cannot be reached from the internet, and the process that can be reached from the internet cannot change your machine.
| koop-svc (privileged) | koop-agent (user) | |
|---|---|---|
| Runs as | SYSTEM / root | the logged-in user |
| Binary size | 0.27 MB | 0.28 MB |
| Speaks to the network | no | yes |
| Parses untrusted input | one hand-written parser, fuzzed | yes, extensively |
| Collects telemetry | no | yes |
| Third-party dependencies | none | none |
| Can change the machine | named bundle actions only | no |
The two halves speak over a local socket in a fixed binary frame. A frame is length-bounded before it is parsed; there is no field in it that can carry a command, a script or an action body. Every deploy runs 700,000 hostile and mutated frames through that parser and asserts that none of them produced a privileged request. A CI gate holds the privileged process to a hard line budget, because an auditor reads at a fixed rate and the difference between 600 lines and 6,000 is the difference between an audit that happens and one that gets scoped down.
Measured footprint
- Two static binaries totalling 0.55 MB, against a budget of 15 MB each. No Electron, no Node, no Python, no embedded interpreter of any kind.
- No third-party crates in either privileged binary. A supply-chain compromise of a transitive dependency is a supply-chain compromise of SYSTEM, so there are no transitive dependencies.
- unsafe is forbidden at the crate root rather than reviewed at the call site.
- Local storage is hard-capped: 32 MB of unsent telemetry, 64 MB of local state, 8 MB of logs. A full week disconnected fits inside the first of those with room to spare.
- When those caps are reached, the oldest routine telemetry is dropped first and the record of what Koop actually did on the machine is never dropped. If anything was lost, the agent says which sequence numbers are missing rather than presenting a record with invisible holes in it.
The Stop control is local and works offline
There is a Stop button in the system tray and an agent halt command on the machine itself. Both take effect immediately, without contacting us, and both survive a reboot. A stand-down initiated on the endpoint cannot be released from the cloud — only from the endpoint. That asymmetry is deliberate: the person sitting at the machine outranks us on the question of whether we may touch it.
Support bundles cannot leak a credential
agent diagnose --bundle produces a file you can email us. It is assembled from a closed list of seven parts — there is no --include flag — and every part is redacted on the way in and re-scanned before the bundle is sealed. A bundle that would contain a credential is not produced with a warning; it is not produced. The redactor is tested against planted enrollment tokens, bearer tokens, JWTs, URL credentials, cloud access keys, and PEM blocks.
Uninstall
The installer writes a manifest at the moment it installs, and the uninstaller reads that manifest rather than keeping a list of its own, so the two cannot drift. Eight kinds of thing may be installed; none of them is a driver, a kernel module, a boot hook or a shim, and a test fails the build if that changes.
After uninstalling, the agent can diff what was recorded against what is still on the machine, and it distinguishes three cases in three different sentences: something that should have been removed and was not, something left behind on purpose with the reason quoted, and — the loudest finding — something present at a path Koop uses that was never in the manifest at all, which means a release installed it without saying so.
04
Everything the agent can see
The complete list of fields Koop is able to collect, the categories it is structurally incapable of collecting, and the test suite that proves the second list is true.
Last reviewed 2026-08-08 · Security engineering
Most endpoint software answers “what does it collect?” with a paragraph. A paragraph is not checkable. What follows is the actual table, the actual prohibitions, and the names of the files a customer or an auditor can open and read. Every claim on this page corresponds to a check that runs on every deploy; if a check fails, the deploy stops and this page cannot ship.
The collection allowlist is a closed table
Koop collects 59 fields, across 11 domains, and cannot collect anything else. Not “does not” — cannot. There is no query interface, no wildcard, no prefix match and no “and anything else in this domain”. A field name that is not in the table resolves to nothing, and a CI gate fails the build if anybody adds a way to resolve one by pattern. Every entry carries, in the source, a sentence saying why it exists; a field nobody can justify is a field nobody ever removes.
| Domain | Fields | What it is, and what it is not |
|---|---|---|
| System | 14 | Version, build, model, capacity and utilisation. Not a serial number, not a licence key. |
| Services | 5 | Name, state, start type, last exit code. Not what a service is doing. |
| Processes | 8 | Names, resource use, signature status. Command lines only if you switch them on. |
| Software | 4 | Installed applications and versions. Not documents, not settings, not app data. |
| Drivers | 5 | Name, version, date, provider, signature status. |
| Patch | 4 | Installed and pending updates, and whether the update service is healthy. |
| Network | 7 | Adapter, address, DNS, gateway, VPN and proxy configuration, and one reachability check. Never traffic contents, never a site list, never a Wi-Fi survey. |
| Storage | 3 | Volume capacity and free space, and the size of the directories Koop is allowed to clear. Never a directory walk. |
| Logs | 1 | A slice of one named log source, filtered by level, bounded to two hours and 500 lines. Never a bulk export. |
| Peripherals | 4 | Printer and queue state, display configuration, dock state. |
| Security | 4 | Whether antivirus and EDR are present and healthy, and whether the disk is encrypted. Never anything those tools have themselves collected. |
Collection happens through nine named recipes, one per class of problem, each of which declares its fields in advance and is refused at compile time if it names one that is not in the table. A recipe runs against a budget — wall-clock, CPU and payload bytes — and stops when it hits the first ceiling rather than running to completion on somebody’s machine. The most generous budget any recipe may have is 30 seconds and two megabytes.
What it cannot collect, and the tests that prove it
Fifteen categories are structurally impossible, and each one is asserted impossible individually, by name, in a test file you can read. The suite does not only try the obvious names. Nobody proposes a field calledscreen_contents; they propose system.visual_context, or session.recording, or a Wi-Fi survey for troubleshooting — so the refusal tests are written in the language the request will actually arrive in.
| Category | The plausible exception, and the answer |
|---|---|
| Keystrokes | Not even to reproduce a bug. A keylogger with a good reason is a keylogger. |
| Screen contents | Not for a screenshot on error. A support engineer can ask the user for one; the agent cannot take one. |
| Clipboard | Not to detect a paste of a credential. Reading it to protect it is still reading it. |
| File contents | Not to diagnose a corrupt document. Koop reports that a file will not open, not what is in it. |
| File names outside the six diagnostic paths | Not to find what is filling a disk. Directory sizes answer that question without a listing. |
| Browser history and bookmarks | Not to diagnose a proxy problem. Adapter and proxy configuration answer that. |
| Cookies and saved credentials | Not to test whether a login works. Nothing that authenticates as the user is ever read. |
| Email content and document metadata | Not to diagnose a sync failure. Service state and log level answer that. |
| Microphone, camera, precise geolocation | Not for asset tracking, not for a support call, not ever. |
| Personal application data | Not to establish which apps a person actually uses. The inventory is names and versions. |
Personal identifiers are replaced before anything leaves the machine
Usernames, hostnames and home-directory paths are replaced with stable salted tokens — usr_4f2a91c8 rather than a name — on the device, before a value is measured, truncated or written down. The salt lives on the endpoint and is not readable from the structure that holds it. Because the tokens are stable, we can still tell you that the same machine has failed three times this week; because they are salted per tenant, they mean nothing outside it. Credentials are not tokenised, they are destroyed. The path rewriter is tested against planted identifiers buried mid-line in log output, and rewriting is idempotent, so a value that passes through twice does not acquire a second identity.
Command lines are off unless you turn them on
Process command lines routinely contain passwords, tokens and connection strings typed by people who were told not to. It is the one field marked opt-in in the table itself, it carries a warning at the point of collection, and a recipe that names it fails to compile without an explicit tenant grant. The grant fails closed, and a CI gate fails the build if anybody turns it on by default.
What it costs you, in numbers
- A heartbeat is at most 320 bytes, once a minute, with jitter derived from the device identifier so a fleet that restarts together does not arrive together. 100,000 devices is 1,667 heartbeats a second and under 45 GB a day for the entire estate.
- The heartbeat carries no inventory and no free text. It is fifteen fixed numeric fields, and a CI gate fails the build if a growable type appears in it.
- Inventory is sent as a delta against the last known state, with a full reconciliation once a day so a delta chain can never silently diverge.
- A collection run is measured against the slowest hardware we support — 25 ms per field of wall clock — and every recipe still finishes inside its budget.
- If we had to cut a value short, the value itself says so. Truncation is marked in the data, not only in a flag somebody might not read.
The person at the machine can see all of it
The tray shows what Koop last read from that machine and when, in plain sentences, drawn from the same sealed record that was actually sent rather than re-rendered from a template. It works with no network and it works if your tenant has been suspended, because it is a local record and not a query. An employee who can see what an agent read is an employee who does not campaign to have it removed.
05
How a machine joins, and what it holds while it is there
Device identity derived from hardware rather than a hostname, private keys generated inside the TPM and never readable, enrolment tokens with real limits, and an agent that holds no standing privilege — it takes one named capability for the length of one action and the language gives it back.
Last reviewed 2026-08-08 · Security engineering
Two questions decide whether an endpoint agent is safe to install on fifty thousand machines. How does a machine prove it is the machine it claims to be, and what does the agent hold while it is running? Most products answer the first with a hostname and the second with “it runs as SYSTEM”. Both answers are why endpoint agents have the reputation they have.
Identity is derived from the hardware, not from a name
A device identifier is a SHA-256 over your tenant salt, the machine UUID, the primary MAC address, the hardware serial, and a value written once at first boot — length-prefixed and in a fixed order, so that two different machines cannot be made to hash the same by shifting a field boundary. Nothing else feeds it.
| Not used as identity | Why not |
|---|---|
| Hostname | Renamed on reassignment, on reimaging, and by users who can. Identity derived from it forks one laptop into a dozen records. |
| IP address | Changes between the office, home and a VPN, which for a laptop is several times a day. |
| Logged-in user | A shared machine has many, a kiosk has none, and a reassigned laptop has a different one. |
| OS version | Changes on every update. An identity that changes on patch Tuesday loses a device history on patch Tuesday. |
| Agent version | Changes on every agent update — the one event where continuity matters most. |
| Domain membership | Changes on a domain migration, which is exactly when an inventory can least afford to lose track. |
A machine cloned from a disk image reports the same hardware and a different first-boot value, so it becomes a distinct device. The record it was cloned from is retired and linked, not deleted, because an audit entry from eighteen months ago points at that identifier and the question “which machine is that now” has to have an answer. Enrolment also recomputes the identifier server-side rather than accepting one the agent supplies: an agent that can name itself can name somebody else.
The key is generated in the TPM and cannot be read
At enrolment the agent asks the platform to generate a keypair inside a TPM 2.0 or a Secure Enclave, marked non-exportable. The only operation available is signing. There is no export, no bytes, noraw — a caller who wanted the key could not express the request, and the handle prints as<held by the platform, not by this process> so a stray log line cannot leak the reference.
Where a machine has no usable TPM the key is software-held and sealed by the operating system, and we say so: the fleet view shows custody per device, so you can see exactly what proportion of your estate is hardware-backed. A tenant that requires hardware custody can set that, and machines without it are refused rather than quietly downgraded.
Enrolment tokens have limits that are actually enforced
- Thirty days maximum lifetime, and the console clamps rather than accepts a longer one.
- Five hundred devices by default, ten thousand absolute — a token that has enrolled more machines than the rollout has is a token somebody else is using.
- A minimum interval between enrolments, so a leaked token cannot be drained in a burst.
- An optional serial allowlist, and optional approval gating: a device that enrols sits in a queue and runs nothing until an administrator admits it.
- Revocation that takes effect on the next attempt, and does not disturb devices already enrolled — revoking a token and revoking a device are different acts.
- The token is never stored. We keep a digest. There is no page that can show it again, and a database dump does not contain one.
On the endpoint the token is consumed by value: the Rust borrow checker prevents a spent token being spent again, rather than a boolean somebody forgets to set. Its debug output is the literal string<not shown>.
The agent holds no standing privilege
It runs as a dedicated service account — NT SERVICE\KoopAgent, _koop or koop — never as SYSTEM, never as root, never as the logged-in user, and that is re-checked at every escalation rather than at install time. When an action needs a capability it takes exactly one, from a closed table of eight, for the length of that action:
| Capability | What it is for | What it does not take |
|---|---|---|
| service-control | Start, stop and query services, launchd jobs and systemd units. | No driver loading, no debug privilege |
| package-management | Install and repair software through the platform package manager. | Never an arbitrary installer |
| network-configuration | DNS servers, proxy settings, adapter state. | SeLoadDriverPrivilege is not taken |
| filesystem-repair | Named system locations only — a jammed queue directory, a broken permission. | Not a general filesystem capability |
| process-control | End a process belonging to another user or the system. | SeDebugPrivilege is not taken |
| device-management | Query and change device state. | No driver installation |
| log-access | Read system and security event logs. | Read only — the one capability that changes nothing |
| scheduled-tasks | Create and remove scheduled tasks and launch agents. | Our own folder and labels only |
Every escalation is written to the Ledger with its capability, its action, the incident it was for and how long it lasted: Elevated for 1.4 seconds, scoped to service-control, to restart the print spooler. Dropped. You can ask for every time this agent has held privilege this year and get a list.
Leaving is a first-class operation
De-enrolment is eight named steps — revoke the certificate, destroy the key, remove the action bundle, remove local state, remove cached credentials, remove the service, remove autostart, mark it in the fleet — and each one states what is left behind if it does not happen. A partial de-enrolment reports which steps failed and what that means, rather than reporting success. The uninstall test does not read a return code; it diffs the filesystem against eight named locations.
Retiring a device revokes its certificate and keeps its history. Deleting one removes the history and leaves a tombstone carrying four fields: the identifier, the tenant, and two timestamps. Nothing about the machine. The tombstone exists so that “deleted on the 14th of March” and “we have no record” remain different answers, which matters to an auditor and to an investigator.
06
Encryption & key management
mTLS everywhere, per-device certificates issued at enrollment, KMS-backed key hierarchy, and what happens on compromise.
Last reviewed 2026-07-15 · Security engineering
In transit
- Agent to cloud: gRPC over mutual TLS 1.3. The agent presents a per-device client certificate issued at enrollment; the cloud presents a certificate pinned to our intermediate. Both sides verify. There is no fallback to server-only TLS.
- Layered on the mTLS channel, a short-lived session token scoped to one device and one tenant, valid 15 minutes, refreshed over the same authenticated channel.
- Browser to cloud: TLS 1.3, HSTS with preload, and no support for TLS 1.1 or below.
- Cloud to your ticketing system: TLS 1.2 minimum, certificate validation enforced, no option to disable it.
At rest
- AES-256-GCM for all stored data, on managed storage with encryption enabled at the volume layer as well.
- Connector credentials use envelope encryption: a per-tenant data key wrapped by a KMS customer master key. Plaintext data keys exist only in process memory during a call.
- Connector credentials are never returned by any API response, never rendered back into the UI after save, and are scrubbed from application logs by a filter with its own test suite.
Key hierarchy and rotation
| Key | Backed by | Rotation | On compromise |
|---|---|---|---|
| Tenant data keys | KMS CMK, per tenant | Annual, automatic | Re-wrap and re-encrypt; no downtime |
| Device client certificates | Koop intermediate CA | 90 days, automatic renewal | Revoked via CRL and OCSP; device must re-enrol |
| Playbook bundle signing key | HSM, offline root | Intermediate annually, root at 10 years | Bundle pinned chain rotated; agents refuse the old chain |
| Agent binary signing | Authenticode + Apple notarisation | Per certificate lifetime | Certificate revoked; Updater forces update |
| Session tokens | Derived, not stored | 15 minutes | Expire on their own |
De-enrollment and compromise
When a device is de-enrolled, its certificate is revoked immediately and published to the CRL and OCSP responder. The agent, if still running, receives a stand-down over the independent Halt channel and stops acting. Telemetry stops. Historical Ledger entries for that device are retained, because deleting the audit record of a device you just removed is exactly backwards.
If you believe a device certificate is compromised, revocation is a single call and is effective on the next connection attempt — under 30 seconds in practice. A revoked certificate cannot be used to enrol a new device; enrollment requires a separate, single-use Enrollment token.
07
The channel between the agent and us
Outbound only, mutually authenticated, with our issuing CA pinned into the binary. No listening ports, no way to turn verification off, and a stop instruction that always overtakes everything else.
Last reviewed 2026-08-06 · Security engineering
Most of what a security team wants to know about an endpoint agent is what it can be reached by. The answer here is nothing. The agent opens no listening port on any platform, accepts no inbound connection, and publishes no service. Every conversation is one the agent starts, outbound, on TCP 443. A port scan of a managed device finds no Koop surface at all, and our build fails if a listener is ever introduced.
What is on the wire
- gRPC over mutual TLS 1.3. The agent presents the per-device client certificate it was issued at enrollment; we present a certificate whose issuer is pinned into the agent binary.
- Four hostnames, all outbound 443: the channel, the long-poll fallback, the signed update feed, and the enrollment API. No inbound firewall rule, static NAT or DMZ placement is required for any of them.
- TLS 1.2 is not offered and cannot be enabled. Three AEAD suites are permitted; the agent refuses anything else rather than negotiating down.
- Certificate verification has no off switch and will not be given one. A flag that disables pinning is a flag that gets set during a bad week and is never unset, and from then on every interceptor looks like a supported configuration.
What happens behind a TLS-inspecting proxy
It fails, deliberately and loudly. An inspecting appliance terminates the connection and re-signs it with an issuer we did not pin, so the agent closes the connection and reports a pinning failure that names the issuer it was shown. In the console this appears as a specific condition with the appliance identified, rather than as a device that has quietly gone quiet — which is the outcome that actually costs people time. The remediation is a decrypt exemption for our four hostnames, and the documentation lists the exact setting for the ten appliances we see most often.
Where a restricted network forces a fallback
Some networks will not permit a long-lived connection at all. The agent then falls back to outbound HTTPS long-polling, and that fallback is never silent: the device is marked as degraded in Fleet with the reason recorded, and a full connection is retried every fifteen minutes. What does not change in fallback is the security posture — mutual TLS, the pinned issuer, sequence numbers and deduplication, the priority of the stop instruction, the absence of any listening port, and the same audit trail. What changes is responsiveness: a stop instruction arrives within 45 seconds rather than immediately.
Ordering, and the instruction that always wins
The channel is divided into lanes and the control lane is not part of the fair-sharing arrangement the other lanes use — it is served first, always. A device streaming telemetry at its full permitted rate still hands the stop instruction over ahead of the queue. We test this by saturating the telemetry lane with a gigabyte of pending frames and measuring how long the stop takes to be selected; the answer is under a microsecond of decision time, and the load test that proves it fails the build if it regresses.
What we assume the agent is lying about
Every field an agent sends is treated as a claim, not a fact. The device identity used for authorisation is the one in the client certificate, never the one in the message body; a mismatch is refused. Revocation is checked before anything else, and if the revocation list cannot be refreshed we refuse rather than admit — “we could not check” must not resolve to “allow”. Malformed input is rejected at the boundary without touching another tenant’s connections, and we fuzz that path with a quarter of a million hostile frames on every build.
| Property | Value | Configurable |
|---|---|---|
| Listening ports on the endpoint | None, on all three platforms | No |
| Direction | Outbound only, TCP 443 | No |
| TLS version | 1.3 only | No |
| Issuer pinning | Compiled into the agent binary, two anchors for rotation | No |
| Session lifetime | 15 minutes, refreshed over the same channel | No |
| Revocation effective within | 5 minutes on a live connection | No |
| Behaviour when revocation cannot be checked | Refuse | No |
| Fallback when a persistent connection is refused | Outbound long-poll, reported in Fleet | No |
08
Stopping us
One control, in the top bar of every screen, that stops every agent in seconds — and reaches the fleet through infrastructure that shares nothing with the platform, so it works when we are down.
Last reviewed 2026-08-06 · Security engineering
This is the section to read first if you are deciding whether to allow an autonomous agent on your estate. Everything else on this page is about how carefully we act. This is about how completely you can make us stop.
The control
Halt is in the top bar of every screen in Console. Not in settings, not behind a menu, not in a danger-zone accordion. It can be issued at six scopes \u2014 one machine, a device group, a workspace, your whole organisation, a single Playbook action across every machine everywhere, or globally by us \u2014 and it takes one authorised person, a reason, and typing the word HALT.
The roles that can issue it are deliberately wide, including operator. The person watching remediations run at two in the morning is an operator, and a design that makes them find an administrator first is a design that adds minutes to an incident during the only minutes that matter.
The numbers we hold ourselves to
| Measurement | Promise | What we measure in CI |
|---|---|---|
| Halt reaches the fleet | Under 5 seconds | 10,000 devices confirmed in under 2 seconds under production telemetry load |
| Decision to fleet-stopped | Under 10 seconds | Measured from the operator clicking confirm, not from the server receiving it |
| Halt with our platform offline | Works | The entire orchestration layer, database and API removed; the halt still lands |
| Agent with no network at all | Stops acting within 30 minutes | Configurable up to 4 hours; cannot be disabled |
Why it works when we do not
A kill switch that depends on the healthy path is not a kill switch. The failures that make you want to stop an agent fleet are correlated with the failures that take a vendor platform down \u2014 a bad deploy, a migration that locks a table, a compromised credential. In every one of those, our platform is precisely the thing you cannot trust to carry the instruction that stops it.
So the halt document is published to infrastructure that shares nothing with the rest of Koop:
| Not shared | Why it matters |
|---|---|
| DNS zone | A different apex, so a registrar or zone problem cannot take both |
| Certificate | Separately issued and renewed, by a different ACME account |
| Hosting | A static object behind a CDN, not an application server |
| Deploy pipeline | Publishing a halt does not run the platform build |
| Database | There is no database. The document is a static object |
| Application code | Nothing in the publisher imports anything from the platform |
| Credentials | The publisher key signs halt documents and nothing else |
| Cloud account | Separate account, separate billing, separate blast radius |
Agents read a complete statement of what is in force rather than a stream of events, every five seconds. An empty document is a signed statement that nothing is halted. A document we cannot serve, or one older than a minute, is an absence of information \u2014 and absence of information never lifts a halt.
Agents that can reach nobody
Both of the paths above assume a network. An agent that has lost both does not carry on acting on its own judgement: after thirty minutes without confirming that it is still authorised, it stands itself down. It keeps collecting telemetry and refuses to act until it can confirm again. You can raise that window to four hours; you cannot disable it, and you cannot set it to a working day.
Halting us at the machine
Any administrator of a machine can run koop halt on it with no connectivity at all. That decision is local, and our cloud cannot lift it \u2014 deliberately. If we could override it, the guarantee would be “Koop stops until Koop decides otherwise”, which is not a guarantee. Console shows those machines as locally held rather than pretending a remote resume will work on them.
Forgery, and the asymmetry
Every halt and un-halt is a signed document over a length-prefixed canonical form, so no field boundary can be moved after signing. An unsigned instruction is refused and alerted on, because no legitimate path produces one. Every order carries a sequence number within its scope, so a genuine clear captured last week cannot be replayed to lift today\u2019s halt.
Starting again is harder than stopping, on purpose. Fewer roles can do it, anything covering a workspace or wider needs two people, it is unavailable for the first ninety seconds, it needs its own reason, and it shows a blast radius computed from your actual fleet before anyone confirms \u2014 how many machines, how many had an action interrupted, how many are mid-rollback, how many suspended approvals become live decisions. The fleet then resumes in stages rather than all at once, because if the underlying problem is not actually fixed, resuming everything simultaneously does the remaining damage in one go.
What a halt does not do
It does not blind you. Telemetry keeps flowing, heartbeats continue, the audit trail keeps recording including the halt itself, and diagnostics still run. Pending approvals are suspended rather than denied, because a denial fabricates a judgement nobody made and in most ticket queues it is terminal; they return exactly as they were. Actions already running stop at the nearest safe boundary declared in the action manifest, so no machine is left half-changed.
09
The Playbook review pipeline
Every remediation action is authored as code, peer-reviewed by a security engineer, sandbox-tested, tiered, signed and versioned. The manifest schema is published.
Last reviewed 2026-07-28 · Security engineering
Playbook is the entire vocabulary of things Koop can do to a machine. Publishing our internal review process for it is unusual. We do it because the process is the control, and a control you cannot inspect is a control you have to take on faith.
The gate, in order
- Authored as code in the Playbook repository, with a declarative manifest. Never a script pasted into a console.
- Peer review by a named security engineer, who is not the author, and who has an unconditional veto. CODEOWNERS enforces it.
- Sandbox fleet: executed against a dedicated fleet spanning every supported OS build, including deliberately broken machines. Rollback is exercised on every run, not just the failure runs.
- Risk tier assigned from observed blast radius, not from author intent.
- Reversibility declared with a rollback procedure that has been tested. An action cannot be marked reversible without a rollback that ran.
- Signed and versioned into a bundle. Bundles are immutable; a fix is a new version, never an edit.
- Staged release through the Playbook channel, which is separate from the Agent binary channel so a remediation fix does not require a fleet-wide agent update.
The manifest schema
This is the real shape. Every field is mandatory except preconditions. The reference published in the docs is generated from these manifests at build time — there is one source, and hand-editing the reference fails CI.
id: koop.printspool.restart
version: 4.2.0
platforms: [windows]
risk_tier: 0
reversible: true
rollback:
procedure: restore-service-state
tested_against: [win10-22h2, win11-23h2, win11-24h2, ws2019, ws2022]
requires_privilege: elevated
privilege_scope: single-call # escalate, act, drop — in one function
max_duration_seconds: 60
parameters:
clear_queue:
type: boolean
default: true
description: Delete queued jobs in the spool directory before restart.
preconditions:
- service_exists: Spooler
- device_health: [healthy, degraded]
verification:
- service_state: {name: Spooler, expect: running}
- test_print: optional
review:
author: <redacted>
security_reviewer: <redacted> # never the author
sandbox_run: 2026-07-19T09:14:22Z
signature: sha256:9f2b1c7ae04d…c81aRisk tiers
| Tier | Meaning | Example | Max autonomy available |
|---|---|---|---|
| Tier 0 | Read-only or trivially reversible | koop.smb.credential.refresh | Unattended |
| Tier 1 | Reversible service-level change | koop.printspool.restart | Unattended |
| Tier 2 | System change with a tested rollback | koop.driver.rollback | Unattended, explicit grant only |
| Tier 3 | High blast radius or irreversible | koop.disk.partition.resize | Approval required, always |
10
Autonomy, control & Halt
How Guardrail is scoped, how autonomy is earned with evidence, and the kill switch that works when everything else does not.
Last reviewed 2026-07-22 · Security engineering
What a rule can be scoped by
- Action identifier, or an action category, or a risk tier.
- Device group — static membership, or dynamic by OS, version, tag, directory OU, location or check-in recency.
- Reversibility requirement.
- Time window, evaluated in the device’s local timezone, not the tenant’s.
- Rate limits per device, per group, per hour and per day.
- Device health preconditions.
- User context — the exclusion of executive or VIP groups is a first-class field, because every enterprise asks for it.
- Maintenance-window awareness.
- Required approver role, for approval-gated outcomes.
Precedence
Deny always wins. More-specific scope beats less-specific. The resolution order is displayed in the policy UI on every rule, along with which other rules it interacts with. Silent precedence is how security policy interfaces cause incidents, so we show it whether or not anyone asks.
Earning autonomy with evidence
Autonomy is not a switch you flip on day one. An action accumulates a record under human approval; when that record is strong enough, the console proposes a scoped promotion with the evidence attached: “this action ran 214 times under approval with a 100% success rate and zero rollbacks — promote to unattended for Standard Laptops, business hours?” You accept a specific scope, not a general permission. Before saving, the simulator replays your last 30 days of Ledger against the draft policy and shows exactly what would have changed.
Halt — the kill switch
Halt stands every agent down. It is reachable in one click from every screen in the console, and it is deliberately not behind a settings page or a “danger zone” accordion. Confirmation requires typing the word HALT and shows the blast radius first: how many devices, how many actions in flight.
- Scope: global, per tenant, per device group, or per device.
- Effect: every agent in scope stops acting within 5 seconds. In-flight multi-step actions halt and roll back to their last checkpoint.
- Telemetry continues. You do not lose visibility at the moment you most want it.
- Independence: the stand-down travels on a channel separate from the orchestration path, with its own endpoint, its own credentials and its own health. Halt works when Act is down. We verify this in staging by taking orchestration fully offline before every release, and the test is a release blocker.
- Agents that are offline when Halt fires receive the stand-down as the first message on reconnect, before any work is dispatched to them.
- Halt is itself an audited action: who, when, from where, what scope, and how many devices acknowledged.
11
Compliance
SOC 2 status stated honestly with dates, 43 controls generating their own evidence continuously, control mapping, GDPR posture, sub-processors, pen-test cadence and disclosure policy.
Last reviewed 2026-08-05 · Security engineering
The control programme
Forty-three controls, each with a named owner, a named deputy, an automated evidence source and a written test procedure an auditor executes verbatim. Seventeen of them are specific to this product and appear in no framework’s template, because no framework anticipated software that changes machines on its own. The matrix is printed from the same array the platform reads at runtime, so it cannot describe a control we do not have, and we cannot have a control that is missing from it.
| Count | What it means | |
|---|---|---|
| Controls | 43 | Across 12 criteria in four categories: security, availability, confidentiality and processing integrity |
| Koop-specific | 17 | Authorisation, action review, post-execution verification, the kill switch, the collection allowlist |
| Automated evidence | 43 | Every one. Nothing depends on a person remembering during the quarter that matters |
| Evidence records so far | 12,885 | Appended to a store with no update and no delete path |
| Manual collection | 0 | A control that cannot be evidenced automatically is one that needs rebuilding, not a rota |
Privacy is not elected. Those criteria govern notice, choice and consent for personal information collected from data subjects; our relationship is with your IT department, and the person whose laptop we fix is not our data subject. Electing a category we could not substantiate would be worse than electing fewer, so we say so plainly rather than leaving the scope ambiguous.
Where the evidence comes from
Each collector pulls from a system that produces the evidence as a side effect of operating. None of them asks anybody to do anything. A collector that stops is alerted on separately from a control that fails, because the two need different people and sending both to one queue means one of them waits a fortnight.
| Collector | Source system | Cadence | Controls fed |
|---|---|---|---|
| Directory | Identity provider | Daily | Access grants, MFA enforcement, offboarding, role separation |
| Code host | Repository and CI | Daily | Change approvals, protected branches, emergency declarations |
| Cloud configuration | Infrastructure APIs | Daily | Encryption at rest, network boundaries, key rotation |
| Build pipeline | CI | Daily | Signing, reproducibility, action review, allowlist enforcement |
| Scanner | Dependency and image scanning | Daily | Vulnerability detection and remediation clocks |
| Ledger | Tenant audit log | Daily | Authorisation, verification, kill switch, tamper evidence |
| Register | Compliance register | Weekly | Training, risk assessment, tabletops, vendor review |
Control mapping
| Trust Services criterion | Implemented control | Evidence source |
|---|---|---|
| CC6.1 Logical access | SSO via WorkOS, SCIM deprovisioning, role-based access with an auditor role that reaches Ledger only | Access review export |
| CC6.6 Boundary protection | mTLS with per-device certificates; no inbound listener on the agent | Certificate inventory, network policy |
| CC6.7 Data in transit | TLS 1.3 everywhere, HSTS preload, no downgrade path | TLS scan, quarterly |
| CC7.2 Monitoring | Ledger append-only with hash chaining; SIEM export | Integrity verification report |
| CC7.3 Incident response | Documented severities and notification SLAs, tested quarterly | Tabletop exercise records |
| CC8.1 Change management | CODEOWNERS review, signed releases, staged rollout with automatic rollback | Release records, signing logs |
| A1.2 Availability | Independent status page, health-probe driven | Uptime history |
| P1 / GDPR Art. 32 | Scrub pass before egress, regional pinning, retention per data class | Redaction test suite |
GDPR and CCPA
- Koop is a processor. You are the controller for device and ticket data.
- A DPA is available and is signed at contract, not on request after the fact.
- Standard Contractual Clauses for transfers out of the EEA, with the transfer impact assessment provided.
- Data subject requests: deletion and export within 30 days, with the exception of audit records under an active legal hold, which is itself an audited state.
- Sub-processor list below is generated from a single source file that also feeds the DPA appendix, so the two cannot disagree. Change notification is 30 days in advance, by email subscription.
Two policies nobody’s template contains
A compliance platform will generate you eleven policies. None of them answers the question your security team actually has about this product, which is: under what circumstances does your software change my machines without asking. So we wrote two more, and they are the two we would hand over first.
- Autonomous action policy — the four conditions under which Koop may act unattended, what is never unattended regardless of configuration, why model output is never treated as authorisation, and how a customer stops all of it without our involvement.
- Remediation action review policy — what an action must declare before review, the evidence required to pass, the two-person sign-off, and the rule that no action is ever born autonomous: every one starts attended and earns its way up.
Both are reviewed on a shorter cycle than the rest, both are acknowledged by everyone who can merge or deploy, and a revision invalidates the previous acknowledgements rather than carrying them forward. Available under NDA alongside the control matrix.
Testing
| Activity | Cadence | By | Available to customers |
|---|---|---|---|
| External penetration test | Annual, plus on major architecture change | Third-party firm | Summary letter, under NDA |
| Agent-specific red team | Annual | Third-party firm | Summary letter, under NDA |
| Dependency and container scanning | Every build | Automated | On request |
| Playbook action review | Every action, every version | Named security engineer | Process published above |
| Halt independence test | Every release, as a blocker | Automated in staging | Result in release notes |
What we can send your auditor
Pick a control and a date range and the evidence package assembles itself: every record in the window, its digest, the collector that produced it, and a cover sheet stating the coverage. If there is a gap — a fortnight where a collector was broken — the manifest says so, with the dates, inside the package. An auditor who finds a gap you disclosed asks one question; an auditor who finds a gap you did not asks about everything else you sent.
- The control matrix: every control, owner, deputy, evidence source, frequency and test procedure.
- A pre-filled CAIQ, kept current rather than reconstructed per deal.
- An evidence package for any control over any closed window, with gaps disclosed rather than omitted.
- Access review records, restore test results, tabletop write-ups and penetration test findings tracked to closure.
- The two product-specific policies above, and the sub-processor register that generates the table below.
Vulnerability disclosure
security@getkoop.ai is monitored by a human, and /.well-known/security.txt is served on every Koop domain. We acknowledge within one business day, agree a disclosure timeline with you, and we do not use legal threats against good-faith researchers. There is no bounty programme yet; we say so rather than implying one.
Sub-processors
Generated from content/subprocessors, the same source that produces the DPA appendix, so the two cannot disagree. Subscribe at security@getkoop.ai for 30-day change notice.
| Sub-processor | Purpose | Region | DPA |
|---|---|---|---|
| Amazon Web Services | Primary infrastructure, storage, KMS | US, IE, DE | signed |
| Anthropic | Model inference for diagnosis (Claude) | US | signed |
| ClickHouse Cloud | Ledger audit store | US, EU | signed |
| Cloudflare | CDN, DDoS protection, WAF for web surfaces | Global edge | signed |
| Stripe | Billing and payment processing | US | signed |
| Temporal Cloud | Durable orchestration state | US, EU | signed |
| WorkOS | SSO, directory sync, audit of auth events | US | signed |
12
Shared responsibility
What Koop secures, what you must configure, the clause each half sits under, and what happens if your half is neglected.
Last reviewed 2026-08-06 · Security engineering
This table is generated from the same register that renders Exhibit B of the master agreement. The boundary you read here before signing and the boundary you are bound by after signing are one array in one file; the build fails if the two copies drift apart.
The last column is the point of it. A responsibility with no stated consequence reads as advice, and advice is not divided — it is ignored by whichever party finds it inconvenient, and argued about afterwards.
| Area | Koop is responsible for | You are responsible for | Clause |
|---|---|---|---|
| Identity | Authenticating users, enforcing role permissions, session lifetime, SCIM deprovisioning | Your IdP configuration, who you grant policy_admin, and reviewing access | MSA 5.1 |
| Autonomy policy | Evaluating policy deterministically and identically every time; showing precedence; refusing invalid configurations | Deciding what Koop may do unattended, and to which devices | MSA 4.2, 5.2 |
| Device groups | Resolving effective policy correctly and warning before a membership change alters autonomy scope | Group membership, and reading the warning | MSA 5.3 |
| Endpoint agent | Signing, notarisation, sandboxing, privilege drop-back, rollback, update integrity | Deploying the agent, MDM and TCC pre-approval, and pinning a version if your change process needs it | MSA 4.7, 5.4 |
| Connector credentials | Envelope encryption, never rendering them back, scrubbing them from logs | Creating a least-privilege service account rather than using a personal admin login | MSA 5.5, DPA 6 |
| Ticket data | Encryption, retention enforcement, redaction before model egress | What your users put in tickets, and choosing zero-retention if your policy requires it | DPA 4, 7 |
| Audit | Append-only storage, hash chaining, integrity verification, export to your own SIEM | Retention period, legal holds, and reviewing the record | MSA 4.5, 9.2 |
| Availability | Platform uptime, independent status page, Halt independence | Network egress to our endpoints, and your own change windows | SLA 2 |
| Incident response | Detecting, containing and notifying within the deadlines in the incident procedure | Keeping your security contact current, and acting on notification | MSA 9, DPA 9 |
| Widening autonomy | Requiring a named acknowledgement of the specific scope, recording it in the ledger, and notifying every designated contact | Nominating contacts who will actually read the notice, and reading it | MSA 4.9 |
If your half is neglected
| Area | What happens |
|---|---|
| Identity | A departed administrator keeps the ability to widen autonomy until SCIM removes them, and SCIM only removes what your IdP tells it about. |
| Autonomy policy | Koop does exactly what the policy says. If the policy says more than you meant, the ledger will show that it did what it was told. |
| Device groups | Moving a device into a group can widen what Koop may do to it without any policy having changed. The warning fires; somebody has to read it. |
| Endpoint agent | Without MDM pre-approval the agent runs with reduced permissions and silently collects less, which reads in the console as a quiet fleet rather than as a deployment problem. |
| Connector credentials | A personal admin login gives Koop every permission that person has, makes their departure an outage, and makes every writeback look like it came from them. |
| Ticket data | Redaction catches credentials and personal identifiers by pattern. It cannot catch a sentence that is sensitive because of what it means. |
| Audit | A retention period shorter than your dispute window means the record of the incident is gone before the argument about it starts. |
| Availability | An appliance that breaks the agent connection looks identical to an outage on our side until somebody reads the diagnostic, which is why the agent produces one. |
| Incident response | Our notification obligation is discharged when we notify the contact you gave us. If that address is a person who left, the clock still ran. |
| Widening autonomy | One administrator can authorise something the organisation as a whole did not intend. The acknowledgement makes that visible; it does not make it impossible. |
13
Incident response
Severity definitions, notification SLAs, escalation path, and the post-incident commitment.
Last reviewed 2026-07-15 · Security engineering
| Severity | Definition | Notify you within | Post-incident report |
|---|---|---|---|
| SEV-1 | Confirmed unauthorised access to customer data, or unauthorised action executed on customer endpoints | 4 hours of confirmation | Within 5 business days, unconditionally |
| SEV-2 | Credible indication of compromise, or a defect that caused an unintended action on a customer device | 24 hours | Within 10 business days |
| SEV-3 | Vulnerability with no evidence of exploitation, or a degradation affecting autonomy decisions | 3 business days | On request |
| SEV-4 | Vulnerability with no customer impact | Next release notes | No |
What we will tell you
- What happened, in plain language, including what we do not yet know.
- Which of your devices, tenants and data classes were in scope — specifically, from Ledger, not estimated.
- What actions were executed, by whom or by what, with the authorizing policy version.
- What we did to contain it, and at what time.
- What you need to do, if anything.
A first notification will not be delayed to make it complete. We would rather send you an incomplete SEV-1 notice inside four hours and follow it than a tidy one on day three.
Escalation
Your named security contact is notified by email and by the webhook you configure. For SEV-1, a human calls. You may escalate at any time to security@getkoop.ai, which pages the on-call security engineer directly and does not route through support.
14
Agent auto-update
What it takes for you to accept software that updates itself on every machine you own: two signatures, staged installs that cannot leave a device half-installed, and a rollback that needs neither us nor your network.
Last reviewed 2026-08-06 · Security engineering
The agent updates itself. There is no honest way to avoid that — an agent that only updates when somebody remembers is an agent running last quarter’s vulnerabilities — so the question is not whether it updates but what it takes for that to be acceptable to you. This section is our answer, and it is a list of mechanisms.
The updater is not the agent
Updater runs as its own process, from its own binary, under its own service registration, with its own dependency tree. It links no code from the agent. That is not tidiness: it is the reason a crashed, hung, corrupted or partially-removed agent is still recoverable remotely. If the two shared a dependency tree, one bad library would break the agent and the mechanism for fixing the agent at the same moment, and the only remaining recovery would be a desk-side visit.
The updater crate holds no HTTP client, no TLS stack, no archive format and no JSON parser. It is handed bytes, a path and a timestamp and decides what is safe to do with them. Its attack surface is deliberately close to zero, and unsafe code is forbidden at compile time.
Two signatures, pinned in the binary
- Every release manifest is signed by two independent release keys. One signature is refused. Two signatures from the same key are refused.
- The keys are compiled into the agent, so changing them requires shipping a release rather than editing a configuration value or a DNS record.
- A manifest more than 12 hours old is refused, so a valid old manifest cannot be replayed to pin a fleet on a vulnerable version.
- Every artifact carries a SHA-256 digest in the signed manifest. Bytes that do not match are refused on download and refused again after staging, because a disk can corrupt a file between those two moments.
- A version older than the one installed is refused. A correctly signed downgrade is still an attack.
- Custody at every hop. The build system computes the digest, the CDN stores the artifact under it, your internal mirror verifies on ingest and again on serve, and the device verifies twice. That end-to-end verification is the only reason we can offer to let you host artifacts yourself.
No device is ever half-installed
The new version is assembled and verified in a scratch directory. A single pointer write is the instant the update takes effect; everything before it is reversible by doing nothing, and everything after it is reversible by writing the pointer back. There is no window in which a machine holds half of one version and half of another.
Rollback needs neither us nor your network
A new version is on probation for 90 seconds and must prove five things: it stays up, it passes its self-test, its signed action bundle still verifies, its channel connects, and it heartbeats. Failing any of them puts the previous version back.
That verdict is computed on the device. It takes no server input, consults no console and requires no connectivity. The two network-dependent checks are judged against what the machine could do before the update, so a laptop that was already offline is not rolled back for still being offline. A crash loop ends probation after three crashes rather than waiting out the clock.
The version being replaced stays on disk for seven days, so a regression discovered on Monday about a build shipped on Friday is free to undo. If a disk is too full to stage an update, the update is refused — the previous version is never deleted to make room. A machine short of disk space is a smaller problem than a machine with no way back.
It will not interrupt you, and it will not spend your money
Three deferral reasons never expire, however long a device has been waiting: an action is in flight on that machine, Koop is halted, or the connection is metered and you have not allowed metered downloads. A remediation is not less dangerous to interrupt on day fifteen, a halt is not less of a halt, and a metered link does not get cheaper. Presenting, active use, low battery and maintenance windows are also respected; those four can be overridden after a fortnight, and only while the machine is idle.
Nothing goes to everyone at once
Releases move through canary, early and stable rings, and within a ring are offered to a percentage of devices. Membership of that percentage is a stable function of the device, the tenant and the version, so a device offered a build at 5% is still offered it at 50% and is never un-offered it. An administrator pin beats the rollout entirely, and pause stops the build reaching anybody new without disturbing devices that already have it.
We alert on the rollback rate per slice — per platform, per OS build, per tenant — not on the release-wide average, because a release-wide 1% is what a catastrophic failure confined to one Windows servicing branch looks like from a distance.
The floor beneath all of it
A standalone repair installer is published with every release and signed with the same keys. It is a normal MSI, PKG or shell installer that you deploy through your existing MDM. It needs no running agent, no working updater, no network, no enrollment token and no console access, and it preserves the device certificate and identity so the machine reappears as itself. It exists for the case where everything above has failed, because a fleet-scale recovery plan that ends in “visit the desk” is not a plan.
15
Where the software comes from
How a commit becomes a signed binary on your machines: a sealed build reproduced by a second runner, two humans who are not the requester approving exact bytes, keys that have never left hardware, and an attestation you can verify without us.
Last reviewed 2026-08-06 · Security engineering
The previous section is about how software gets onto your machines. This one is about where that software came from, which is the question that decides whether the rest of it matters. An agent that verifies two signatures before installing anything is worthless if the thing being signed was assembled on somebody’s laptop from a dependency set nobody looked at.
No private key exists outside hardware
Every signing key we hold lives in a cloud HSM or on an offline hardware token, marked non-exportable, with a two-person quorum on use. There is no key on a developer machine, no key in a CI variable, no key in a secret manager, and no key in our repository. Signing is a request: the pipeline sends a digest to hardware and receives a signature back.
This is a specific claim about a specific failure. If our build system were compromised tomorrow, an attacker could ask the HSM for signatures until we revoked the credential. That is bad, and we have a runbook for it. What they could not do is walk away with the key, which is the difference between an incident that ends in a rotation and one that ends the company.
| Key | Custody | Boundary |
|---|---|---|
| Windows EV, macOS Developer ID, Linux GPG | Cloud HSM, non-exportable | Binary signing |
| Release manifest A | Cloud HSM, non-exportable | Manifest |
| Release manifest B | Offline hardware token | Separate, offline |
| Playbook bundles | Cloud HSM, non-exportable | Playbook |
| Attestations | Cloud HSM, non-exportable | Attestation |
The two release manifest keys are deliberately in different boundaries, because the agent requires two signatures on a manifest. If both keys were reachable from the same place, whoever held that place would hold both signatures and the quorum would be theatre. The Playbook key is separate from the binary keys for the same reason in reverse: publishing an action bundle happens weekly and shipping an executable happens quarterly, and putting them in one boundary would make the frequent operation as dangerous as the rare one.
Two people, and neither of them the one who asked
A production signature requires two approvals from distinct humans, neither of whom is the person who requested it. The second person’s job is not cryptographic. It is to read the release notes and ask what this build is for, which is the only thing that catches the case where the artifact is perfectly fine and the intent is not.
- Approvals bind to the artifact digest, not to a version number. Get a build approved, rebuild it from a different tree, and the approvals no longer apply. That attack — approve one thing, sign another — is the reason the binding is to bytes.
- An approval expires after seven days, so nobody can bank one in advance of a change they intend to make.
- Changes touching the executor, the privilege model, the channel, or anything cryptographic require an approver from security specifically. The area is computed from the paths in the diff, not declared by the author.
- Nothing built off an unprotected branch is signed, however many people approve it.
- Every signing request — including every refusal, and why — is written to an append-only log. A burst of refusals is the signal that somebody is trying.
Sealed builds, reproduced by a second runner
Builds run in a container addressed by digest rather than by tag, with pinned toolchain versions, frozen lockfiles, vendored dependencies, a fixed SOURCE_DATE_EPOCH, and no network. Every release is then built a second time, on a different runner, from a clean checkout. If the artifacts are not byte-identical the release stops.
That check is not decoration. It is what makes the provenance statement worth reading: an attestation over bytes nobody can reproduce says only that we signed something. An attestation over reproducible bytes says that what we signed corresponds to source you can read, and you can confirm it yourself.
What you can check without asking us
sha256sum /opt/koop/bin/koop-agent curl -sO https://releases.koop.sh/attest/<digest>.intoto.jsonl cosign verify-blob-attestation --key koop-attest.pub <digest>.intoto.jsonl jq -r ".subject[].digest, .predicate.sbomDigest" <digest>.intoto.jsonl make -C koop reproduce COMMIT=<commit>
The provenance is in-toto with a SLSA predicate, signed with our attestation key. It names the commit, the build container by digest, that the build ran with no network, the resolved dependency set, the digest of the bill of materials, and the two people who approved the signature. A CycloneDX SBOM is published for every artifact, flagging which components are actually linked into the agent binary and which are only used to build it.
What blocks a release
- Any advisory affecting a component linked into the agent, at any severity.
- Any clippy finding — the agent builds at deny level.
- Any unsafe block in the agent. The budget is zero, and raising it is a decision with a name on it rather than a commit.
- Any missing leg of the platform test matrix, treated as severely as a failing leg.
- Any copyleft licence reaching the agent binary.
- Any artifact whose independent rebuild does not match.
- Any macOS entitlement that is not on the reviewed list — including one nobody has seen before, which stops the build rather than defaulting to allowed.
Channels and soak
Releases walk internal → canary → beta → stable. No rung can be skipped, each has a soak time, and a build the fleet is already rejecting does not widen: promotion refuses at the same rollback threshold the update dashboard alerts at. A genuine emergency can shorten a soak, but it takes a named approver and a written reason, and it cannot waive anything else — there is no path that ships something unsigned, unattested or unreproduced.
Is that binary yours?
Every artifact we have ever signed is indexed by digest. Send us a SHA-256 from an EDR alert or a quarantine folder, or paste it into the Releases panel in Console, and you get back the commit, the builder, the bill of materials, the two humans who approved it, and which channels it reached — or a flat statement that we have no record of producing those bytes on any commit, on any builder, ever.
The second answer is the more valuable one, and being able to give it in seconds rather than in an afternoon is the entire reason the index exists.
If a key is compromised
There is a written runbook, it is rehearsed, and the rehearsal changed it. The counter-intuitive part: we do not revoke first. The agent pins its release keys, so revoking before a transitional build has reached stable would strand every device on a key that nothing can sign — including the build that would have taught it the new key. The order is cut the pipeline off from the HSM, enumerate what the key signed, generate a replacement in a new boundary, ship the transitional build, and only then revoke with an effective date. Customers are told in parallel, not afterwards.
Planned rotation follows the same shape with a ninety-day overlap, and a key is not retired until 99.5% of the fleet trusts its replacement. The remainder is handled by hand, because waiting longer does not converge.
16
When we touch your machines
A release reaches half a percent of the fleet before it reaches five, a defective build halts itself without a human in the loop, and you can hold your fleet at a version you have tested — with one narrowly-drawn exception written into the agreement.
Last reviewed 2026-08-06 · Security engineering
The two sections above cover how an update is delivered and where the software came from. This one covers timing, which is the part most security reviews get to last and most operations teams care about first. You have given us a standing permission to change software on machines you are responsible for. These are the limits we hold ourselves to in exercising it.
The ladder
A release does not go to your fleet. It goes to ours first — every Koop machine runs a build for two days before any customer sees it — and then to a fraction of a percent of the customer fleet, then five percent, then twenty-five, then everyone. Each rung is held for a minimum period, and the release only widens if the machines already on it are measurably no worse off than they were on the version it replaces.
| Rung | Reaches | Minimum hold |
|---|---|---|
| Internal | Koop-owned machines | 48 hours |
| Canary | 0.5% of the customer fleet | 24 hours |
| Early | 5% | 48 hours |
| Broad | 25% | 72 hours |
| Stable | 100%, excluding pinned fleets | — |
The cohort at each rung is drawn deterministically and stratified across platform, operating-system family, device group, customer and region, so it resembles the fleet rather than whatever a hash happened to select. It is also capped per customer: no single organisation has more than a bounded share of their own estate on an unproven rung. Half a percent of the fleet is never a hundred percent of you.
Organisations below twenty devices are excluded from the early rungs entirely. The cap cannot be expressed on an estate that small — one machine out of fifteen is already seven percent — and the smallest customers are also the least able to absorb a bad update.
How a bad build stops
Six health signals are compared between the devices on the new version and the devices still on the old one: update success, health-check pass rate, channel connectivity, action success, crash rate and resident memory. The comparison is against the previous version rather than against a fixed threshold, which matters more than it sounds like it should. A threshold of “crash rate under one percent” passes a build running at 0.85% when its predecessor ran at 0.05% — seventeen times worse, and inside the threshold.
A severe regression halts the rollout automatically. There is no page, no on-call engineer and no meeting in that path, because a halt that waits for somebody to click is a halt that takes as long as it takes to find somebody. Restarting a halted rollout is a human decision with a written justification; stopping one is not.
A metric we could not conclude — too few devices reporting, or telemetry that has stalled — blocks promotion in exactly the same way a regression does. A gate that treats a missing number as a passing number opens on a broken pipeline.
Pinning
You can hold a tenant, a workspace, a device group or an individual device at an exact version or on a channel. The narrowest pin wins, so a fleet-wide freeze can still be overridden for the one machine that has to stay where it is. Pins survive releases: a fleet pinned in May is still pinned in October, through however many versions have shipped in between.
The console shows every pin alongside what it is holding back — which releases you have not taken, which of those contain security fixes, and what each one changed. We show that because the decision to keep a pin should be informed rather than forgotten. We do not put a banner on it asking you to reconsider.
The exception, stated precisely
A critical security advisory overrides a version pin. This is the only circumstance in which we update a machine you have told us not to, and it is bounded on every side:
- The right is a named clause in the agreement, agreed before either of us needed it.
- It applies only to the versions the advisory affects. Every other pin stays in force.
- Notice comes first — seventy-two hours for a critical advisory, seven days for a high one — before anything moves.
- It carries the fleet to the fixed version and stops there. Your pin holds at the new version rather than being quietly released.
- The override appears in your audit ledger with the advisory identifier, the contract clause, the notice timestamp and the affected devices.
- We do not override a pin for a feature release, a bug fix, or a change we would like you to have.
- We do not override a pin for an advisory that does not affect the version you are pinned at.
- We do not use the mandatory path to shorten a rollout that is going slowly.
Maintenance windows and blackouts
Updates are attempted only inside a maintenance window you define, expressed in the device’s local time rather than ours. Blackout periods sit above windows: a trading desk whose window is 08:00–10:00 and whose blackout covers the trading session is not touched during the session, because blackouts are evaluated first.
Common blackouts our customers configure: trading hours, clinical shift change, month-end close, and the run-up to a regulatory filing. A device outside its window when a rung opens is not skipped — it waits, and takes the update at the next opening.
Rolling back
The primary rollback path is on the machine itself: an agent that fails its post-update health checks reverts to the previous version without being told to. The server can also roll back a cohort, which is the path for a build that is technically healthy and subtly wrong.
Rollback is bounded. We will not roll back more than a fixed number of versions, across a wire-protocol change that would leave the fleet unable to reach the control plane, or past a migration that cannot be undone. A refusal states which of those three applies. We exercise the rollback path on a schedule across multiple platforms and a real number of machines, and the promotion gate will not open a rung if that exercise has gone stale — a recovery mechanism nobody has run is a plan, not a mechanism.
What you can see
- The current rung, the share of your fleet on it, and how long the rung has left to soak.
- Each of the six health signals for the new version against the one it replaces.
- Your exposure: how many of your devices are on the unproven version, and the cap that applies.
- Every pin, who set it, when, why, and what it is holding back.
- Every manual control anybody pulled, with the name, the justification and whether anything was waived.
- For any halted release: the measured blast radius, the detection latency, and what regressed.
17
Action library releases
The remediations ship weekly on their own key, their own pipeline and their own compatibility contract, entirely separately from the agent binary — and a bad one is gone from your fleet in under five minutes.
Last reviewed 2026-08-04 · Security engineering
The agent is a runtime. What it actually does lives in a separately signed action library that ships on its own schedule. The two are independent all the way down to the signing key, and this section is why that is a security property rather than a packaging detail.
Why they are separate
If a remediation were part of the agent binary, fixing a bad one would mean shipping a new agent to every machine you own — a swap, a restart and a probation window, on a quarterly release train, for a change to one line of a manifest. Worse, removing one would be impossible without doing the same. Separating them is what makes minutes-scale revocation possible at all.
| Action library | Agent binary | |
|---|---|---|
| Cadence | Weekly | Quarterly |
| Signing key | koop-playbook, in its own HSM boundary | Platform release keys, in a different one |
| Applied by | The running agent, in place, no restart | Updater, with a swap and a 90-second probation |
| Removable in minutes | Yes, by signed revocation | No — it rolls back to the previous build |
Neither key will do the other’s job. A bundle signed with a platform release key is refused by the agent for that specific reason, and an agent binary signed with the bundle key is refused by Updater. The library moves fifty times a year and the binary moves four; a shared key would be used with weekly familiarity and quarterly consequences.
What an action passes before it reaches a device
- A sandbox diff on a clean machine of every supported OS build, in which every file, registry key, service and network destination the action actually touched is compared against what it declared. An undeclared touch of any of the three is a hard failure.
- A rollback trial in which the before and after snapshots are compared including attributes, not only values — a service restored to running with a changed start type counts as an incomplete rollback, because it is a machine that breaks at next boot with nothing pointing back here.
- A written blast radius, in prose, reviewed against what the action can actually reach rather than what its tier says.
- Sign-off by a named security engineer, on the exact content, within the last ninety days.
- The same canary, early and stable rollout the agent binary goes through.
- There is no emergency flag, admin merge or override that skips security review. We tested eleven ways round it and each one is blocked by a different mechanism.
- There is no exemption list for the sandbox diff. The action that would most benefit from one is exactly the action that must not have it.
- An approval does not survive an edit. Push a commit after sign-off and the review is void.
- A reviewer who has left cannot approve, and an approval older than ninety days is stale.
Compatibility
Every bundle declares the range of agent versions it supports. Our servers never offer one outside that range and the agent refuses one anyway if it arrives — two independent checks, so a bug on our side does not become an incident on yours. A device on an agent so old that no current bundle supports it is reported to you as stranded, because a machine silently receiving no fixes looks identical to a healthy one otherwise.
Revocation
When an action is found to be wrong, we revoke it. A revocation is a small signed list that travels a path independent of the main platform, and agents poll for it every sixty seconds. From signature to the slowest online device having stopped offering the action is under five minutes, and that is arithmetic we measure against a simulated fleet on every build, not a target we aim at. It works with the console, the API and the primary ingest path all down.
A revocation can only remove capability. That is precisely why it is allowed to skip the pipeline: the worst case of a mistaken revocation is that a fix is temporarily unavailable, which is recoverable, whereas the worst case of an additive fast path is not.
If a bundle will not verify
The agent keeps the last bundle that both verified and successfully ran an action. A new bundle that fails any check — signature, key, digest, compatibility or age — causes a fall back to that one, reported as such. The agent does not end up with no actions. An agent that can diagnose a problem and not fix it is worse than useless during an incident, so failing back, not failing closed, is the safe behaviour here.
Actions you write yourself
You can author actions for your own environment. They are namespaced under your tenant, visible only to you, capped at risk tier 1, and pass the same sandbox diff, rollback trial and security review as ours. We sign them; you cannot self-sign, because a device that trusts a customer-held key is a device that trusts whoever obtains that key.
18
Watching us from your own SIEM
Every privileged action we take lands in your detection stack, in OCSF or ECS, on your retention — and the six classes that matter cannot be switched off, including by you.
Last reviewed 2026-08-06 · Security engineering
Everything else on this page is a claim about our behaviour. This section is the one that lets you stop taking claims. We would rather you monitor us properly than believe us, so the record of every privileged thing Koop does on your estate is exported to a destination you own, in a schema you can write detections against, on a retention we do not control.
What arrives
Thirty-nine event types, grouped into ten classes, rendered as OCSF or ECS. Twenty-two documented fields, versioned, with a hundred and eighty days of notice before any of them changes shape. Splunk HEC, Microsoft Sentinel, Datadog, Elastic, Sumo Logic, S3 and a signed generic webhook are supported directly.
Each event carries the hash and previous hash from our ledger, so you can verify the chain from your side rather than asking us whether it verified from ours. If we ever removed an entry, the copy in your SIEM would still be there and would still not link.
We are aware this is us refusing to do something a customer asked for. The reason is that those six are the record of privileged action on your own machines, and a setting that can remove them turns one mistaken click into an audit gap that surfaces eleven months later during an investigation. When a filter tries to exclude them, the API returns the classes it added back and the reason, rather than accepting the request and quietly ignoring it — silent non-compliance with a security setting is worse than a refusal.
What never leaves us
Nineteen internal field names are enumerated and asserted absent on every exported event: model prompts and responses, our token costs, stack traces, pod and region identifiers, build hashes, internal queue names. This is checked per event and raises a violation rather than a log line, because a redaction that fails quietly is not a redaction.
Event payloads are not passed through. They are picked from a twenty-key allowlist and then redacted for eleven classes of secret — private keys, JWTs, cloud access keys, bearer tokens, connection strings, card numbers, and any value with the entropy of a credential — in free text and in structured fields alike, including where the field name is the only evidence that the value is a secret. A key we did not anticipate is absent by default rather than exported by default.
Credentials for your destinations are resolved from the secret store at the moment of framing and are never written to a log, an error message, or the console. What is rendered anywhere in the product is the reference into the secret store, which is enough to debug and useless to steal.
When your destination is down
Nothing is discarded. A failure that improves with waiting is retried with exponential backoff and full jitter, capped at five minutes per attempt, for up to twenty-four hours — so a maintenance window on your side costs you no events. A failure that does not improve with waiting is treated differently: a rejected credential is set aside on the first attempt rather than retried, because retrying a 401 is how a service account gets locked out and how the real cause stays hidden behind a backoff.
Batches that could not be delivered are held for fourteen days with their events intact and replayed from the console once the destination is fixed. A destination that has stopped accepting events shows as failing within five minutes, measured on how long the oldest batch has waited rather than on how many are queued — a large backlog that is draining is fine, and a small one that is not moving is precisely the failure a queue-depth number shows green through.
Detections, written for you
Nine detections ship with the connector in both SPL and KQL, covering unusual escalation volume, escalation without a matching privilege drop, action outside a maintenance window, repeated reverts on a single device, autonomy being widened, halt being issued, support impersonation, authentication failures, and the export pipeline itself going quiet. Each one documents the benign situations that will fire it, because a detection shipped without its false positives is a detection your SOC mutes in month two.
19
Document shelf
Self-serve access to the artifacts a vendor review actually needs, including a pre-filled CAIQ-Lite.
Last reviewed 2026-07-30 · Security engineering
Everything a security reviewer normally has to email for. The CAIQ-Lite is the highest-leverage item on this page: it is pre-filled, answer by answer, against what is actually implemented, and it saves your team roughly a week.
Security whitepaper
availableArchitecture, threat model, and the four invariants in detail.
no gate — direct download
CAIQ-Lite, pre-filled
availableCross-checked line by line against implementation by a security engineer.
no gate — direct download
Architecture whitepaper
availableData flow diagrams, trust boundaries, and the agent privilege model.
no gate — direct download
Data Processing Agreement
availableWith the sub-processor appendix generated from the same source as this page.
no gate — direct download
Penetration test summary
availableMost recent third-party test. Findings and remediation status.
click-through NDA required
SOC 2 Type II report
pendingObservation window open since 12 April 2026. Target Q1 2027.
click-through NDA required
Insurance certificate
availableTechnology E&O and cyber liability, with the endpoint-action endorsement.
click-through NDA required
20
The hostile questions
The questions a security lead actually asks, answered directly, including where the answer is “not yet”.
Last reviewed 2026-07-28 · Security engineering
What happens if your AI decides to delete System32?
What if your cloud is breached — can an attacker run commands on my fleet?
What they could do is trigger authorized, reversible, tier-appropriate actions on devices inside your policy — restart a service you already let us restart. That is the real, bounded worst case, and we would rather state it than claim there is none.
Can I run it fully air-gapped?
Does Agent give you remote access to my machines?
Can your support staff see my ticket contents?
What stops a bad Playbook action from breaking 6,000 machines at once?
How do I prove to an auditor what happened?
What is your bus factor on the signing key?
Still have a question this page did not answer?
Send it to security@getkoop.ai. If it is a question a reviewer would reasonably ask, the answer gets added to this page rather than emailed to one person — which is the entire point of publishing it.
security@getkoop.ai