<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://xml2rfcv3.xsd" type="application/relax-ng-compact-syntax"?>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>

<rfc category="std" docName="draft-bouchez-scram-mcf-01"
     ipr="trust200902" submissionType="IETF" consensus="yes"
     xml:lang="en" version="3">

  <front>
    <title abbrev="SCRAM-MCF">SCRAM with Modular Crypt Format (SCRAM-MCF)</title>

    <author fullname="Arnaud Bouchez" initials="A." surname="Bouchez">
      <organization>Tranquil IT SAS</organization>
      <address>
        <postal>
          <street>12 Avenue Jules Verne</street>
          <city>44230 Saint-Sebastien-sur-Loire</city>
          <country>France</country>
        </postal>
        <email>abouchez@tranquil.it</email>
	<uri>https://tranquil.it</uri>
      </address>
    </author>

    <date year="2025" month="November" day="23"/>

    <area>Security</area>
    <workgroup>KITTEN</workgroup>

    <keyword>SCRAM</keyword>
    <keyword>SASL</keyword>
    <keyword>MCF</keyword>
    <keyword>Argon2</keyword>
    <keyword>SCrypt</keyword>
    <keyword>bcrypt</keyword>

    <abstract>
      <t>This document specifies SCRAM-MCF, an extension to the Salted Challenge Response Authentication Mechanism (SCRAM) family of SASL mechanisms (<xref target="RFC5802"/>) and HTTP Digest extensions (<xref target="RFC7616"/>, <xref target="RFC7677"/>).</t>
      <t>The extension replaces the PBKDF2-specific iteration count attributes <tt>i=</tt> and <tt>s=</tt> in the server-first-message with a generic Modular Crypt Format (MCF) descriptor <tt>f=</tt>. This allows servers to use modern memory-hard key derivation functions such as Argon2, SCrypt, or bcrypt while preserving the full security properties and message flow of SCRAM.</t>
      <t>The change is fully backward compatible: servers can continue sending <tt>i=</tt> and <tt>s=</tt> for legacy clients and only send <tt>f=</tt> (or both) when the client advertises support.</t>
      <t>This document is intended to be discussed and potentially adopted by the KITTEN working group. Feedback from the KITTEN WG is welcome on the kitten@ietf.org mailing list.</t>
    </abstract>
  </front>

  <middle>

    <section anchor="introduction" numbered="true" toc="default">
      <name>Introduction</name>
      <t>SCRAM as defined in <xref target="RFC5802"/> and its SHA-256 variant in <xref target="RFC7677"/> is widely deployed (PostgreSQL, MongoDB, Kafka, SASL libraries, etc.). Its only key derivation function is PBKDF2-HMAC-SHA-1 or PBKDF2-HMAC-SHA-256. PBKDF2 is no longer considered state-of-the-art against GPU/ASIC-based password cracking.</t>

      <t>Modern password hashing algorithms (Argon2 – winner of the 2015 Password Hashing Competition, SCrypt, bcrypt) are memory-hard and far more resistant to parallel brute-force attacks. However, replacing SCRAM entirely with a new mechanism is unnecessary: the core proof-of-possession construction of SCRAM is excellent. Only the key derivation step needs to become negotiable.</t>

      <t>This document defines the smallest possible standards-compliant extension that achieves exactly that.</t>
    </section>

    <section anchor="conventions" numbered="true" toc="default">
      <name>Conventions and Terminology</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>

      <t>The term "Modular Crypt Format" (MCF) refers to the de-facto standard string format used by crypt(3), Passlib, Spring Security, and most modern password hashing libraries. Examples:</t>

      <artwork type="example"><![CDATA[
$argon2id$v=19$m=65536,t=2,p=4$z8e0jsE2kz7z6...$7KX4Wm6Q7f...
$scrypt$ln=16,r=8,p=1$z8e0jsE2kz7z6uL0m4zZ6Q$7KX4Wm6Q7...
$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe]]>
      </artwork>
    </section>

    <section anchor="extension" numbered="true" toc="default">
      <name>SCRAM-MCF Extension</name>

      <section anchor="client-capability" numbered="true" toc="default">
        <name>Client Capability Advertisement</name>
        <t>A client that implements SCRAM-MCF <bcp14>MUST</bcp14> include the attribute <tt>f=y</tt> in the reserved extension field of the client-first-message when using any SCRAM mechanism that supports this extension.</t>

        <t>Example (client-first-message):</t>
        <artwork type="example">
