Security
The security model
Every claim here is a property something in the system enforces, not an aspiration. Where a defence is absent, it is named.
Tenant isolation
- Tenant data is scoped by row-level security in the database, not only in application code.
- Another tenant’s identifier gets the same answer a typo gets. Confirming that something exists but belongs to somebody else is a cross-tenant oracle.
- A revoked membership stops project access on the next request, not at the end of a cache window.
Fail closed
- A dependency that cannot be reached produces a refusal, never a permissive default.
- A revocation registry that cannot be consulted is reported as such — never treated as “not revoked”.
- A permit constraint this build cannot enforce is refused rather than ignored.
- Custody with a wrong or missing key encryption key does not start, or refuses to sign. It never signs with something else.
No universal administrator
ADMIN cannot approve, cannot author or activate policy and cannot register a permit. This is enforced at the route, not by hiding a button: a hidden link is a courtesy, and typing the URL gets the same refusal.
On the network side there is no module account that can act on everyone, governance has exactly four actions, and none of them reaches the Trust protocol or a user’s assets.
Secret handling
- API key secrets are shown once and stored only as a hash.
- Private keys are never returned by any endpoint, and there is no export API.
- The audit trail records a digest of what was signed, never the document and never key material.
- Log redaction is configured, and a leakage scan runs against real deployment logs.
Semantic signing
Custody accepts an operation from a closed set and builds the transaction itself, stamping its own chain id. A caller cannot send bytes, a digest, a raw sign document, an Any or a type URL, because no field carries one — and the route refuses those names explicitly rather than ignoring them.
Key-class isolation
Approval keys are Ed25519 and chain signing keys are secp256k1, and the database refuses a row with the wrong pairing. An approval key presented on the chain route is refused by name, before anything is decrypted. Permit issuer keys, policy authorship keys and validator consensus keys are deliberately never in Custody.
Software custody, and what it is not
Bengar Custody is self-hosted software custody. Keys are encrypted at rest under a KEK held outside the database, and during one signing operation the key exists in that process’s memory. That defeats a stolen dump, a copied volume, an edited row and a compromised Gateway. It does not defeat root on the Custody host.
It is not an HSM. A hardware backend is an optional higher-assurance option that Bengar does not ship today, and a PKCS#11 software token would be a simulator rather than a device.
The chain boundary
The chain witnesses; it does not authorize. A decision never waits for a block, chain finality is a property of the audit trail rather than of an authorization, and a chain outage does not stop the product.
UNKNOWN, replay and idempotency
- An outcome nobody observed is UNKNOWN, held for a person, and never retried automatically.
- An execution nonce binds one execution to one action; a repeat replays rather than acting twice.
- An approval is consumed once. A replayed approval is refused.
- A gating artifact’s nonce is spent on use, and spent nonces outlive the gate.
Audit and proofs
- Audit rows cannot be updated or deleted, including by the schema owner.
- Batches are anchored so the trail can be checked by somebody who does not trust us.
- Verification has four outcomes and they are never collapsed into a boolean.
What Bengar does not have
No SOC 2 report. No ISO 27001 certificate. No FIPS validation. No penetration test by an external firm has been commissioned. If a page anywhere on this site implied otherwise, that would be the most consequential falsehood on it — so it is stated here instead.
The network has no public testnet and no mainnet, and real multi-host validation is an open gate. Test coin has no value.
Reporting something
Security reports go to the repository’s security policy rather than to a public issue. Please include what you did, what you expected, and what happened.