Security
How this handles your keys, and what it does not promise
The cryptographic claims Flanner Mesh makes, in one place, each with its limits stated. Written to be forwarded to whoever reviews tools before your team adopts them. Flanner Curb's claims follow, under their own headings.
The client is MIT-licensed and every claim here is checkable in the source. See also what we store.
Identity and signing
Keys are generated on your machine
Each device makes its own Ed25519 keypair the first time it enrols. The private half never leaves that machine — not to Flanner, not to your own administrator.
A device id is a hash of the public half, so nothing assigns it and nobody can issue you one. That is also why a browser cannot enrol a device on your behalf, and why forwarding an invitation enrols the other person's machine rather than yours.
What this does not cover: The private key is stored in your OS keychain where one is available, and otherwise in a file created 0600. Anyone with your logged-in user account can use it.
Every artifact is signed at the source
Plan versions, comments, review decisions, tombstones, shared memories and messages are all signed by the machine that created them. A receiving device verifies the signature against the author's public key from the organisation keyring.
The peer that hands you an artifact is not the peer you trust. A hostile device can offer whatever it likes; anything it did not legitimately receive fails verification and is dropped.
Access control
Entitlements are short-lived and checked locally
The control plane signs a statement of which workspaces a device may enter and with what role. Devices verify it themselves, offline, so syncing works with the control plane unreachable.
They last a day. Revoking a device or removing a member takes effect when the entitlement next renews rather than needing a revocation broadcast to arrive.
What this does not cover: An expired entitlement stays usable through a grace window for reads, so a device that has been offline still works. Writes require a current one, which caps the window in which a revoked device can push at one lifetime rather than a lifetime plus the grace.
Requests are signed and replay-protected
A peer request carries a signature and a nonce. The nonce is spent after the signature is checked and never before, so a captured request cannot be replayed even within the clock-tolerance window.
Being reachable grants nothing. A caller needs a signed request and an entitlement naming both its own device and the workspace it is asking about.
Transport
Content travels device to device
Plans and memory move over an encrypted QUIC connection between your machines. Flanner's servers store accounts, device public keys, workspace membership and billing. They never receive plan or memory content.
Devices find each other by public key, through a discovery service run by n0, the company that makes the iroh networking library. Each device publishes its current network addresses there. There is no VPN to install, no port to open and no administrator rights needed: each machine dials out and answers on that connection.
The relay cannot read what it forwards
When two machines cannot reach each other directly, an encrypted relay forwards the bytes: one of n0's public relays, or Flanner's own where it runs one. It sees that two devices are exchanging something, and not what.
Whether a device may use Flanner's relay is derived from the same facts as its entitlement, so a cancelled subscription stops it relaying without a second list to keep in step. n0's public relays are open to any device.
What this does not cover: Traffic analysis is not addressed. Whoever runs the discovery service or a relay, n0 or Flanner, can see device ids, IP addresses, and connection timing and volume.
Content
Secrets are refused before they are stored
Anything written to memory is checked against eighteen credential patterns plus an entropy test — on what you type, on what an agent proposes, and again on anything a teammate sends you.
A peer's signature proves who wrote something. It is not this device's judgement about whether to keep it, so the check runs on received content too.
What this does not cover: It is a pattern and entropy check, not a proof. A credential that resembles ordinary prose can pass it. Treat it as a backstop, not as permission to paste secrets.
Withdrawal is a request, not an erasure
Withdrawing a shared memory, or retiring a plan, signs a tombstone that peers honour: they stop recalling and stop advertising it.
A device that already received the content still has the bytes on its disk. No design without a central copy can reach into somebody else's machine, and Flanner does not claim to.
What this does not cover: If content must be provably destroyed, this is not the tool for it. That is a property of holding no central copy, which is the same property the rest of this page sells.
Flanner Curb: reports
Output is redacted for every caller
flanner curb map and its JSON carry counts by severity, category and channel. They never carry a credential's name or location. No flag, environment variable or terminal setting changes that, because an agent can unset its markers and fake a terminal.
Names and locations appear only in a window on your screen, which flanner curb show opens in a process of its own. Nothing comes back to the command that asked, and nothing with full detail is written to disk. The Curb pages in the local web UI are redacted the same way, with the one exception described under changes below.
What this does not cover: An agent that writes its own code can still scan the disk, or read the screen, as you. Only the agent's sandbox and deny rules stop that. A machine with no desktop session gets redacted reports only.
Everything is worked out on your machine
Curb reads agent settings and credential locations locally, and runs nothing from the repository it reads. It offers no MCP tools, so an agent cannot call it as a tool and get a report back.
The leak sweep is offline. A secret's value is held only long enough to make a keyed fingerprint: HMAC-SHA256 under a key made on the device, which never leaves it. Stored reports keep counts, classes and fingerprints for 30 days, never a value or a location. A found secret goes to its own issuer only when you run a sweep with --validate and answer yes, and it asks every run.
What this does not cover: A report describes settings, not a running session. A session started with other flags, profiles or settings files may reach more than the report shows, and every report says which launch it assessed.
Flanner Curb: changes
Every change needs a yes from your operating system
The process about to write asks the operating system to confirm that a person is present, and names the change: Windows Hello or the account password in the Windows Security prompt, Touch ID or the account password on macOS, polkit on a Linux desktop. None of them reads the terminal that started the command, so an agent that runs the command cannot answer.
A yes is a grant: single use, valid for two minutes, bound to the hash of the exact change, and held only in memory. A write without one fails. Three refused or ignored requests in ten minutes pause requests for an hour. With no approval method, Curb stays read-only.
What this does not cover: A password prompt is weaker than a fingerprint: a look-alike window could capture the password. Approvals stop an agent using Curb to change settings. They do not stop an agent that edits a settings file itself.
Fixes only tighten, and are backed up
A fix is planned only if no channel ends up broader, judged on what the settings allow before and after, not on the kind of edit. A change Curb cannot judge is left for you, with the reason.
Each changed settings file is copied to a user-only folder for 7 days. A settings file can hold tokens, so the same fix denies Claude Code that folder. Codex is denied it only when it uses a permissions profile, which its older sandbox settings cannot express.
What this does not cover: Fixes go into each agent's user settings, which that user can undo. Scrubbing a secret out of a file keeps no backup, because a backup would be another copy, so it cannot be undone.
Names in the web UI: one browser, five minutes
The Curb pages in the local web UI hide credential names and locations, as the terminal does. Asking to show them gives the page a four-digit code, and the operating system's prompt shows the same code. After a yes, that one browser sees names for 5 minutes.
The browser is known by a random token in a cookie that scripts cannot read. Tokens and expiry times live in memory only, so restarting the web UI ends every reveal. Responses that carry a name are sent with no-store. Secret values are never shown.
What this does not cover: For those 5 minutes, anything that can read that browser's memory or its session cookie can read the names. A Linux desktop's prompt cannot show the code, so there names stay in the desktop window.
Flanner Curb: team policy
Policies are signed, versioned and checked on the device
An organization's agent policy is signed by a policy key, separate from the key that signs entitlements. The list of valid policy keys is itself signed by the entitlement key, which every device already holds. So a device checks a policy against the list, and the list against a key it already trusts.
Versions only rise. A device refuses a lower version, the same version with other contents, another organization's policy, an unknown or revoked key, and an expired policy, and keeps the one in force. An expired policy stays in force, flagged: a device never weakens on its own.
The delegation covers tightening only
Enrolling a device is one approval, the delegation. It lets signed policy make changes that only tighten, and the device works that out against its own settings, with the same test fixes use. Anything else waits for a person to approve that exact change on that device. The delegation can be withdrawn at any time.
So a compromised control plane can push a tightening, and nothing broader.
What this does not cover: Whether a change only tightens is the client's judgement, and a fault in that test would be a fault on every device. Without device management, a policy lands in user settings, which the user can undo; Curb reports the drift.
Device reports are minimised, signed and keyed per device
A fleet report holds the device id, a sequence number, agent names and versions, the policy state, and counts by severity and exposure class. No paths, usernames, hostnames, repository names or fingerprints.
Each report is signed with the device key and carries the hash of the one before it. flanner curb fleet checks every signature and the order itself, so an admin need not take the console's word. Fingerprints of secrets are keyed with a key that never leaves the device, so nobody can tell whether two devices hold the same secret.
Alert destinations are encrypted at rest
To relay an alert, the hosted service holds your webhook or Slack address and a signing secret. Each is encrypted under a data key of its own, and that key is wrapped by a key in Vault transit, which will not export it. Only the job that delivers alerts can open one. The console shows a value's last four characters.
Each delivery carries an event id, and a webhook's carries a signature, so a receiver can drop repeats and forgeries. An alert waits for delivery for 7 days at most.
What this does not cover: If the wrapping key is lost, every stored destination is lost with it, and admins enter theirs again. The token for your own audit collector is the one secret the API can open, under a separate key, because a device has to be given it.
Flanner Curb: commit attribution
Each agent signs with its own key, through a broker
Each agent on each device has a random Ed25519 key, never derived from the device's identity key. The private half lives only in the OS credential store. There is no file fallback, because an agent can read files: with no credential store, attribution is off.
git calls a broker, flanner-curb-sign, for an agent's commits. It signs only while an agent session the hooks recorded is running a shell command, and logs the commit, the key and the session. A commit outside such a session is refused. Signatures are OpenSSH's, so git, ssh-keygen and GitHub read them.
What this does not cover: A signature shows which key signed, not who wrote the code. You, or malware running as you, can call the broker inside an agent session, and the action log it relies on is your own file.
Keys are registered with proof, and checked against a signed registry
Registering a key carries two signatures: the device's, and the key's own over the device id, the public key, a fresh nonce and any key it replaces. A key's owner never changes, so one device cannot register or replace another's key.
Your organization's registry lists every key with its owner and status, signed by the entitlement key. A device refuses a registry that is older, changed without a new version, moves a key, or drops a revocation. A revocation is never undone, and it applies offline.
What this does not cover: With no fresh registry, a signed commit shows as key status unknown rather than attributed. Every commit by a revoked key counts as untrusted, whatever its date, because a commit's date can be forged.
Reporting a vulnerability
Open a private security advisory on the GitHub repository. This is a small operation with no paid support tier, so there is no response-time commitment — but security reports are read before anything else.