Skip to content

fix(yubikey): verify enrollment + FIPS PIN handling + work-checklist#295

Merged
DevSecNinja merged 2 commits into
mainfrom
fix/yubikey-enroll-verify-and-fips
May 4, 2026
Merged

fix(yubikey): verify enrollment + FIPS PIN handling + work-checklist#295
DevSecNinja merged 2 commits into
mainfrom
fix/yubikey-enroll-verify-and-fips

Conversation

@DevSecNinja

@DevSecNinja DevSecNinja commented May 4, 2026

Copy link
Copy Markdown
Owner

Closes #294.

What

Three related fixes/features from real macOS dogfooding with a fresh YubiKey 5C NFC FIPS:

1. Verify file post-condition (Ctrl+C regression)

When the user pressed Ctrl+C at Enter PIN for authenticator: mid-ssh-keygen, the wrapping function returned a status that fish's pipeline reported as success. The wizard then printed Enrolled: <path> and the Done. Next steps block — even though no key file was written. Trust the filesystem, not exit codes.

Now both bash and fish wizards stat <out_path> and <out_path>.pub after yk-ssh-new returns and abort with a clear Aborted: ... was not created if either is missing. The Done. summary is gated on the pubkey actually existing on disk.

2. FIPS YubiKey factory PIN handling

Brand-new YubiKey 5 FIPS keys ship with PIN 123456. ykman fido info reports "PIN is set" — true, but the PIN is publicly documented. The wizard now:

  • Detects FIPS via the device-type string and prints an explicit warning instead of a green check when PIN is set on a FIPS key.
  • New --rotate-pin flag forces ykman fido access change-pin even when one is already set.

The half-baked interactive Change PIN now? [y/N] prompt from an earlier attempt was removed — it deadlocked bats and added zero value over the explicit flag.

3. work-checklist for manual post-install steps

Some setup steps can't be automated by chezmoi: corporate URLs that require the work network/VPN (e.g. https://aka.ms/CloudMFA for SSO MFA enrollment), browser-based MFA enrollment, per-user sign-ins. Today these live in a wiki tab nobody remembers to open on a fresh machine.

New work-checklist (bash) / work_checklist (fish) is a side-effect-free helper that prints the work-only manual checklist:

$ work-checklist
Work machine — manual post-install checklist
…
  [ ] CloudMFA enrollment
        Open: https://aka.ms/CloudMFA
        Required for corporate SSO; resolves only on the work network/VPN.
  [ ] YubiKey: enroll for SSH + Git signing
        Run:  yk-enroll
…

yk-enroll's Done. footer now points users at work-checklist so it's discovered organically right after YubiKey enrollment finishes — no hard-coded URL exposed unless the user asks.

Verify

./tests/bash/run-tests.sh --test yk-enroll.bats --test work-checklist.bats

19 bats cases (8 new this PR):

  • warns about FIPS factory default PIN (under --check, no prompts)
  • --rotate-pin forces change-pin even when PIN is set
  • --rotate-pin under --check is a no-op
  • non-FIPS key with PIN set does NOT prompt for rotation
  • aborts when ssh-keygen exits 0 but no file was written (Ctrl+C regression)
  • work-checklist: prints CloudMFA URL
  • work-checklist: mentions yk-enroll
  • work-checklist: idempotent (no side effects, repeatable)

Files

  • home/dot_config/shell/functions/yk-enroll.sh--rotate-pin, FIPS warning, post-condition check, work-checklist hint
  • home/dot_config/fish/functions/yk_enroll.fish — same
  • home/dot_config/shell/functions/work-checklist.sh (new)
  • home/dot_config/fish/functions/work_checklist.fish (new)
  • tests/bash/yk-enroll.bats — 5 new tests
  • tests/bash/work-checklist.bats (new, 3 tests)
  • docs/yubikey.md — FIPS factory PIN section, post-condition note, work-checklist section + helpers-table entry

Two yk-enroll fixes from real macOS dogfooding:

1. Trust the filesystem, not exit codes.

   When the user pressed Ctrl+C at the FIDO2 PIN prompt during

   ssh-keygen enrollment, ssh-keygen returned a status that the

   wrapping function reported as success in fish's pipeline. Result:

   the wizard printed 'Enrolled: <path>' and 'Done. Next steps' even

   though no key file was ever written. Now both the bash and fish

   wizards stat <path> and <path>.pub after yk-ssh-new returns and

   abort with a clear error if either is missing. The Done summary

   block is also gated on the pubkey existing.

2. FIPS YubiKeys ship with factory PIN 123456.

   ykman fido info reports 'PIN is set' on a brand-new YubiKey 5

   FIPS, even though the PIN is the publicly documented default. The

   wizard now detects FIPS via the device type and warns explicitly:

     FIDO2 PIN is set — but this is a FIPS YubiKey, which ships with

     factory default PIN '123456'. If you haven't changed it yourself,

     rotate it now.

     Re-run with --rotate-pin to change it now.

   New --rotate-pin flag forces a change-pin call even when one is

   already set, so users can rotate the factory default without

   having to remember the raw ykman incantation.

Removed the half-baked interactive 'Change PIN now? [y/N]' prompt:

it deadlocked bats (stdin-is-a-tty) and added zero value over the

explicit --rotate-pin flag.

Tests: 16 bats cases (5 new): FIPS warning under --check, --rotate-pin

forces change, --rotate-pin under --check is a no-op, non-FIPS keys

are NOT prompted, and the Ctrl+C regression (ssh-keygen exits 0 but

no file written -> wizard aborts and never says 'Done').

Docs: docs/yubikey.md gained a 'FIPS YubiKeys ship with a factory

PIN' section and the post-condition guarantee in the step-5 bullet.
Some setup steps can't be automated by chezmoi: corporate URLs that

require the work network/VPN, browser-based MFA enrollment, per-user

sign-ins. Today these live in a wiki tab nobody remembers to open on

a fresh machine.

Add work-checklist (bash) and work_checklist (fish): a side-effect-

free helper that prints the work-only manual checklist. Includes

https://aka.ms/CloudMFA for corporate SSO MFA enrollment plus the

usual gh ssh-key add / gh auth login / az login reminders.

yk-enroll's Done. footer now points users at work-checklist so it's

discovered organically right after YubiKey enrollment finishes.

Tests: 3 bats cases (CloudMFA URL present, mentions yk-enroll,

idempotent / no side effects).

Docs: docs/yubikey.md gained an 'On work machines' section under

'Multiple YubiKeys' and a helpers-table entry.
@DevSecNinja DevSecNinja changed the title fix(yubikey): verify enrollment post-condition + FIPS factory PIN handling fix(yubikey): verify enrollment + FIPS PIN handling + work-checklist May 4, 2026
@DevSecNinja DevSecNinja marked this pull request as ready for review May 4, 2026 09:54
@DevSecNinja DevSecNinja enabled auto-merge (squash) May 4, 2026 09:54
@DevSecNinja DevSecNinja merged commit 8ae532c into main May 4, 2026
19 checks passed
@DevSecNinja DevSecNinja deleted the fix/yubikey-enroll-verify-and-fips branch May 4, 2026 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(yubikey): yk-enroll reports success when key file isn't written; doesn't warn about FIPS factory PIN

1 participant