n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL,f=y
        </artwork>

        <t>Clients that do not send <tt>f=y</tt> MUST be treated exactly as in the original SCRAM algorithm (legacy clients). They MUST NOT support the <tt>f=</tt> attribute if they did not send <tt>f=y</tt> first.</t>
        
        <t>The <tt>f=</tt> attribute name - as in "<tt>f</tt>ormat" - was selected because <xref target="RFC5802"/> states that names are single US-ASCII letters, and that <tt>m=</tt> is already reserved.</t>
      </section>

      <section anchor="server-first-changes" numbered="true" toc="default">
        <name>Server-first-message Changes</name>
        <t>A server that receives <tt>f=y</tt> and wishes to use a modern KDF <bcp14>MUST</bcp14> respond with the attribute <tt>f=</tt> instead of <tt>i=</tt> and <tt>s=</tt>.</t>

        <t>The value of <tt>f=</tt> is the full MCF identifier string up to but not including the final stored hash part, encoded as base-64. In other words: everything up to and including the base64-encoded salt and its trailing <tt>$</tt> character (if any), then converted to base-64. The MCF identifier MUST be converted to base-64, to ensure no commas signs appear in the attribute value.</t>

        <t>Valid examples of MCF identifiers:</t>
        <artwork type="example">
$argon2id$v=19$m=65536,t=2,p=4$z8e0jsE2kz7z6uL0m4zZ6Q$
$scrypt$ln=16,r=8,p=1$z8e0jsE2kz7z6uL0m4zZ6Q$
$2a$06$m0CrhHm10qJ3lXRY.5zDGO
        </artwork>

        <t>Values transmitted as <tt>f=</tt> attribute, after base-64 encoding:</t>
        <artwork type="example">
