v1.1 — YubiKey end-to-end + Silent VSC Fallback discovery
Headline finding — Silent TPM Virtual Smart Card Fallback Discovery
During v1.1 enrollment testing we discovered that smart card enrollment can silently land on a TPM-backed Virtual Smart Card instead of the intended physical token, with no error surfaced anywhere in the GUI. Logon works, audit events fire, the user is happy — but the credential is on the wrong factor. A hardware-factor authentication design silently demotes to a software-factor design.
The discovery doc captures the failure mode in full: environment, what was observed, why it happened, how certutil -scinfo exposes it, a detection-script sketch, and four compensating controls. The most important compensating control is procedural — the operator runbook now mandates a four-point acceptance check on every enrollment.
📄 Architecture/Lessons-Learned/2026-06-16-Silent-VSC-Fallback-Discovery.md
Maps to NIST SP 800-53 IA-2(11), IA-5(11), CM-6, AU-6 and CISA ZTMM Identity pillar.
What's new
YubiKey enrollment validated end-to-end
jdoe enrolled on a physical YubiKey 5 NFC via New-YubiKeyToken.ps1 + Enroll-on-Behalf, with the Yubico Smart Card Minidriver, against the lab's internal Issuing CA. Logs into WO02 with card + PIN under full SmartcardLogonRequired=True enforcement. Event 4768 Pre-Auth Type 16 (PKINIT) on the DC confirms the protocol-level handshake.
Slots 1, 1b, 1d, and 4 of the Demo-Walkthrough captured and embedded:
- Slot 1 —
01-lockscreen-smartcard-only.png— lock screen with smart-card-only logon - Slot 1b —
01b-certutil-scinfo-yubikey-chain-validates.png— cert chain validates on physical reader - Slot 1d —
01d-certutil-scinfo-yubikey-cert-context-jane-doe.png— Subject + UPN binding evidence - Slot 4 —
04-session-lock-on-card-removal.png— ~2-second session lock on card removal
Hirsch uTrust FIDO2 FIPS — declared NO-GO for PIV (n=2 cards)
Factory 3DES management key rejected on both cards (OpenSC admin_mode failed -1201). The vendor minidriver assumes an already-personalized card; it does not personalize one. FIDO2 applet on the same cards works fine — but for PIV / AD smart-card logon, the card is a dead end without the vendor's per-card management key + personalization software.
This is now the lab's procurement-evaluation criterion for any new card form factor: can the card be brought to a known-management-key state using off-the-shelf tooling (ykman, OpenSC, GIDS minidriver), or does it require vendor-specific software + per-card management key?
Enrollment kit — five new operator artifacts
In Lab-Kit/03-DomainController/:
New-LabUser.ps1— AD user creation with OU resolver + numbered menuNew-TokenEnrollment.ps1— RA + Issuer ceremony script (SCRIPT-ICAM-011, NIST SP 800-53 AC-5)New-YubiKeyToken.ps1— YubiKey PIV provisioning (SCRIPT-ICAM-016)Deploy-ScriptsToDC.ps1— SMB-based deploy of the three above to Lab-DC01
In Lab-Kit/Reference/:
RUNBOOK-YubiKey-Enrollment.md(RUNBOOK-ICAM-001) — operator runbook for the scripted pathMANUAL-Enrollment-Walkthrough.md(RUNBOOK-ICAM-002) — GUI-driven walkthrough using the real-world "copy a peer in ADUC" pattern. Companion piece showing what the scripts automate, click-by-click.
The two runbooks are explicitly cross-referenced. Anyone reading both gets a complete picture of the workflow regardless of whether their environment uses scripted automation or GUI-driven user management.
Card-Test-Matrix.md filled in
PIV and FIDO2 rows populated for both tested cards (YubiKey 5 NFC, Hirsch uTrust FIDO2 FIPS). Six observations documenting the YubiKey path that works, the Yubico minidriver requirement, the mgmt-key sequencing rule, the Hirsch NO-GO finding, the silent VSC fallback callout, and the procurement-evaluation criterion for future cards.
Framing rewritten as ongoing testing rather than complete — the matrix grows as new card form factors are evaluated.
Documentation expansions
Architecture/Lessons-Learned/2026-06-16-CAC-Enrollment-Session.md— full forensic session log (scrubbed) tracing the v1.1 enrollment journey with 10 documented issues and fixes- 24 v1.1 screenshots staged in
Screenshots/with named slot filenames; one redacted to hide YubiKey serial + AES-256 management key Screenshots/README.mdcatalog rewritten to reflect five-tier structure (headline / lessons-learned / session evidence / FIDO2 / portfolio reference)
Infrastructure improvements
Scrub-Repo.ps1 — two bug fixes, caught before any file was touched
Both bugs were caught by the -WhatIf preview during the v1.1 pre-push cycle, not by a real run. They're shipped publicly as documentation:
-
_*meta-key filter — when documentation keys like_README,_README_REBUILTare added to.scrub-patterns.local.jsonto explain the file inline, the scrubber must skip them. Previously, it would treat them as substitution patterns and corrupt every file containing the literal string_README. Now matchesScan-LocalRepo.ps1's existing behavior. -
Skip gitignored local-only scanner files —
Scan-LocalRepo.ps1andSCAN-README.mdare gitignored local tools that contain real values BY DESIGN (they document the scrub patterns). The scrubber must not rewrite them, since that would degrade the local documentation used during pre-push scans.
Scrub pattern coverage extended
- New literal patterns: YubiKey AES-256 management key, Hyper-V host name, YubiKey serial
- New preemptive tripwire patterns for off-repo business context that should never appear in the public repo (commercial-build entity names, vendor-relationship contacts)
- Four
_README_*documentation keys explain the file's organization, rebuild history, and tripwire policy
Deferred to a future tag
- Slot 5 — VPN EAP-TLS capture — depends on Phase 9 (Azure VPN Gateway) or Phase 9B (OPNsense on-prem appliance). Honest framing: the credential story closes when the VPN build lands, not before.
- Real AAGUID values via
ykman fido infoand equivalent for Hirsch — webauthn.io anonymizes them; device-side CLI captures pending - Optional Ansible STIG hardening pass — would push SCAP scores up but the delta from hardening is the portfolio value, not the absolute number
- Additional card form factors — GIDS smart cards and other vendors queued
For reviewers — start here
| Artifact | Why it matters |
|---|---|
Architecture/Lessons-Learned/2026-06-16-Silent-VSC-Fallback-Discovery.md |
The headline DevSecOps finding. Demonstrates ability to catch a high-severity silent failure mode that vendor and Microsoft documentation does not adequately cover, and to codify the fix as a procedural control. |
Lab-Kit/Reference/RUNBOOK-YubiKey-Enrollment.md + MANUAL-Enrollment-Walkthrough.md |
Two runbooks — scripted and GUI-driven — for the same workflow. Shows operator-engineering discipline: automation for compliance environments, manual procedure for small-shop reality. |
Lab-Kit/Reference/Card-Test-Matrix.md |
Hardware-evaluation methodology applied across multiple form factors with both ✅ and ❌ outcomes. Procurement-question criterion stated explicitly. |
Demo-Walkthrough.md |
Step-by-step live demo with slots 1, 1b, 1d, 3, 4, 6, 7, 8 captured. NIST control mapping table at the bottom. |
Diff from v1.0: 46 changed files, 19 new files, 27 modified files.
Acknowledgments: The Silent VSC Fallback failure mode was discovered during normal lab operations, not from any vendor or industry source. The methodology to detect it (certutil -scinfo as a reader-level acceptance check) is now baked into the operator runbook and the four-point verification at the end of every enrollment.