docs(smime): record UI key-import verification

User manually imported bernd.rodler.p12 through the real Settings >
S/MIME > Import key dialog on localhost:3100 - real native file picker,
real PKCS#12 passphrase, real storage passphrase. Succeeded.

This closes the last unverified layer. Every step of the delivery path
is now proven end to end: crypto correctness, parser hardening against
hostile input, admin install, client activation under the B-04 gate,
and now UI key import.

Also fixes a stale line in the audit doc that still listed finding 5
as open after it was fixed in a4155aa3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Bernd Rodler
2026-08-04 12:09:23 +02:00
co-authored by Claude Opus 4.8
parent a4155aa342
commit 5c1f14fa8b
+15 -1
View File
@@ -44,7 +44,21 @@ Built from the forked source with the repo's own pipeline (`npm run build` → e
Worth noting against an earlier assumption: **this bundle does not trip the `B-01` pattern scanner** — zero matches on all five patterns. `B-01` remains correct (it closed a real entrypoint-only coverage gap, and openpgp.js for the PGP plugin may yet need the override) but it is not required to install this plugin.
**Remaining risk:** findings 4 (unlocked keys persisted to IndexedDB), 5 (parser DoS) and 6 (PKCS1v1.5 oracle surface) are open. Suitable for sandbox use; findings 4 and 5 should be closed before real mailboxes.
**Remaining risk:** finding 4 is hardened but not eliminated (unlocked keys still persist to IndexedDB, not memory — see the remediation table above), findings 6/7/8/9 are open. Finding 5 (parser DoS) is fixed. Suitable for sandbox use.
### End-to-end verification (2026-08-04)
Every layer of the delivery path has now been exercised at least once:
| Layer | How verified |
|---|---|
| Crypto correctness | `roundtrip.mjs`, 28 assertions — real PKCS#12 → unlock → sign → verify → encrypt → decrypt against genuine self-signed certs |
| Parser hardening | Same suite, hostile MIME (5000-level nesting, 5000 siblings, 64 MB) fed to the real parser; confirmed the unpatched upstream parser crashes on identical input |
| Admin install path | Bundle uploaded via `POST /api/admin/plugins`, no scanner rejection, registry shows `tier=privileged`, Ed25519-signed |
| Client activation | `managed:true`, `adminApproved:true`, tier resolves to privileged, iframe spawns same-origin, `hooks=5, slots=3` with **zero refusals** under the `B-04` gate |
| **UI key import** | **User-performed**, real browser, real native file picker: `bernd.rodler.p12` imported via Settings → S/MIME → Import key, decrypted with the correct PKCS#12 passphrase (`spike`) and re-wrapped under a user-chosen storage passphrase. Succeeded. |
One near-miss during that last step, worth a minor UX note rather than a security finding: the PKCS#12-file-passphrase field has a "leave blank if the file has none" placeholder and no required marker, while the storage-passphrase field is marked required. The first attempt left the file passphrase blank and got pkijs's literal MAC-verification error — *"Integrity for the PKCS#12 data is broken!"* — which is the **correct** response to a wrong passphrase, not a bug. Most real CA-issued `.p12` files do have a passphrase, so the placeholder invites the mistake. Worth revisiting the copy in a later UI pass; out of scope for this audit.
## Findings