Diffhold pre-alpha

Security model

What Diffhold guarantees, what it trusts, and what is still open. The full threat model, with 25 threats and the evidence for each, is docs/threat-model.md in the repository.

Guarantees

What it trusts

BoundaryControl
Gateway → DiffholdMutual TLS with a pinned client name. The agent identity comes from gateway metadata, never from request headers.
Grants in agent namespacesHMAC-SHA256 over the grant, the Secret's name and UID, with a key in Diffhold's namespace that agents can't read. A tampered grant is denied and revoked.
Used-grant markersCreated atomically in Diffhold's namespace, out of the agent's reach.
PoliciesRead only from Diffhold's namespace by default. A policy's ServiceAccount must be in an agent namespace and used by one policy only.
ApproversTheir own token, checked by TokenReview with a dedicated audience. The agent and agent-namespace ServiceAccounts can't approve.
EvidenceHash-chained audit log. Secret values and policy-chosen paths are redacted; approvals stay bound to the unredacted change.

Fixed before any outside use

The threat model found seven issues that blocked outside use. All are fixed, and each fix started with a test that reproduced the attack.

IDIssueStatus
T1Agent identity could be claimed with a headerFIXED
T2The gRPC port had no authenticationFIXED
T3An apply token could write a different specFIXED
T4A write without a name matched any objectFIXED
T5Grants could be edited, forged or replayedFIXED
T6Any policy could take over an agent's ServiceAccountFIXED
T7Approvals used a shared token and ignored approver rulesFIXED

Hardening before v0.1

IDRiskControlStatus
T13An agent ServiceAccount with RBAC over webhook configurations, AgentPolicy, RBAC or Diffhold's namespace could switch off its own guardPermission self-check at startup, on policy change and every 5 minutes. warn reports; enforce also denies that agent's callsDONE
T14A mutating webhook or server default changes an applied object after policy checked itConditions run again on the dry-run's predicted objectDONE
T16Audit records rewritten wholesaleEd25519-signed checkpoints of the chain head, replica IDs and sequence numbers. Ship logs to append-only storage to catch truncation of the unsigned tailDONE
T18An agent floods Diffhold or its approversratePerMinute and a cap of 20 open approval requests per agentDONE
T20Admin traffic read on the networkHTTPS on the admin port with the chart's certificateDONE
T22Supply-chain compromiseActions pinned by SHA, Dependabot, SBOM and provenance. Image signing at the public releasePARTIAL

An external review of the credential path is required before the v0.1 release.

Known limitation

kubernetes-mcp-server applies changes client-side, while Diffhold predicts them with a server-side apply. When an apply removes fields, the two can differ, and the backstop then denies the write. This fails closed.

Reporting a vulnerability

Until the source repository is public, report security issues privately through GitHub private vulnerability reporting on this site's repository. Do not open a public issue.