diff --git a/vnc/audits/SMIME-PLUGIN-AUDIT-2026-08-04.md b/vnc/audits/SMIME-PLUGIN-AUDIT-2026-08-04.md index 2072c0a3..254a1c5f 100644 --- a/vnc/audits/SMIME-PLUGIN-AUDIT-2026-08-04.md +++ b/vnc/audits/SMIME-PLUGIN-AUDIT-2026-08-04.md @@ -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