f=JGFyZ29uMmlkJHY9MTkkbT02NTUzNix0PTIscD00JHo4ZTBqc0Uya3o3ejZ1...
f=JHNjcnlwdCRsbj0xNixyPTgscD0xJHo4ZTBqc0Uya3o3ejZ1TDBtNHpaNlEk
f=JDJhJDA2JG0wQ3JoSG0xMHFKM2xYUlkuNXpER08=
        </artwork>

        <t>Backward compatibility fallback: If the server cannot or does not want to use MCF, it simply omits <tt>f=</tt> and sends the normal <tt>i=</tt> and <tt>s=</tt> attributes.</t>
      </section>

      <section anchor="client-processing" numbered="true" toc="default">
        <name>Client Processing Rules</name>
          <ul spacing="normal">
            <li>If the server-first-message contains <tt>f=</tt>, the client <bcp14>MUST</bcp14> ignore any <tt>i=</tt> and <tt>s=</tt> attributes and <bcp14>MUST</bcp14> use the specified MCF string, after proper base-64 decoding, to derive SaltedPassword exactly as if it were calling the standard password-to-key function of that algorithm with the cleartext password and the MCF parameters/salt.</li>
            <li>The full encoded output of this MCF KDF, including its identifier, parameters, salt and checksum, <bcp14>MUST</bcp14> become the SaltedPassword as in <xref target="RFC5802"/> Section 3.</li>
            <li>The rest of the protocol (ClientKey, ServerKey, AuthMessage, ClientProof, etc.) is unchanged.</li>
            <li>The <tt>H()</tt> and <tt>HMAC()</tt> functions used to compute the client and server proofs <bcp14>MUST</bcp14> follow the SASL negotiation, e.g. SHA-256 and HMAC-SHA-256 for "SCRAM-SHA-256" or SHA-512 and HMAC-SHA-512 for "SCRAM-SHA-512".</li>
            <li>If the client does not recognize or support the MCF identifier, it <bcp14>MUST</bcp14> respond with a SASL/HTTP error (e.g., "invalid-parameters").</li>
          </ul>
      </section>

      <section anchor="algorithm-overview" numbered="true" toc="default">
        <name>SCRAM-MCF Algorithm Overview</name>
        <t>The following is a description of the algorithms used in a full, uncompressed SASL SCRAM-MCF authentication exchange.</t>

        <artwork type="code"><![CDATA[
// SCRAM-MCF password KDF
SaltedPassword = MCF(Password, identifier, parameters, salt)
// using MCF prefix identifier, parameters and salt
// e.g. "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2Kd..."

// initial server storage
ClientKey       := HMAC(SaltedPassword, "Client Key")
StoredKey       := H(ClientKey)
ServerKey       := HMAC(SaltedPassword, "Server Key")
persist the MCF prefix, StoredKey and ServerKey in the DB

// client
ClientKey       := HMAC(SaltedPassword, "Client Key")
ClientSignature := HMAC(StoredKey, AuthMessage)
return ClientProof := ClientKey XOR ClientSignature

// server
ClientSignature      := HMAC(StoredKey, AuthMessage)
CandidateClientKey   := ClientProof XOR ClientSignature
Checks: H(CandidateClientKey) == StoredKey
return ServerProof := HMAC(ServerKey, AuthMessage)

// client verifies
ServerSignature := ServerProof XOR ClientSignature
Checks: ServerSignature == HMAC(ServerKey, AuthMessage)
]]></artwork>

        <t>The rest of these messages is defined in <xref target="RFC5802"/> Section 7.</t>
      </section>

      <section anchor="storage" numbered="true" toc="default">
        <name>Server Storage Recommendation</name>
        <t>Servers <bcp14>MUST</bcp14> store the MCF prefix string (identifier + parameters + salt) for each user. For security reasons, the MCF checksum part <bcp14>MUST NOT</bcp14> be persisted; instead, the SCRAM-derived <tt>StoredKey</tt> and <tt>ServerKey</tt> <bcp14>MUST</bcp14> be stored.</t>

        <t>Servers <bcp14>MAY</bcp14> store and accept other SCRAM hashes (e.g., SCRAM-SHA-1 or SCRAM-SHA-256) for backward compatibility. But restricting to the safest algorithms (like SCRAM-MCF) is strongly recommended.</t>
      </section>
    </section>

    <section anchor="abnf" numbered="true" toc="default">
      <name>Formal ABNF Changes (augmented from RFC 5802)</name>

      <artwork type="abnf"><![CDATA[
server-first-message = ( scram-attr-val "," )* "r=" nonce
                       [ "," "s=" base64 ]
                       [ "," "i=" posint ]
                       [ "," "f=" mcf-base64 ]
                       *( "," scram-extension )

mcf-base64     = base64( mcf-descriptor )
mcf-descriptor = "$" mcf-id "$" mcf-params "$" base64-salt [ "$" ]
mcf-id         = "argon2i" / "argon2d" / "argon2id" /
                 "scrypt" / "2b" / other registered identifiers
]]></artwork>
    </section>

    <section anchor="security" numbered="true" toc="default">
      <name>Security Considerations</name>

    <section anchor="scram-proof" numbered="true" toc="default">
      <name>Preservation of the SCRAM Proof Construction</name>

      <t>In respect to the standard SCRAM mechanism, this SCRAM-MCF extension could be evaluated as such:</t>

      <ul spacing="normal">
          <li>The extension preserves channel binding, proof-of-possession, and mutual authentication exactly as in SCRAM.</li>
          <li>Memory-hard KDFs dramatically increase the cost of offline dictionary attacks.</li>
          <li>Because the KDF identifier and parameters are sent in the clear (as in standard SCRAM with <tt>i=</tt>), no new information is leaked to an eavesdropper.</li>
          <li>MCF algorithms <bcp14>MUST</bcp14> use a cryptographically random per-user salt.</li>
          <li>Clients and servers <bcp14>MUST</bcp14> reject weak MCF parameters (see "Minimum Acceptable" column in <xref target="kdf-levels"/>).</li>
          <li>Thanks to the MCF registration mechanism, this SCRAM-MCF pattern was designed to be future-proof.</li>
          <li>Weaker "SCRAM-SHA-1" <bcp14>MUST</bcp14> be rejected when used with the <tt>f=</tt> extension.</li>
      </ul>
    </section>
    
    <section title="Minimum and Recommended MCF Parameters Levels" anchor="kdf-levels">
    <t>MCF parameters levels are informed by NIST SP 800-63B <xref target="NIST.SP.800-63B"/> (preferring Argon2id with memory-hard properties) and OWASP guidelines <xref target="OWASP.PasswordStorage"/>.</t>     
      <t>Tune iteratively based on client load; aim for ~500ms-1s per verification to balance security and usability. Note that the server load is not affected by the MCF parameters, since during SCRAM authentication, the password derivation is done on the client side. For performance and Denial Of Service (DoS) mitigation, consider rate-limit derivations, e.g. testing with RFC 5802 <xref target="RFC5802"/> tools.</t>

    <table anchor="kdf-levels-table">
  <thead>
    <tr>
      <th align="left">KDF</th>
      <th align="left">Minimum Acceptable</th>
      <th align="left">Recommended (2025+)</th>
      <th align="left">Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td align="left">Argon2id (preferred)</td>
      <td align="left">Memory: 19 MiB<br/>t=1, p=1, m=19×1024</td>
      <td align="left">Memory: 64 MiB<br/>t=3, p=4, m=64×1024</td>
      <td align="left">Memory-hard; primary recommendation in NIST and OWASP. Salt &gt;= 16 bytes.</td>
    </tr>
    <tr>
      <td align="left">bcrypt</td>
      <td align="left">cost=10<br/>salt &gt;= 128 bits</td>
      <td align="left">cost=14–16<br/>salt &gt;= 192 bits</td>
      <td align="left">Still acceptable when Argon2 is unavailable. 72-byte password limit.</td>
    </tr>
    <tr>
      <td align="left">scrypt</td>
      <td align="left">N=2^17 (131072), r=8, p=1</td>
      <td align="left">N=2^20 (1M), r=8, p=4</td>
      <td align="left">Memory-hard; good alternative when Argon2 cannot be used.</td>
    </tr>
    <tr>
      <td align="left">PBKDF2 (FIPS-only fallback)<br/>(for plain SCRAM)</td>
      <td align="left">&gt;= 10 000 iterations<br/>HMAC-SHA-256, salt &gt;= 128 bits</td>
      <td align="left">&gt;= 600 000 iterations<br/>HMAC-SHA-256, salt &gt;= 256 bits</td>
      <td align="left">Approved by <xref target="NIST.SP.800-132"/> but vulnerable to GPU attacks; use only when FIPS compliance is required.</td>
    </tr>
    <tr>
      <td colspan="4" align="left">
      PBKDF2 KDF is listed only as reference, and makes little sense to appear as a MCF algorithm, since it is already used by the original SCRAM.
      </td>
    </tr>
  </tbody>
