docs(security): open KeyCape exposure rotation incident
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02929-244b-7391-b933-c04010e8eedb
This commit is contained in:
parent
61aeafef71
commit
9264a8a613
1 changed files with 121 additions and 0 deletions
121
workplans/NK-WP-0033-keycape-secret-exposure-rotation.md
Normal file
121
workplans/NK-WP-0033-keycape-secret-exposure-rotation.md
Normal 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue