docs(security): open KeyCape exposure rotation incident
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02929-244b-7391-b933-c04010e8eedb
This commit is contained in:
tegwick 2026-08-23 14:05:07 +02:00
parent 61aeafef71
commit 9264a8a613

View file

@ -0,0 +1,121 @@
---
id: NK-WP-0033
type: workplan
title: "Contain and rotate the exposed KeyCape credential bundle"
domain: infotech
repo: net-kingdom
status: active
owner: codex
topic_slug: net-kingdom
planning_priority: P0
created: "2026-08-23"
updated: "2026-08-23"
origin: routed
origin_ref: "State Hub message 8cc44a39-683c-4fab-80dd-b2275d0728e0"
related:
- NK-WP-0032
---
# NK-WP-0033 — KeyCape credential exposure containment and rotation
KeyCape reported that an agent tool rendered the base64 data map of the live
`sso/keycape-config` Secret. Base64 is encoding, not protection. Treat the
carried RS256 signing private key, LLDAP bind credential, Authelia client
credential, and privacyIDEA admin token as exposed even though no value was
decoded, reused, or intentionally repeated.
No task in this workplan authorizes a credential value in Git, State Hub,
agent output, command arguments, or non-secret evidence. Live mutation requires
the exact provider/custody owners, a reviewed sequence, abort and rollback
conditions, and the authority stated by the owning execution path.
## T01 — Contain, classify, and route the exposure
```task
id: NK-WP-0033-T01
status: done
priority: high
```
Mark every credential class in the rendered bundle exposed, stop further
rendering, consult credential routing, notify custody and issuer owners, and
publish a sanitized risk notice.
Completed 2026-08-23. State Hub decision
`c43eef14-a209-41b1-ba67-781ca14c5ea2` requires governed rotation. Coordination
was routed to railiance-platform in `acf98be3-ff6b-4270-bd21-0193bebd806b`
and KeyCape in `c774f748-6240-4733-89c7-518079a30f61`; risk-nexus received
sanitized notice `c5d67801-1bc3-4e66-98c9-e08a58313970`. No value was inspected
or copied.
## T02 — Agree the value-safe rotation and issuer-continuity contract
```task
id: NK-WP-0033-T02
status: progress
priority: high
```
KeyCape and railiance-platform must name the authoritative provider, custody,
and consumer update for all four classes; select one revision-pinned bundle or
field-safe sequence that cannot replay a stale exposed value; specify positive
and predecessor-negative verification; and state abort, rollback, and evidence
rules.
KeyCape currently loads one private key and signs under static `kid=key-1` even
though its JWKS type can serve multiple keys. The contract must either add and
verify an active-key plus retained-public-key overlap or deliberately accept
immediate token invalidation and verifier refresh. Evidence was routed in
`2b24ccc2-c031-453e-ac70-52f0aaa127d5` and
`9277d962-b511-4da7-9fc6-2c79bac448c1`.
Warden routing has no concrete entries for these four KeyCape lanes. Catalog
repair was requested in `e5794329-cda5-4a6f-8234-a6eaa1fc318c`; generic or
unrelated routes do not authorize execution.
## T03 — Implement a non-printing, non-stale rotation path
```task
id: NK-WP-0033-T03
status: wait
priority: high
```
After T02 review, implement or select an owner-controlled path that receives
replacement material through hidden input or mode-0600 files, updates every
provider and consumer in the agreed order, never reconstructs the bundle from
stale local inputs, and retains no plaintext artifact after verification.
Do not use `sso-mfa/bootstrap/creds-rotate.sh` through an agent as currently
written: it prints generated replacement values and its signing-key path
causes immediate invalidation. Do not use a helper that reads the live Secret
unless its output and temporary-state behavior have been independently
reviewed for this incident.
## T04 — Execute the governed replacement cutover
```task
id: NK-WP-0033-T04
status: wait
priority: high
```
Under the separately approved authority/window, replace the signing material,
LLDAP bind credential, Authelia client credential, and privacyIDEA admin token;
roll or reload every affected provider/consumer; preserve or explicitly end
JWT continuity according to T02; and abort on partial-bundle or stale-source
evidence. This task is not authorized until T02 and T03 are done.
## T05 — Prove replacement, predecessor rejection, and cleanup
```task
id: NK-WP-0033-T05
status: wait
priority: high
```
Record only sanitized identifiers, public-key fingerprints, revisions,
rollout status, positive authentication/MFA outcomes, predecessor rejection or
expiry, cleanup receipts, and residual limitations. Close the incident only
after all four credential classes have an authoritative disposition and no
temporary plaintext or stale bundle remains.