ka2a documentation
Threat model
Developer preview. Not yet production ready. This page is rendered from docs/threat-model.md of the ka2a repository at revision 96fb45e5e5f6693e779837998c3aa9581d6a37f2. It describes the behavior of that revision.
Contents
This document describes what ka2a protects, whom it trusts, which attacks it stops and which risks stay. It describes this revision, a developer preview. The requirement IDs refer to the specifications in openspec/changes/reimplement-ka2a/specs. The acceptance ledger shows the tests of each requirement. The go-live checklist turns this model into steps.
Assets
| Asset | Why it matters |
|---|---|
| Message bodies and results | They hold business data. ka2a does not encrypt them end to end. |
Signing keys (ka2a.signing-key.v1) | A key lets its holder send records as its endpoint. |
Trusted catalog (ka2a.catalog.v1) | It decides which keys are valid, which endpoints exist and which grants allow an operation. |
| Broker credentials (SASL passwords, client keys) | They give access to the topics and to the consumer group of an endpoint. |
| State directory (SQLite store, epoch witness) | It holds the outbox, the received requests, the deduplication state, the tasks and the bodies. Its loss or rollback can repeat or lose work. |
| Backups | They hold the same data as the store. |
| Correct execution | A request must not run twice when its effect is not idempotent, and a timeout must not look like a failure. |
| UI token | It gives read access to the operational UI. |
Trust boundaries
- Between endpoints: each endpoint trusts only records that a key of the catalog signed for the asserted source, and only for the granted operations.
- Between an endpoint and Kafka: the broker carries the records and stores them. TLS protects the connection. The broker sees the plaintext bodies. ka2a does not trust the broker for integrity: the signature covers the topic, the key, the sorted headers and the value.
- Between the process and its host: the files of the state directory, the keys and the catalog are on the host. ka2a checks their owners and modes, but it trusts the host operating system and the root user.
- Between the node and the application handler: the handler is trusted code. ka2a gives it the verified principal.
- Between the operator and the node: the command line and the loopback UI run on the host.
Attackers
| Attacker | Capabilities |
|---|---|
| Network attacker | Reads, changes or injects traffic between the hosts and the brokers. |
| Peer endpoint | Holds a valid key of the catalog and sends records that are valid but hostile, for example large, many or for another principal's task. |
| Broker client without a key | Has broker credentials with Write access to a mailbox topic, but no signing key. |
| Broker administrator or a compromised broker | Reads, deletes, delays, reorders or repeats the records. Changes offsets of consumer groups. |
| Local user without the service account | Reads files that are readable by others, and connects to loopback ports. |
| Attacker with the service account or root | Reads and changes everything of the endpoint. |
| Supply-chain attacker | Changes a dependency, the build or a published artifact. |
Mitigations
| Threat | Mitigation | Requirement |
|---|---|---|
| Forged records, a changed route or a forged actor name | Ed25519 signature (KA2A-WIRE-1) over the topic, the key, the headers and the value. The key must be in the catalog, bound to the source and valid at the signed time. The destination and the topic must be the local ones. The handler gets the verified principal, never an actor name from the payload. | KA2A-R1-015, KA2A-R1-005 |
| An operation that the catalog does not grant | Per-operation grants of source and destination. A denied record never reaches a handler. | KA2A-R1-015 |
| Replay of an old record by a broker or a client | Deduplication by request identity for the dedup retention, a signed expiry, a horizon per record kind, and refusal of a replay after the purge. | KA2A-R1-004, KA2A-R1-012 |
| A peer reads or cancels a task of another principal, or uses its context | Task and context authorization by the verified principal. | KA2A-R1-013 |
| Large or deep documents, floods | Bounded record size, header size, JSON depth and node count. A bounded retained-state budget (storage_pressure). Bounded queues and histories. | KA2A-R1-016, KA2A-R1-012 |
| Duplicate execution after a crash or an unknown outcome | Durable dispatch markers, held work for HoldOnAmbiguity, the same frozen bytes on a retry, operation keys with identity_conflict. | KA2A-R1-008, KA2A-R1-009, KA2A-R1-004 |
| Rollback or loss of the store | Epoch witness, backup provenance, recovery marker and the committed-offset check (broker_ahead) put the store in quarantine. | KA2A-R1-014 |
| A second owner on the same host | Exclusive flock of the state directory. | KA2A-R1-014 |
| Network attacker against the broker connection | TLS 1.2 or 1.3 with server name verification, optional revocation lists, SASL or mutual TLS. The qualified profile refuses plaintext. | KA2A-R1-015 |
| Secrets in diagnostics | Logs, metrics, the UI and default snapshots hold no bodies, credentials or raw identifiers. Metrics have no free labels except the local endpoint. | KA2A-R1-017 |
| Local users and web pages against the UI | Loopback only, a one-time token, Host and Origin checks, read-only, no external assets. | KA2A-R1-019 |
| Local users against the files | The store refuses files with group or other permissions and parents that others can write. Secret files must have mode 0600 and the effective user as owner. The catalog must not be writable by group or others. | KA2A-R1-014, KA2A-R1-015 |
| Supply chain | Pure Go, CGO_ENABLED=0, pinned modules in go.sum, reproducible release builds with SBOMs (make release-check), and make vulncheck. | KA2A-R1-022, KA2A-R1-024 |
Residual risks
These risks stay. Accept them or control them outside ka2a.
- Confidentiality against the broker: bodies are plaintext on the brokers, in the stores and in the backups. Broker administrators can read them. See Data protection.
- No erasure of one message: a body stays until its retention ends.
- Availability depends on the broker. A broker administrator can delete or withhold records. ka2a shows the unknown outcomes; it cannot force a delivery.
- A peer with a valid key and a grant can fill the retained-state budget of a receiver. ka2a has no quota per peer. Grant operations only to the peers that need them.
- A stolen signing key works until you revoke it in the catalog and restart the nodes. There is no online key revocation.
- The catalog is a static file. Its integrity depends on your review and distribution process. ka2a reports a changed file, but it trusts the file that it loaded at the start.
- The owner lock works on one host only. Two hosts with copies of one state directory are not detected and can run a request twice.
- A consistent snapshot of the whole state directory (file system or virtual machine) is
detected only when input was committed after the snapshot (
broker_ahead). - The signed times use the wall clocks of the hosts. A clock error beyond the skew rejects valid records. See Clock drift and expired records.
- The handler is trusted. A handler that leaks data or is not idempotent under
IdempotentWithKeybreaks the guarantees. - The release artifacts are not signed, and the project publishes no container image. Verify the checksums and build from a reviewed commit.
- The items of the section "What was not executed" of the newest release-candidate report are not qualified.