Skip to content

Security model

Talmi decides who may mint which downstream tokens, so its security properties are worth understanding. This page covers the built-in guarantees; Config source trust and Auditing go deeper on those two areas.

Hardening checklist for public exposure

Before putting Talmi on a public network:

  • [ ] Rate limiting on, with trusted_proxies set if you run behind an ingress. See Configure rate limiting.
  • [ ] TLS at the edge. Talmi speaks plaintext HTTP; terminate TLS at the ingress or load balancer.
  • [ ] Secrets as file: or env: refs (raw: is for local testing only). See Secrets.
  • [ ] A stable signing key (ES256 from a mounted PEM), not the --dev ephemeral key. See Enable admin access.
  • [ ] The config source locked down: review-gated branch, least-privilege App. See Config source trust.
  • [ ] PostgreSQL store and auditor so leases and the audit log survive restarts. See Run with PostgreSQL.
  • [ ] config vet clean in CI before every deploy.

Default deny

Anything the rules don't explicitly allow is denied, and the engine does not assume config vet ran. Each of these denies on its own:

  • no rule matches the principal;
  • a requested resource has no realm prefix, or an unknown realm;
  • a request has an empty action list;
  • a rule's condition is empty and allow_empty was not set;
  • a match expression errors or returns a non-boolean.

A request is authorized only if the union of matching allow grants covers every requested resource=action, and the grant never exceeds the realm's capability ceiling.

Anti-spoofing identity

The identity keys iss/sub/id/issuer in conditions always come from the verified principal, never from token attributes. A token claim named sub cannot override the verified subject.

Least privilege at mint time

When several provider instances can serve a resource, the resolver picks the one whose action ceiling most tightly fits the request. A read request is served by a read-only App even if a write App exists in the same realm.

Secrets

Credentials are secret.Refs (file: or env:, or raw: for local testing) resolved at load time and never logged. Error messages reference the scheme or variable name, not the value. Minted token values are never persisted - only a SHA-256 fingerprint (for tracing) and a hash of the revocation secret.

Server-generated identifiers

Lease IDs, artifact IDs, and audit IDs are generated by the server, never derived from client input (for example, the correlation header). This prevents a client from colliding or predicting them.

Transport

Talmi speaks plaintext HTTP and expects TLS termination at the ingress or load balancer. Request bodies are capped (1 MB). 5xx responses return a generic message plus a correlation id; internal error detail is logged, never returned.

Sessions

Admin session JWTs are signed with a pinned algorithm (keyfunc rejects a mismatched alg), so there is no algorithm-confusion or alg=none bypass. See Sessions and admin.