</table>
        
  </section>    
  
    <section anchor="mcf-hmac" numbered="true" toc="default">
      <name>Using MCF-Derived Outputs as HMAC Keys</name>
      
      <t>As defined above, <tt>ClientKey</tt> and <tt>ServerKey</tt> are computed using <tt>HMAC()</tt> on the MCF output. The length and structure of this value differ from PBKDF2, as used in classic SCRAM.</t>
      
      <t>HMAC constructions (including HMAC-SHA-256 and HMAC-SHA-512 refered by this document) are provably secure even when the supplied key is long or non-uniform.  Per Bellare, Canetti, and Krawczyk (1997; 2006), HMAC guarantees pseudorandomness provided that:</t>
      <ul spacing="normal">
        <li>keys longer than the hash function block size are reduced by hashing (as mandated by HMAC), and </li>
        <li>keys of arbitrary internal structure are permitted.</li>
      </ul>
      
      <t>Thus, MCF outputs — even if longer than a SHA-2 block — are acceptable and safe HMAC keys. Because memory-hard KDFs generate outputs indistinguishable from random to an attacker lacking the password, the resulting <tt>SaltedPassword</tt> is at least as strong as the PBKDF2-derived <tt>SaltedPassword</tt> in classic SCRAM.</t>

        <t>Therefore, replacing PBKDF2 output with memory-hard KDF output does not weaken the HMAC-based authentication proofs of SCRAM.</t>
      </section>

    </section>

    <section anchor="iana" numbered="true" toc="default">
      <name>IANA Considerations</name>
      <t>This document requests IANA registration of the SASL/GS2 extension attribute <tt>f=y</tt> and the server-first-message attribute <tt>f</tt>.</t>

      <t>No new SASL mechanism name ("SCRAM-MCF-*") needs to be registered. The existing names "SCRAM-SHA-256", "SCRAM-SHA-256-PLUS", "SCRAM-SHA-512", etc. continue to identify the underlying <tt>H()</tt> and <tt>HMAC()</tt> functions used for the proof calculation.</t>
    </section>

    <section anchor="scram-exchange" numbered="true" toc="default">
      <name>SCRAM Authentication Exchange</name>
      <t>This is a simple example of a SCRAM-SHA-256 authentication exchange when the client doesn't support channel bindings (username 'user' and password 'pencil' are used, with SCrypt MCF hashing):</t>
      <artwork type="example"><![CDATA[
C: n,,n=user,r=rOprNGfwEbeRWgbNEkqO,f=y
S: r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,f=
JHNjcnlwdCRsbj00LHI9OCxwPTEkUU54NE40NTRwcE1lS21Eanh5cmhzaDdRL1BZQlF3JA==
C: c=biws,r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,
   p=LyMcKMrzBJUoDhfO7e8aD0BYBLqe3wBrCoJMTIEhJEg=
S: v=2c7tBGYYY8tx/oLZNhZVJnjQKWeku17ZDaV0Jh3Hvmo=
]]></artwork>      
      <t>The corresponding MCF prefix string is "<tt>$scrypt$ln=4,r=8,p=1$QNx4N454ppMeKmDjxyrhsh7Q/PYBQw$</tt>", which is base-64 encoded in the <tt>f=</tt> attribute above.</t>
    </section>  

    <section anchor="acknowledgments" numbered="true" toc="default">
      <name>Acknowledgments</name>
      <t>The idea of using Modular Crypt Format inside a SCRAM-like flow was first implemented by the author in the Synopse mORMot 2 Framework in 2025 and standardized as the wire-level extension described in this document.</t>

      <t>The author would like to thank the PostgreSQL, MongoDB, and SASL communities for their prior art and feedback on modernizing password hashing in authentication protocols. A special thanks to Simon Josefsson and Thilo Molitor for their very valuable feedback to our initial proposal.</t>
    </section>
    
  </middle>

  <back>

    <references>
      <name>Normative References</name>

      <reference anchor="RFC2119" target="https://www.rfc-editor.org/rfc/rfc2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author initials="S." surname="Bradner" fullname="Scott Bradner">
            <organization>Harvard University</organization>
          </author>
          <date month="March" year="1997"/>
        </front>
      </reference>

      <reference anchor="RFC8174" target="https://www.rfc-editor.org/rfc/rfc8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author initials="B." surname="Leiba" fullname="Barry Leiba"/>
          <date month="May" year="2017"/>
        </front>
      </reference>

      <reference anchor="RFC5802" target="https://www.rfc-editor.org/rfc/rfc5802">
        <front>
          <title>Salted Challenge Response Authentication Mechanism (SCRAM) SASL and GSS-API Mechanisms</title>
          <author initials="C." surname="Newman" fullname="Chris Newman"/>
          <author initials="A." surname="Menon" fullname="Abhijit Menon"/>
          <author initials="J." surname="Hildebrand" fullname="John Hildebrand"/>
          <author initials="K." surname="Zeilenga" fullname="Kurt Zeilenga"/>
          <date month="July" year="2010"/>
        </front>
      </reference>

      <reference anchor="RFC7677" target="https://www.rfc-editor.org/rfc/rfc7677">
        <front>
          <title>SCRAM-SHA-256 and SCRAM-SHA-256-PLUS SASL Mechanisms</title>
          <author initials="T." surname="Hansen" fullname="Tony Hansen"/>
          <author initials="A." surname="Melnikov" fullname="Alexey Melnikov"/>
          <date month="November" year="2015"/>
        </front>
      </reference>

      <reference anchor="RFC7616" target="https://www.rfc-editor.org/rfc/rfc7616">
        <front>
          <title>HTTP Digest Access Authentication</title>
          <author initials="R." surname="Fielding" fullname="Roy T. Fielding"/>
          <author initials="J. F." surname="Reschke" fullname="Julian F. Reschke"/>
          <date month="September" year="2015"/>
        </front>
      </reference>

  <reference anchor="NIST.SP.800-132" target="https://doi.org/10.6028/NIST.SP.800-132">
    <front>
      <title>Recommendation for Password-Based Key Derivation: Part 1: Storage Applications</title>
      <author fullname="M. S. Turan" initials="M. S." surname="Turan">
        <organization>NIST</organization>
      </author>
      <author fullname="E. Barker" initials="E." surname="Barker">
        <organization>NIST</organization>
      </author>
      <author fullname="W. Burr" initials="W." surname="Burr">
        <organization>NIST</organization>
      </author>
      <author fullname="L. Chen" initials="L." surname="Chen">
        <organization>NIST</organization>
      </author>
      <date month="December" year="2010"/>
      <area>Security</area>
    </front>
    <seriesInfo name="NIST Special Publication" value="800-132"/>
  </reference>

  <reference anchor="NIST.SP.800-63B" target="https://doi.org/10.6028/NIST.SP.800-63b">
    <front>
      <title>Digital Identity Guidelines: Authentication and Lifecycle Management</title>
      <author fullname="M. L. Grassi" initials="M. L." surname="Grassi">
        <organization>NIST</organization>
      </author>
      <author fullname="M. E. Richer" initials="M. E." surname="Richer">
        <organization>NIST</organization>
      </author>
      <author fullname="S. P. Winters" initials="S. P." surname="Winters">
        <organization>NIST</organization>
      </author>
      <author fullname="K. B. Lefkovitz" initials="K. B." surname="Lefkovitz">
        <organization>NIST</organization>
      </author>
      <author fullname="J. M. Light" initials="J. M." surname="Light">
        <organization>NIST</organization>
      </author>
      <author fullname="W. E. Burr" initials="W. E." surname="Burr">
        <organization>NIST</organization>
      </author>
      <author fullname="S. Nadeau" initials="S." surname="Nadeau">
        <organization>NIST</organization>
      </author>
      <author fullname="M. A. Gruenberg" initials="M. A." surname="Gruenberg">
        <organization>NIST</organization>
      </author>
      <author fullname="D. A. McKay" initials="D. A." surname="McKay">
        <organization>NIST</organization>
      </author>
      <author fullname="J. A. Sigmon" initials="J. A." surname="Sigmon">
        <organization>NIST</organization>
      </author>
      <date month="June" year="2017"/>
      <area>Security</area>
    </front>
    <seriesInfo name="NIST Special Publication" value="800-63B"/>
  </reference>

  <reference anchor="OWASP.PasswordStorage" target="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html">
    <front>
      <title>Password Storage Cheat Sheet</title>
      <author fullname="OWASP Foundation" initials="OWASP" surname="Foundation"/>
      <date month="November" year="2025"/> <!-- Latest as of current date -->
      <area>Security</area>
    </front>
  </reference>

</references>
  </back>
</rfc>
