<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yusuf Mohammed</title>
    <description>The latest articles on DEV Community by Yusuf Mohammed (@ymohammed006).</description>
    <link>https://dev.to/ymohammed006</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4032692%2Fac5adf0e-dafd-4c77-b878-06b27e00c39c.png</url>
      <title>DEV Community: Yusuf Mohammed</title>
      <link>https://dev.to/ymohammed006</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ymohammed006"/>
    <language>en</language>
    <item>
      <title>Implementing FIDO's new passkey-export format — and the five spec bugs I found</title>
      <dc:creator>Yusuf Mohammed</dc:creator>
      <pubDate>Thu, 16 Jul 2026 19:34:40 +0000</pubDate>
      <link>https://dev.to/ymohammed006/implementing-fidos-new-passkey-export-format-and-the-five-spec-bugs-i-found-2d18</link>
      <guid>https://dev.to/ymohammed006/implementing-fidos-new-passkey-export-format-and-the-five-spec-bugs-i-found-2d18</guid>
      <description>&lt;p&gt;The FIDO Alliance recently published the Credential Exchange Format (CXF) — the first standard way to move passkeys, passwords, and TOTP secrets between credential managers. Apple ships it in iOS 26, Bitwarden was the first third-party manager to support it, and until now, exporting your vault meant a plaintext CSV. CXF is genuinely important infrastructure.&lt;/p&gt;

&lt;p&gt;There was no TypeScript implementation. So I built one: &lt;a href="https://github.com/ymohammed006/cxf-kit" rel="noopener noreferrer"&gt;cxf-kit&lt;/a&gt; — data models, parser, serializer, conformance validator, and a CLI, built against the Proposed Standard of 2025-08-14 with the spec's CDDL grammar vendored as the single source of truth, and interop-tested against Bitwarden's Rust implementation.&lt;br&gt;
Implementing a spec line-by-line is the deepest way to read it. Here's what I found.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The spec's own example contradicts its own grammar. Appendix A's passkey carries fido2Extensions.hmacSecret with an "HS256" algorithm — a structure and value that appear nowhere in the CDDL, which defines hmacCredentials with hmac-sha256. Real exporters copy examples, so my validator treats this shape as a warning rather than an error: a validator that fails the spec's own example would be useless against real-world exports.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The example breaks the spec's formatting rules twice more. It uses "CA" where subdivision-code requires the ISO 3166-2 form US-CA, and "WPA2" where the wifi enum says wpa2-personal.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A CDDL typo makes an enum into a map. WIFINetworkSecurityType is written with braces — { "unsecured" / ... } — which in CDDL means a map, though it's plainly meant as a string enum like every other enum in the spec.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. A grammar contradiction: an array that's simultaneously required-non-empty and defaulted-to-empty. CustomFields.extensions is declared [ + Extension ] .default [] — "one or more" with a default of none. My serializer had to make preservation the default and normalization opt-in, because the spec's own example wouldn't survive its own exporter rules.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The spec defines no packaging. File credentials carry an id, size, and integrity hash — but the spec never says where the bytes live in an export. Every implementation must invent its own convention (mine: a ZIP with index.json + documents/, documented as kit-defined, not spec).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All five are documented with evidence in the repo's &lt;a href="https://github.com/ymohammed006/cxf-kit/blob/main/SPEC_NOTES.md" rel="noopener noreferrer"&gt;SPEC_NOTES.md&lt;/a&gt;, and I'll be reporting them upstream.&lt;/p&gt;

&lt;p&gt;Some things I'm proud of in the implementation: a lossless round-trip guarantee (parse → serialize → parse is value-identical for any input, even nonconforming ones), hardened archive reading (decompression caps, path-traversal rejection, strict UTF-8 — silently corrupting a secret is worse than failing), and a CLI whose inspect command cannot print credential values — enforced by a test that greps the output of every mode for eleven planted secrets, on every CI run, on Linux and Windows.&lt;/p&gt;

&lt;p&gt;npm install cxf-kit&lt;br&gt;
npx cxf validate export.json&lt;/p&gt;

&lt;p&gt;It's MIT, on &lt;a href="https://github.com/ymohammed006/cxf-kit" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and v0.1.1 today. If you're implementing CXF — or you maintain a credential manager and want an independent validator for your exports — issues and interop reports are very welcome.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
