Skip to content

Pre-release. v0.1 is not out yet, so there is nothing to install and no public source to clone — the quickstart builds from a checkout.

Threat model

Onbe is worth having only if it is clear about what it does not do. This page is that list.

A leaked agent credential. The thing an agent holds is a task token that lives minutes and a task grant bound to one task, one audience and one agent. Neither is a general-purpose key. A grant presented by another agent does not exist, because a refresh authenticates the agent exactly as the original exchange did.

An agent exceeding the person who asked. The token’s scope is the intersection of the user’s scopes, the agent’s registration and the request. There is no path through the server where it widens: not at issue, and not at refresh, where the request must be a subset of what the task already holds.

A compromised agent reaching further than it was registered for. The audience must appear in the agent’s allowed_audiences; anything else is invalid_target. A token minted for one audience is not a token for another.

An off-boarded user’s agents carrying on. Every refresh re-checks that the sponsor is still active at your identity provider, with the answer cached for no longer than the token being issued. Disabling somebody stops their agents within one expires_in.

A replayed client assertion. Each jti is accepted exactly once, assertions live at most five minutes, and a replay is invalid_client.

Quiet edits to the record. The ledger is hash-chained and the table refuses UPDATE, DELETE and TRUNCATE by trigger. Changing a record breaks every link after it in its chain.

An anonymous flood filling the ledger. A caller with no credential is limited per source and its denials are summarised per reason per window; attributable denials are never summarised.

A stopped task doing one more thing — where the token is introspected. Listing an audience in high_risk_audiences puts introspect_required in every token for it, and both server SDKs ask the control plane on every call when they see that claim, so a revocation takes effect at once. A route may also be marked highRisk on its own. What the control plane cannot do is make a tool server it has never met honour either: a server written against the raw HTTP contract has to read the claim, and one that validates locally and ignores it is bounded by max_token_ttl like anything else.

  • Your identity provider is trustworthy and correct. Onbe does not authenticate people. If your provider issues a token for the wrong person, Onbe will faithfully delegate the wrong person’s authority.
  • The database is not hostile. The chain detects edits, but somebody with write access can truncate the tail, and nothing inside the database can tell that from a shorter ledger. This is why audit-verify prints one head per chain to keep elsewhere.
  • Agent private keys are kept properly. Onbe verifies signatures against a published JWKS. An attacker holding an agent’s private key is that agent, bounded by that agent’s registration.
  • The signing key is kept properly. Whoever holds it can mint tokens this control plane’s tool servers will accept, up to any scope, for any audience.
  • TLS is terminated by something you trust, and the control plane is not reachable from places that have no business reaching it.
  • Admin identities and role-based access control. There is one admin API key. It grants every admin operation, and rotating it means changing a setting and restarting.
  • Multi-tenancy. One instance serves one organisation. There is no tenant concept in v0.1.
  • Sub-agent delegation. The claim format allows a chain and tool servers enforce a limit on one, but the control plane issues depth 1 only, and the specification marks it not in v0.1. See delegation depth.
  • mTLS client authentication. v0.1 authenticates agents with private_key_jwt alone, and discovery advertises nothing else.
  • Denial of service. A per-source rate limiter is on by default (Onbe:RateLimit:*, 429 slow_down), and denials that name nobody are counted rather than written one per request. That is a floor, not a defence: unbounded volume is out of scope, so put it behind something that sheds load before it reaches the process.
  • Preventing misuse of authority the user genuinely has. If a person can delete a project and their agent is registered for that scope, Onbe will issue a token that can delete the project. It records who and on whose behalf; it does not second-guess the permission.
  • Confidentiality of tool contents. Onbe sees scopes, audiences and identifiers. It does not see or protect what the tool server actually returns.
  • Hardening of any example configuration. Examples exist to be read, not deployed.

Three things are worth stating again because they are the ones people misremember:

  1. Local validation makes revocation eventual, bounded by max_token_ttl. A kill switch does not reach a token already in flight unless the route introspects.
  2. audit-verify cannot detect a cut tail on its own. Keep the heads somewhere else.
  3. There is no agent without a human. Every v0.1 exchange requires a subject token, and a registration asking for sponsor_required: false is refused rather than accepted and ignored. Scheduled agents with a service sponsor are a later thing, not a switch you can already flip.
OnbePre-release. v0.1 is not out yet.

© 2026 Onbe