SECURITY AND GOVERNANCE
Nothing moves without permission¶
EKKA authorizes every action an AI agent takes before it happens, and signs every action it allows into a hash chain that verifies with EKKA switched off. An action without permission stops before any I/O: no socket is opened, no DNS lookup is made, no credential is read from your vault.
This page is for the person who has to approve an AI agent touching a production system, and for the engineer they will ask.
Security and governance are one thing here, not two features sitting next to each other. A Grant is least privilege. Deny before I/O is access control. A receipt is the audit trail. Revoking a Grant is incident response.
Every claim on this page ships with the command that checks it, and every one of those commands runs on your own machine. A control you cannot test yourself is a control you are taking on trust.
Check the whole signed chain right now, with no EKKA service in the loop:
✓ All 234 records check out.
Nothing has been changed, added or removed since the first one.
36 of them were signed by this machine's Enclave, and those signatures are valid.
This ran entirely on your machine. It did not ask EKKA anything,
which is the point: if checking our proof needed us, it would not be proof.
-
Governed
Every action is authorized before it happens. No Grant, no I/O.
-
Proven
Every allowed action is signed after it happens, into a chain anyone can verify offline.
-
Private
Your prompts, your rows, your files and your credentials never reach EKKA.
How does EKKA stop an agent before it acts?¶
An agent asks to do something. EKKA decides first, and a refusal is complete: no socket is opened, no DNS lookup is made, no secret is read from your vault.
The refusal itself is recorded as a signed event in your audit chain, the same chain an allowed action lands in. "It was blocked" is evidence, not a claim.
Preview any decision without executing it:
Read the decision after the fact:
--check reports ALLOWED or DENIED with no I/O and no cost. It is the same
decision the real call gets.
A refusal and an allow are different shapes of the same evidence
An allowed action produces a signed receipt chain you verify offline
against published keys. A refusal produces a signed deny event in your
audit chain, carrying who was refused, what they asked for, and the reason
code. There is no receipt for work that never ran.
Both are signed. Neither depends on our dashboard, or on us.
One thing we do not put in the chain: our own bugs. If EKKA cannot classify an operation or cannot parse a token it just issued, that is an error, not a decision about you. Recording it as a refusal would make "we were broken" indistinguishable from "you were not allowed".
How do I give an agent permission, and take it back?¶
You do not write access-control code. You set a Grant: this agent, this operation, this resource, through this gate, until you revoke it.
ekka gate grant list # what is authorized right now
ekka gate grant revoke <grant-id> # the next attempt is refused, live
Revocation is not a deploy. The operation that worked a second ago is refused a second later, and the refusal is recorded like any other decision.
Grants are also time-boxed where you want them (--ttl), and the token a
gate receives is issued just in time for one operation rather than held open.
What can EKKA see?¶
Govern decides whether an action is allowed. It does that without seeing the content of the action. Prompts, model output, database rows, file contents: none of it reaches EKKA. What reaches EKKA is the shape of the request and cryptographic digests of the result.
We call this a No Knowledge Proof, and it has its own section below.
That property holds whether you run your own Enclave or use a hosted one. Where your data lives is a choice; not being read is not a choice.
What leaves your machine is the field-by-field detail, including the one thing we do receive when a run finishes and why.
What is a No Knowledge Proof?¶
A No Knowledge Proof is a record that proves what your agent did without containing what your agent handled. EKKA can stand behind that record because EKKA signed it, and EKKA never saw the contents.
Think of a thumbprint¶
A thumbprint identifies a person with certainty. No two people share one, so matching a print to a person settles the question beyond argument.
Now try it the other way around. Look at a thumbprint on its own and say what that person looks like, what they are called, where they live. You cannot. The print answers who and carries nothing else about them.
A receipt works the same way. When your agent reads a row or writes a file, EKKA records a digest of it: a short string calculated from the content. Hand anyone the same content and they can calculate the same digest and confirm the record matches. Nobody can work backwards from the digest to the content, because the content was never put into it.
EKKA holds the thumbprint. The data it belongs to stays with you.
What that buys you¶
- Your prompts, model output, database rows and file contents stay in your environment, so there is no copy of them on our side.
- The proof still works. An auditor can confirm the record was not altered after the fact without ever seeing the data it describes.
- It holds however you run EKKA, hosted or in your own Enclave. Where your data lives is a separate choice, and this does not depend on it.
Where the comparison stops¶
It is not zero-knowledge cryptography. Zero-knowledge is a specific branch of mathematics for proving a statement true while revealing nothing else about it. This is blunter and easier to check: we signed it, and we never saw it.
It is also a claim about the content of an action, not about every field. When you dispatch a plan, the inputs you typed travel with it, because EKKA authorizes the call against them. What leaves your machine is the field-by-field list.
Check it yourself¶
Read the signed record of a run you just did, and look for your own data in it. The record names what was touched and carries the digests. The rows, the prompt and the file contents are not in there.
Where do my credentials live?¶
Secrets live in your Enclave's vault, encrypted at rest and sealed by your operating system's keychain. The gate injects a credential into the outbound call; nothing upstream of it ever holds one.
Three consequences worth stating, because each one is a real attack that does not work here:
- A caller cannot set an authorization header. The gate refuses the request rather than letting a plan overwrite the credential it was given.
- A refusal never quotes the request. Error text cannot leak a credential that was sitting in a query string, because the message names the field and never the value.
- Copying the vault files off the machine gets you nothing. The sealing key is in the keychain, not in the files.
What can an agent not do, even with a Grant?¶
Some limits are structural, which means they hold even if every other check somewhere failed.
- A read cannot write. A read-class call has no slot on the wire for a method or a body. It is not that a check refuses the mutation, it is that there is nowhere to put one.
- An origin is pinned. A connection reaches the host it was made for. It cannot be redirected to another.
- Narrowing rules bind method and path together. A connection can be limited
to
GET /v1/messagesand nothing else on the same host. - Network reach is declared. A connection states whether it may reach the public internet, your loopback, or your private network. The default refuses a local address outright.
Can anything change quietly?¶
- A plan version is frozen when you create it. It runs the steps it was
created with, and its name and number in the audit chain always mean those
bytes. Fixing a plan makes the next version beside the old one. Check the
bytes yourself:
ekka plan show <plan> --verifyrecomputes the plan's fingerprint and says whether it still matches what was recorded when the version was created. - A skill version is never rewritten. Creating the same name again makes
the next version. A plan naming
@1.0.0keeps running@1.0.0, and the body's SHA-256 is served with the skill, so an auditor can recompute it and prove which body a past run executed. - Cataloged APIs are immutable. Changing an API means a new version beside the old one, so a connection pinned to the old one keeps behaving.
- Connection records are fingerprinted. A record altered on disk by anything other than EKKA is refused before the call is considered.
- The audit trail is append-only, enforced in the database rather than by
convention: a
REVOKEon the runtime role and a trigger on top of it, because aREVOKEdoes not bind a table's owner. - A change to who may do what cannot be saved without its audit entry. For Grants, published Skills and organization settings, the database refuses the transaction unless the entry is written alongside the change. This is the other half of append-only: one stops an entry being removed, this one stops a change happening without an entry in the first place.
You cannot check our database privileges, so check the consequence
Append-only is enforced on our side, which means you cannot run a command against it, and a claim you cannot check is a claim you have to take on trust. That is not how the rest of this page works.
What you can check is the property it exists to produce: that nothing in
your chain was altered after the fact. ekka audit verify recomputes every
hash link and checks every signature against the key govern publishes at
/.well-known/audit-signers. That key is public and the check runs on your
machine, so this is not our word for it. If a row had been edited or removed,
that is what would catch it, whatever our privileges say.
Note what it does not tell you: whether something that happened is missing from the chain in the first place. Integrity and completeness are different properties, and no amount of re-reading a chain settles the second one.
Completeness is built in rather than checked, for the records that decide who may do what: the change does not commit unless its entry commits with it. So the check you can run is the ordinary one, do the thing and look for it.
If the entry had been missing, the first command would have failed. What that covers and what it does not is in Governance receipts.
How do I check EKKA's proof without EKKA?¶
That recomputes every hash link and checks every signature against the identity that made it, on your machine, with no EKKA service in the loop. If checking our proof needed us, it would not be proof.
An auditor does not need an EKKA account, and does not need to trust your screenshot. They need the chain and the public keys.
ekka receipts verify covers the whole local chain and takes no run id. For one
run, read its signed record with ekka receipts show <run-id>.
Governance receipts explains what a receipt contains and how to read one.
Does the CLI track me?¶
The ekka binary contains no third-party analytics. No product analytics,
no session recording, no activation telemetry. Check the binary you installed:
strings $(which ekka) | grep -icE 'posthog|sentry\.io|segment\.io|amplitude\.com|mixpanel|datadoghq'
That prints 0. It is the exact list our release pipeline checks on every
build, so the command you run is the check that gates the release rather than a
friendlier version of it.
Crash reports are first-party, minimal, and optional. The error text stays on your machine, because a crash message can contain whatever the program was holding at the time.
Which command proves which claim?¶
Every claim on this page, in one table.
| The claim | The command |
|---|---|
| A refusal happens before any I/O | ekka gate <type> <op> --resource <name> --check |
| These are the permissions that exist right now | ekka gate grant list |
| Revoking is live, not a deploy | ekka gate grant revoke <grant-id> |
| Secrets are names to us, never values | ekka secret list |
| This is every endpoint my Enclave contacts | ekka enclave config |
| The proof verifies without EKKA | ekka receipts verify |
| The decision record for one run, including a refusal | ekka run show <run-id> |
| Nothing in my chain was altered after the fact | ekka audit verify |
| A change to what an agent may do cannot happen unrecorded | ekka gate grant add ... then ekka audit list |
| There is no analytics vendor in the binary | strings $(which ekka) \| grep -icE 'posthog\|sentry\.io\|segment\.io\|amplitude\.com\|mixpanel\|datadoghq' |
How do I report a vulnerability?¶
Write to contact@ekka.ai, the address in our security.txt. Our full policy, including safe harbor and what to expect, is at ekka.ai/security.