<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- Erzeugt nach dem gemeinsam erarbeiteten Inhaltsmodell (Stand Juli 2026). -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="bcp"
     docName="draft-rodenhaeuser-idna-transparent-resolution-00"
     ipr="trust200902"
     submissionType="IETF"
     tocInclude="true"
     sortRefs="true"
     symRefs="true"
     consensus="true"
     version="3">

  <front>
    <title abbrev="Transparent IDN Resolution">Transparent Handling of Internationalized Domain Names in Name Resolution APIs</title>
    <seriesInfo name="Internet-Draft" value="draft-rodenhaeuser-idna-transparent-resolution-00"/>

    <author fullname="Luca Rodenhäuser" asciiFullname="Luca Rodenhaeuser"
            initials="L." surname="Rodenhäuser" asciiSurname="Rodenhaeuser">
      <address>
        <postal>
          <street ascii="Lindenstrasse 11">Lindenstraße 11</street>
          <city>Gundernhausen</city>
          <code>64380</code>
          <country>Germany</country>
        </postal>
        <email>otzelot2021@outlook.de</email>
      </address>
    </author>

    <date/>

    <area>art</area>
    <keyword>IDNA</keyword>
    <keyword>IDN</keyword>
    <keyword>Unicode</keyword>
    <keyword>Punycode</keyword>
    <keyword>UTS 46</keyword>
    <keyword>getaddrinfo</keyword>
    <keyword>resolver</keyword>

    <abstract>
      <t>Applications are expected to convert internationalized domain names
      to their ASCII-Compatible Encoding (A-label) form before invoking name
      resolution APIs.  In practice this conversion is performed
      inconsistently: different applications follow different IDNA standards,
      use different libraries, and ship different versions of the Unicode
      mapping tables, so that the same input string can resolve to different
      registrable domain names depending on which software component performs
      the conversion.</t>
      <t>This document specifies that name resolution services accept Unicode
      host names by default and perform the conversion to A-labels
      internally, exactly once, at the point where a name is handed to a
      specific resolution protocol.  The DNS wire format is unchanged: only
      A-labels appear in queries to the public DNS.  The conversion procedure
      is Unicode IDNA Compatibility Processing (UTS #46), nontransitional,
      with a mapping-table floor of Unicode 15.1.  This codifies the
      architectural recommendation of RFC 6055 and the deployed practice of
      several major platforms.</t>
    </abstract>

    <note removeInRFC="true">
      <name>Discussion Venues</name>
      <t>Discussion of this document is encouraged on the IETF DISPATCH
      working group mailing list (dispatch@ietf.org); DNS-specific
      aspects may also be raised on the DNSOP working group list
      (dnsop@ietf.org).  Comments may also be sent directly to the
      author.</t>
    </note>
  </front>

  <middle>

    <section anchor="introduction">
      <name>Introduction</name>
      <t>The Domain Name System carries internationalized labels in an
      ASCII-Compatible Encoding: U-labels are converted to A-labels
      <xref target="RFC5890"/> before they appear in DNS queries.  IDNA
      deliberately placed this conversion inside applications so that
      existing APIs and servers could remain unchanged
      <xref target="RFC3490"/>.  Fifteen years of deployment experience show
      the cost of that choice: every application converts for itself, and no
      two convert alike.</t>
      <t>The resulting divergence is observable on three levels.  On the
      standards level, widely used runtime facilities still implement
      IDNA2003 (for example the java.net.IDN class and Python's built-in
      "idna" codec) while other components implement IDNA2008 with UTS #46
      mapping <xref target="UTS46"/>.  On the library level, a single
      portable program may use a different conversion backend on every
      platform it supports.  On the table-version level, even components that
      agree on UTS #46 nontransitional processing disagree when their copies
      of the Unicode mapping table differ in age: at the time of writing, the
      input "STRAẞE.de" is converted to "strasse.de" by implementations
      shipping tables older than Unicode 15.1 and to "xn--strae-oqa.de" by
      implementations with current tables -- two independently registrable
      domain names from one input string, on one host, depending on which
      library is asked.  The divergence even crosses layers within a single
      runtime and a single vendor; <xref target="survey"/> records the
      observed state of common implementations.</t>
      <t>The consequences are not merely cosmetic.  When a security filter
      canonicalizes a name differently from the resolver that later looks it
      up, the filter examines one domain and the network connects to another.
      When two applications on the same system convert differently, the same
      user input reaches different destinations.</t>
      <t>This document specifies the remedy that the IAB recommended in 2011:
      <xref target="RFC6055"/> concludes that it is inappropriate for
      applications calling general-purpose name resolution APIs to convert
      names to A-labels themselves, and that the conversion should instead be
      performed by the entity that knows which resolution protocol will be
      used -- the resolver, at the moment it decides to hand the name to the
      DNS.  The candidate mappings at the time included the local mapping of
      <xref target="RFC5895"/> and both modes of UTS #46, and no single
      choice could yet be recommended.  The original IDNA specification
      anticipated the same evolution,
      expecting that future resolver libraries would accept domain names in
      non-ASCII form and perform the ToASCII operation internally
      <xref target="RFC3490"/>.  What RFC 6055 could not settle at the time --
      which of the competing mappings the resolver should apply -- has since
      been settled elsewhere: Unicode deprecated transitional processing,
      declared the industry transition to IDNA2008 behavior complete, and in
      Unicode 15.1 aligned the mapping of capital sharp s with
      nontransitional expectations <xref target="UTS46"/>.</t>
      <t>Accordingly, this document requires that name resolution services
      accept Unicode input by default, without any opt-in flag or attribute;
      that they convert it with a single, versioned procedure
      (<xref target="conversion-procedure"/>); that the conversion happens
      exactly once, at the protocol boundary
      (<xref target="architecture-late"/>); and that nothing changes on the
      wire (<xref target="architecture-wire"/>).</t>

      <section anchor="requirements-language">
        <name>Requirements Language</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&#160;14 <xref target="RFC2119"/>
        <xref target="RFC8174"/> when, and only when, they appear in all
        capitals, as shown here.</t>
      </section>
    </section>

    <section anchor="terminology">
      <name>Terminology</name>
      <dl newline="true">
        <dt>Name resolution service</dt>
        <dd>Any interface that accepts a host name as a character or byte
        string and resolves it using one or more name resolution protocols,
        of which the DNS is typically one.  This includes C library stub
        resolver entry points such as getaddrinfo() <xref target="RFC3493"/>,
        operating system name
        resolution services, resolvers embedded in language runtimes, and
        high-level lookup functions of DNS libraries.  It does not include
        interfaces that accept names already in DNS wire format
        (<xref target="scope"/>).</dd>
        <dt>Conversion point</dt>
        <dd>The place within a name resolution service at which a name is
        transformed into the encoding required by one specific resolution
        protocol.</dd>
        <dt>Table version</dt>
        <dd>The version of the Unicode IdnaMappingTable (and associated
        derived data) from which an implementation's UTS #46 processing is
        generated.</dd>
        <dt>U-label, A-label</dt>
        <dd>As defined in <xref target="RFC5890"/>; A-labels carry a
        Punycode-encoded <xref target="RFC3492"/> form of the label.</dd>
      </dl>
    </section>

    <section anchor="scope">
      <name>Scope and Non-Goals</name>
      <t>This document applies to name resolution services as defined above:
      entry points that accept host names as text.  Interfaces that operate
      on names already in DNS wire format (for example res_mkquery()-level
      APIs) are out of scope; callers of such interfaces have already chosen
      an encoding.</t>
      <t>This document does not change the DNS wire format, and it
      deliberately does not define any negotiation mechanism for carrying
      Unicode names on the wire; the obstacles to such a mechanism, DNSSEC
      canonicalization first among them
      (<xref target="architecture-wire"/>), are outside its scope.  It does
      not constrain registry or registration policy (for which see
      <xref target="RFC5891"/>), does not specify the display direction
      (conversion of A-labels to U-labels for presentation), does not modify
      URL or IRI processing (see <xref target="WHATWG-URL"/>), and does not
      address internationalized email.</t>
      <t>The requirement keywords of this document define conformance to
      the practice it specifies.  They impose no obligation on
      implementations that do not claim conformance, and they render no
      existing implementation invalid with respect to any other
      specification; in particular, conformance to this document is
      orthogonal to conformance to interface standards such as
      POSIX.</t>
    </section>

    <section anchor="architecture">
      <name>Architecture</name>

      <section anchor="architecture-behavior">
        <name>Behavioral Requirements, Not API Signatures</name>
        <t>This document states requirements on the observable behavior of
        name resolution services.  It does not define function signatures,
        flag constants, or other language- or platform-specific interface
        details, which belong to the respective interface specifications
        (for POSIX, the Austin Group).  <xref target="survey"/> maps the
        requirements onto existing interfaces informatively.</t>
      </section>

      <section anchor="architecture-wire">
        <name>The Wire Format Remains A-Labels</name>
        <t>Queries sent to the public DNS carry A-labels, exactly as today.
        Several properties of the deployed DNS depend on names being ASCII
        at the protocol layer: the DNSSEC canonical form is defined in terms
        of ASCII case folding only <xref target="RFC4034"/>; caches,
        case-randomizing resolvers, and middleboxes compare and copy names
        under the same assumption; and the entire registration ecosystem
        provisions A-labels.  While the DNS protocol itself places no
        restriction on the octets in a label <xref target="RFC2181"/>, and
        UTF-8 labels do occur in private namespaces
        (<xref target="private-namespaces"/>), changing the encoding used in
        the public tree is a separate and much larger problem than the one
        this document solves.</t>
      </section>

      <section anchor="conversion-procedure">
        <name>A Single Conversion Procedure</name>
        <t>Implementations <bcp14>MUST</bcp14> convert names using Unicode
        IDNA Compatibility Processing <xref target="UTS46"/>, conforming to
        conformance clause C2 (nontransitional processing), with the ToASCII
        operation parameterized as follows:</t>
        <table anchor="profile">
          <name>UTS #46 ToASCII Profile</name>
          <thead>
            <tr><th>Parameter</th><th>Value</th></tr>
          </thead>
          <tbody>
            <tr><td>UseSTD3ASCIIRules</td><td>false</td></tr>
            <tr><td>CheckHyphens</td><td>false</td></tr>
            <tr><td>CheckBidi</td><td>true</td></tr>
            <tr><td>CheckJoiners</td><td>true</td></tr>
            <tr><td>Transitional_Processing</td><td>false</td></tr>
            <tr><td>VerifyDnsLength</td><td>false (see <xref target="length-limits"/>)</td></tr>
            <tr><td>IgnoreInvalidPunycode</td><td>false</td></tr>
          </tbody>
        </table>
        <t>Transitional processing (conformance clause C1) is deprecated by
        Unicode and <bcp14>MUST NOT</bcp14> be used, in any mode, including
        as a fallback for input that fails nontransitional processing.</t>
        <t>UseSTD3ASCIIRules is false because names containing underscores,
        such as service and policy labels of the form "_sip._tcp", must
        remain resolvable.  CheckHyphens is false because labels such as
        those beginning with "r3---" occur in deployed DNS content and must
        remain resolvable.  CheckBidi preserves conformance with the Bidi
        rule <xref target="RFC5893"/>, and CheckJoiners preserves the
        contextual rules for joiner characters.  This parameter set is
        identical to the one used by the WHATWG URL Standard's
        domain-to-ASCII operation <xref target="WHATWG-URL"/>; a resolver
        conforming to this document therefore derives the same A-labels as
        the browsers running above it.</t>
        <t>Callers are not required to normalize their input: UTS #46
        processing itself maps and normalizes to NFC, so input in NFD or
        mixed normalization forms is acceptable.</t>

        <section anchor="unicode-floor">
          <name>Table Version</name>
          <t>Implementations <bcp14>MUST</bcp14> use mapping and validity
          data derived from Unicode version 15.1 or later, and
          <bcp14>SHOULD</bcp14> track the current Unicode version, following
          the review process established for IDNA in
          <xref target="RFC8753"/>.</t>
          <t>The floor of 15.1 is not arbitrary.  Unicode 15.1 is the version
          in which, as an explicit exception to the otherwise-guaranteed
          backward compatibility of the mapping table, the mapping of U+1E9E
          (LATIN CAPITAL LETTER SHARP S, "ẞ") was changed from "ss" to
          U+00DF (LATIN SMALL LETTER SHARP S, "ß"), which nontransitional
          processing treats as valid <xref target="UTS46"/>.  Under older
          tables, the uppercase and lowercase spellings of the same word
          convert to two different registrable domain names
          (<xref target="security-skew"/>).  A floor below 15.1 would
          perpetuate exactly the divergence this document exists to
          remove.</t>
        </section>
      </section>

      <section anchor="architecture-late">
        <name>Late Conversion</name>
        <t>Conversion happens at the conversion point of each resolution
        protocol, not at the API boundary.  Name resolution services are
        protocol-independent: the same call may be satisfied by the DNS, by
        Multicast DNS <xref target="RFC6762"/>, by LLMNR
        <xref target="RFC4795"/>, by a hosts file, or by other mechanisms,
        and these protocols do not share an encoding.  Multicast DNS, for
        example, uses UTF-8 on the wire.  A name converted to A-labels at
        the API boundary would therefore be wrong for some backends; a name
        converted at each protocol boundary is right for all of them.  This
        is the architecture recommended by <xref target="RFC6055"/> and
        implemented, for example, by systemd-resolved, which prepares both
        an IDNA form and a UTF-8 form of each question and lets the backend
        select the appropriate one.</t>
      </section>
    </section>

    <section anchor="processing">
      <name>Processing Requirements</name>

      <section anchor="ascii-fastpath">
        <name>ASCII Fast Path</name>
        <t>If the input consists entirely of ASCII characters -- including
        input that already contains A-labels -- the service
        <bcp14>MUST NOT</bcp14> apply any IDNA processing to it.  Behavior
        for such input remains octet-for-octet identical to the behavior of
        a service not implementing this document.</t>
        <t>This rule makes the conversion idempotent and protects the two
        largest classes of existing callers: applications that only ever
        resolve ASCII names, and applications that perform their own
        conversion and pass A-labels.  Neither can observe any change.  It
        also preserves the ability to resolve ASCII labels that merely
        resemble A-labels: names beginning with "xn--" are passed through
        without validation or re-mapping, as they are today.</t>
      </section>

      <section anchor="byte-interfaces">
        <name>Byte-Oriented Interfaces</name>
        <t>For interfaces that accept names as byte strings: if the input
        contains at least one non-ASCII octet and is valid UTF-8, the
        service <bcp14>MUST</bcp14> process it as described in
        <xref target="conversion"/>.  UTF-8 validity is as defined in
        <xref target="RFC3629"/>, which excludes surrogates and overlong
        forms.  If the input contains non-ASCII octets
        but is not valid UTF-8, the service <bcp14>SHOULD</bcp14> pass it to
        the resolution protocol unchanged, preserving the historical
        eight-bit transparency of the DNS <xref target="RFC2181"/>; it
        <bcp14>MAY</bcp14> instead provide a configuration under which such
        input is rejected with an error (<xref target="errors"/>).</t>
      </section>

      <section anchor="unicode-interfaces">
        <name>Unicode-Native Interfaces</name>
        <t>For interfaces that accept names as Unicode strings (for example
        UTF-16 string types), any input containing non-ASCII characters
        <bcp14>MUST</bcp14> be processed as described in
        <xref target="conversion"/>.  No byte-level heuristic is needed or
        permitted.</t>
      </section>

      <section anchor="conversion">
        <name>Conversion</name>
        <t>Input selected by <xref target="byte-interfaces"/> or
        <xref target="unicode-interfaces"/> <bcp14>MUST</bcp14> be converted
        by applying the ToASCII operation with the profile of
        <xref target="conversion-procedure"/> to the whole domain name.
        The mapping step of UTS #46 itself handles the ideographic and
        fullwidth label separators (U+3002, U+FF0E, U+FF61), so no separate
        pre-processing of dots is required.  The conversion is performed
        exactly once, at the conversion point of the protocol that will
        carry the query (<xref target="architecture-late"/>).</t>
      </section>

      <section anchor="length-limits">
        <name>Length Limits and Root-Label Semantics</name>
        <t>After conversion, the service <bcp14>MUST</bcp14> verify the DNS
        length limits on the converted form: at most 63 octets per label
        and at most 255 octets for the name in wire format
        <xref target="RFC1035"/>.  A single trailing dot denotes the root
        label and <bcp14>MUST</bcp14> retain its conventional meaning of
        marking the name fully qualified and suppressing search-list
        processing.  This is why the profile in
        <xref target="conversion-procedure"/> sets VerifyDnsLength to false:
        with that flag enabled, UTS #46 would reject the empty root label,
        whereas with it disabled the empty root label passes through and the
        service applies its own checks with the correct semantics.  Interior
        empty labels are invalid and <bcp14>MUST</bcp14> be rejected; only
        the single trailing empty label denoting the root is permitted.
        Where search-list expansion applies
        (<xref target="search-lists"/>), the limits are verified for each
        candidate name actually queried.</t>
      </section>

      <section anchor="search-lists">
        <name>Search Lists</name>
        <t>The service <bcp14>MUST</bcp14> convert the caller-supplied name
        before performing search-list expansion.  Configured search domains
        may themselves contain non-ASCII characters; they
        <bcp14>MUST</bcp14> be converted with the same procedure when the
        configuration is loaded, so that expansion concatenates A-label
        forms -- except where a search domain belongs to a private namespace
        configured as described in <xref target="private-namespaces"/>, in
        which case the form appropriate to that namespace is used.  Note
        that <xref target="RFC6055"/> documents deployments in which suffix
        search lists contain UTF-8.</t>
      </section>

      <section anchor="fail-closed">
        <name>Failure Handling</name>
        <t>If mapping or validation of input on the IDNA path fails, the
        service <bcp14>MUST</bcp14> report an error that is distinguishable
        from a resolution failure such as "name not found"
        (<xref target="errors"/>).  Input that was recognized as Unicode
        <bcp14>MUST NOT</bcp14> be sent to the public DNS in unconverted
        form, and partial conversions <bcp14>MUST NOT</bcp14> be used: a
        name is converted completely or the call fails.  The pass-through
        behavior of <xref target="byte-interfaces"/> applies exclusively to
        input that is not valid UTF-8.</t>
      </section>

      <section anchor="default-on">
        <name>Default Activation and Opt-Out</name>
        <t>Acceptance and conversion of Unicode input <bcp14>MUST</bcp14> be
        the default behavior of the service and <bcp14>MUST NOT</bcp14>
        require any per-call flag, option, attribute, or prior
        configuration.</t>
        <t>Implementations <bcp14>MUST</bcp14> provide a mechanism to
        disable the conversion -- per call, per process, or per system -- for
        compatibility and diagnostic purposes.  An existing example of such
        a mechanism is the AI_DISABLE_IDN_ENCODING flag of the Windows
        getaddrinfo() family.</t>
      </section>

      <section anchor="alabel-visibility">
        <name>Access to the Converted Form</name>
        <t>The service <bcp14>SHOULD</bcp14> make the converted (A-label)
        form of the queried name available to the caller, for example
        through the mechanism used to return canonical names or through
        another interface-specific channel where that mechanism already
        carries DNS-derived names.  Protocol
        elements above the resolver -- TLS Server Name Indication
        <xref target="RFC6066"/>, HTTP Host headers, and certificate
        identity verification <xref target="RFC9525"/> -- operate on
        A-labels; a caller that only holds the U-label form is forced to
        repeat the conversion itself, reintroducing the very divergence
        this document removes.</t>
        <t>Names returned by the DNS (for example CNAME chains and PTR
        targets) remain in A-label form.  Conversion of results to U-labels
        for display <bcp14>MUST</bcp14> be available only on explicit
        request of the caller; presentation of internationalized names, and
        its associated spoofing concerns, are outside the scope of this
        document.</t>
      </section>
    </section>

    <section anchor="non-dns">
      <name>Non-DNS Name Services and Private Namespaces</name>

      <section anchor="mdns-llmnr">
        <name>Multicast DNS and LLMNR</name>
        <t>Names sent over Multicast DNS <bcp14>MUST</bcp14> be carried in
        the UTF-8 form specified by <xref target="RFC6762"/>, not as
        A-labels.  The same applies to LLMNR <xref target="RFC4795"/>.  The
        conversion point for these protocols therefore performs no ToASCII
        operation; the late-conversion architecture of
        <xref target="architecture-late"/> is what makes this correct.</t>
      </section>

      <section anchor="hosts-file">
        <name>Hosts File</name>
        <t>Entries in a hosts file may be written as U-labels or as
        A-labels.  When matching a looked-up name against hosts file
        entries, the service <bcp14>SHOULD</bcp14> apply the conversion
        procedure of <xref target="conversion-procedure"/> to both sides
        and compare the results, so that either spelling of an entry
        matches either spelling of a query.  If conversion of an entry or of
        the queried name fails, that side is matched by direct comparison
        of its UTF-8 form.</t>
      </section>

      <section anchor="private-namespaces">
        <name>Private DNS Namespaces Using UTF-8</name>
        <t><xref target="RFC6055"/> documents a long-established practice of
        provisioning UTF-8 names in private DNS namespaces, particularly in
        enterprise environments, and recommends that resolvers be liberal
        enough to reach names in such namespaces.  This document
        accommodates that practice without weakening the public case:
        queries sent to the public DNS <bcp14>MUST</bcp14> carry A-labels;
        for zones or network scopes that are explicitly configured as
        private UTF-8 namespaces, an implementation <bcp14>MAY</bcp14> send
        the UTF-8 form of a name in addition to, or instead of, the A-label
        form.  Such behavior <bcp14>MUST</bcp14> be bound to the configured
        scope and <bcp14>MUST NOT</bcp14> be a global default.  Note that DNS servers
        do not case-fold non-ASCII octets <xref target="RFC4343"/>; names
        in such namespaces match bit-for-bit, and provisioning
        conventions need to account for this.</t>
      </section>
    </section>

    <section anchor="errors">
      <name>Error Reporting</name>
      <t>Services distinguish at least the following failure classes on the
      IDNA path: mapping failures (input containing disallowed code
      points), validation failures (violations of the Bidi rule, the
      joiner context rules, or Punycode validity inside a mixed name),
      length failures (<xref target="length-limits"/>), and -- where the
      strict mode of <xref target="byte-interfaces"/> is enabled -- invalid
      UTF-8.</t>
      <t>Errors of these classes <bcp14>MUST</bcp14> be reported through a
      code or condition distinct from resolution failures, so that callers
      can tell "this name cannot be encoded" apart from "this name does not
      exist".  An existing example is the EAI_IDN_ENCODE error of the GNU C
      library.  Diagnostics <bcp14>SHOULD</bcp14> identify the offending
      label and, where possible, the offending code point position.</t>
    </section>

    <section anchor="migration">
      <name>Migration and Backward Compatibility</name>
      <t>Existing callers fall into three classes.  Applications that only
      resolve ASCII names are untouched by construction
      (<xref target="ascii-fastpath"/>).  Applications that perform their
      own IDNA conversion hand ASCII to the service and are equally
      untouched; no double conversion can occur, since Punycode input is
      never re-mapped.  Applications that deliberately pass raw non-ASCII
      octets -- a small class, chiefly in private-namespace environments --
      are served by the UTF-8 pass-through of
      <xref target="byte-interfaces"/>, by
      <xref target="private-namespaces"/>, and by the opt-out of
      <xref target="default-on"/>.</t>
      <t>Applications need not change to benefit, and need not wait to be
      safe: an application that continues to convert names itself remains
      correct indefinitely, because its A-label output takes the ASCII
      fast path unchanged (<xref target="ascii-fastpath"/>).  Until an
      application can rely on the services it uses conforming to this
      document, continuing to pre-convert is the prudent choice; the aim
      of this document is to make that burden unnecessary, not to forbid
      carrying it.</t>
      <t>Default-on conversion is not an experiment.  The Windows resolver
      has converted by default since Windows 8 with an opt-out flag, across
      more than a decade of deployment, without ecosystem breakage -- even
      though, as <xref target="survey"/> records, the procedure behind that
      default is today the part most in need of the present specification.
      The musl C library, which currently performs no IDN conversion,
      states as project policy that support, when added, will always be
      enabled rather than requiring application flags; this document
      supplies the specification such an implementation needs.</t>
      <t>For implementations, the migration is incremental: a libc that
      today offers opt-in conversion makes that behavior the default,
      turns the opt-in flag into a no-op, adds an opt-out, and updates its
      mapping tables to meet the floor of <xref target="unicode-floor"/>;
      a runtime whose HTTP layer already converts extends the same
      procedure to its socket-level lookups.  Interface-level details for
      POSIX getaddrinfo() are a matter for the Austin Group and are
      sketched informatively in <xref target="survey"/>.</t>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>

      <section anchor="security-skew">
        <name>Table-Version Skew</name>
        <t>Until the floor of <xref target="unicode-floor"/> is universally
        met, implementations with pre-15.1 tables convert "STRAẞE.de" to
        "strasse.de" while implementations with current tables convert it
        to "xn--strae-oqa.de".  These are independently registrable
        domains: the operator of the .de registry admitted the letter "ß"
        on 16 November 2010 after a one-time sunrise phase for holders of
        the corresponding "ss" domains, and applies its ordinary
        first-come-first-served rules since -- there is no bundling
        requirement, and the registry itself noted at introduction time
        that software following the older standard would lead users
        entering "ß" to the "ss" domain, which need not belong to the same
        holder <xref target="DENIC2010"/>.  An attacker who controls the
        name produced by the older tables receives the traffic of every
        client on the wrong side of the skew.  The table-version floor
        exists to shrink this window; until it closes, operators of names
        containing deviation-adjacent characters should consider holding
        both spellings.</t>
      </section>

      <section anchor="security-components">
        <name>Divergence between Components</name>
        <t>Security decisions that compare domain names -- allowlists,
        blocklists, SSRF protections, pinning, access control -- are only
        sound if the comparing component and the resolving component
        canonicalize identically.  Such comparisons <bcp14>SHOULD</bcp14>
        be performed on the A-label form produced by the procedure of
        <xref target="conversion-procedure"/>;
        <xref target="alabel-visibility"/> exists to make that form
        available.  Logs <bcp14>SHOULD</bcp14> record both the input form
        and the converted form of resolved names.</t>
      </section>

      <section anchor="security-residual">
        <name>Residual Asymmetries</name>
        <t>The conversion is deliberately context-free, and some case
        asymmetries therefore remain: the Greek capital sigma always maps
        to U+03C3, while a final lowercase sigma (U+03C2) is valid as
        written, so the uppercase and lowercase spellings of a Greek word
        ending in sigma still convert to different labels.  This document
        does not and cannot repair that; it only guarantees that every
        component disagrees in the same way.  Visual confusability between
        distinct code points (homoglyphs) is likewise out of scope; see
        UTS #39 <xref target="UTS39"/> and the registry-side
        recommendations of <xref target="RFC5891"/>.</t>
      </section>

      <section anchor="security-surface">
        <name>Changed Attack Surface of Default Activation</name>
        <t>Applications that implicitly relied on non-ASCII input never
        resolving -- using the resolver's previous behavior as an accidental
        input filter -- lose that property under this document.  Such
        applications should validate input explicitly and may use the
        opt-out of <xref target="default-on"/> during transition.</t>
      </section>

      <section anchor="security-wire">
        <name>No New Wire Exposure</name>
        <t>Because the wire format is unchanged
        (<xref target="architecture-wire"/>), this document introduces no
        new interactions with DNSSEC validation, caching, or on-path
        devices.</t>
      </section>

      <section anchor="security-passthrough">
        <name>Pass-Through of Non-UTF-8 Input</name>
        <t>The pass-through behavior of <xref target="byte-interfaces"/>
        preserves compatibility with eight-bit legacy deployments, but it
        is itself a canonicalization boundary: a component that leniently
        decodes malformed input as Unicode will canonicalize a byte
        sequence that the resolver forwards untouched, recreating the
        divergence of <xref target="security-components"/> at the
        encoding layer.  Deployments in security-sensitive contexts
        <bcp14>SHOULD</bcp14> enable the strict rejection mode of
        <xref target="byte-interfaces"/>, and comparing components
        <bcp14>SHOULD NOT</bcp14> apply lenient decoding to input that
        the resolver treats as opaque bytes.</t>
      </section>

      <section anchor="security-preconversion">
        <name>Application-Side Pre-Conversion</name>
        <t>The status quo is itself a documented vulnerability:
        <xref target="RFC6055"/> observes that applications converting to
        A-labels before calling protocol-independent resolution APIs can be
        directed to attacker-controlled destinations wherever a namespace
        uses a different encoding, because the attacker can register the
        A-label spelling of a name whose canonical form in that namespace
        is UTF-8.  By moving conversion to the protocol-aware conversion
        point, this document removes the incentive and the need for
        application-side pre-conversion, and with it this class of
        attack.</t>
      </section>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.  In particular, it deliberately
      does not define an EDNS(0) option or any other protocol element for
      negotiating name encodings on the wire.</t>
    </section>

  </middle>

  <back>

    <references>
      <name>References</name>

      <references anchor="normative">
        <name>Normative References</name>

        <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author initials="S." surname="Bradner"/>
            <date year="1997" month="March"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>

        <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author initials="B." surname="Leiba"/>
            <date year="2017" month="May"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>

        <reference anchor="RFC1035" target="https://www.rfc-editor.org/info/rfc1035">
          <front>
            <title>Domain names - implementation and specification</title>
            <author initials="P." surname="Mockapetris"/>
            <date year="1987" month="November"/>
          </front>
          <seriesInfo name="STD" value="13"/>
          <seriesInfo name="RFC" value="1035"/>
          <seriesInfo name="DOI" value="10.17487/RFC1035"/>
        </reference>

        <reference anchor="RFC3629" target="https://www.rfc-editor.org/info/rfc3629">
          <front>
            <title>UTF-8, a transformation format of ISO 10646</title>
            <author initials="F." surname="Yergeau"/>
            <date year="2003" month="November"/>
          </front>
          <seriesInfo name="STD" value="63"/>
          <seriesInfo name="RFC" value="3629"/>
          <seriesInfo name="DOI" value="10.17487/RFC3629"/>
        </reference>

        <reference anchor="RFC5890" target="https://www.rfc-editor.org/info/rfc5890">
          <front>
            <title>Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework</title>
            <author initials="J." surname="Klensin"/>
            <date year="2010" month="August"/>
          </front>
          <seriesInfo name="RFC" value="5890"/>
          <seriesInfo name="DOI" value="10.17487/RFC5890"/>
        </reference>

        <reference anchor="RFC5891" target="https://www.rfc-editor.org/info/rfc5891">
          <front>
            <title>Internationalized Domain Names in Applications (IDNA): Protocol</title>
            <author initials="J." surname="Klensin"/>
            <date year="2010" month="August"/>
          </front>
          <seriesInfo name="RFC" value="5891"/>
          <seriesInfo name="DOI" value="10.17487/RFC5891"/>
        </reference>

        <reference anchor="UTS46" target="https://www.unicode.org/reports/tr46/">
          <front>
            <title>Unicode IDNA Compatibility Processing</title>
            <author>
              <organization>The Unicode Consortium</organization>
            </author>
            <date year="2025" month="September"/>
          </front>
          <refcontent>Unicode Technical Standard #46, Revision 35</refcontent>
        </reference>

      </references>

      <references anchor="informative">
        <name>Informative References</name>

        <reference anchor="RFC2181" target="https://www.rfc-editor.org/info/rfc2181">
          <front>
            <title>Clarifications to the DNS Specification</title>
            <author initials="R." surname="Elz"/>
            <author initials="R." surname="Bush"/>
            <date year="1997" month="July"/>
          </front>
          <seriesInfo name="RFC" value="2181"/>
          <seriesInfo name="DOI" value="10.17487/RFC2181"/>
        </reference>

        <reference anchor="RFC3490" target="https://www.rfc-editor.org/info/rfc3490">
          <front>
            <title>Internationalizing Domain Names in Applications (IDNA)</title>
            <author initials="P." surname="Faltstrom"/>
            <author initials="P." surname="Hoffman"/>
            <author initials="A." surname="Costello"/>
            <date year="2003" month="March"/>
          </front>
          <seriesInfo name="RFC" value="3490"/>
          <seriesInfo name="DOI" value="10.17487/RFC3490"/>
        </reference>

        <reference anchor="RFC3492" target="https://www.rfc-editor.org/info/rfc3492">
          <front>
            <title>Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)</title>
            <author initials="A." surname="Costello"/>
            <date year="2003" month="March"/>
          </front>
          <seriesInfo name="RFC" value="3492"/>
          <seriesInfo name="DOI" value="10.17487/RFC3492"/>
        </reference>

        <reference anchor="RFC3493" target="https://www.rfc-editor.org/info/rfc3493">
          <front>
            <title>Basic Socket Interface Extensions for IPv6</title>
            <author initials="R." surname="Gilligan"/>
            <author initials="S." surname="Thomson"/>
            <author initials="J." surname="Bound"/>
            <author initials="J." surname="McCann"/>
            <author initials="W." surname="Stevens"/>
            <date year="2003" month="February"/>
          </front>
          <seriesInfo name="RFC" value="3493"/>
          <seriesInfo name="DOI" value="10.17487/RFC3493"/>
        </reference>

        <reference anchor="RFC4343" target="https://www.rfc-editor.org/info/rfc4343">
          <front>
            <title>Domain Name System (DNS) Case Insensitivity Clarification</title>
            <author initials="D." surname="Eastlake 3rd"/>
            <date year="2006" month="January"/>
          </front>
          <seriesInfo name="RFC" value="4343"/>
          <seriesInfo name="DOI" value="10.17487/RFC4343"/>
        </reference>

        <reference anchor="RFC4034" target="https://www.rfc-editor.org/info/rfc4034">
          <front>
            <title>Resource Records for the DNS Security Extensions</title>
            <author initials="R." surname="Arends"/>
            <author initials="R." surname="Austein"/>
            <author initials="M." surname="Larson"/>
            <author initials="D." surname="Massey"/>
            <author initials="S." surname="Rose"/>
            <date year="2005" month="March"/>
          </front>
          <seriesInfo name="RFC" value="4034"/>
          <seriesInfo name="DOI" value="10.17487/RFC4034"/>
        </reference>

        <reference anchor="RFC4795" target="https://www.rfc-editor.org/info/rfc4795">
          <front>
            <title>Link-Local Multicast Name Resolution (LLMNR)</title>
            <author initials="B." surname="Aboba"/>
            <author initials="D." surname="Thaler"/>
            <author initials="L." surname="Esibov"/>
            <date year="2007" month="January"/>
          </front>
          <seriesInfo name="RFC" value="4795"/>
          <seriesInfo name="DOI" value="10.17487/RFC4795"/>
        </reference>

        <reference anchor="RFC5893" target="https://www.rfc-editor.org/info/rfc5893">
          <front>
            <title>Right-to-Left Scripts for Internationalized Domain Names for Applications (IDNA)</title>
            <author initials="H." surname="Alvestrand"/>
            <author initials="C." surname="Karp"/>
            <date year="2010" month="August"/>
          </front>
          <seriesInfo name="RFC" value="5893"/>
          <seriesInfo name="DOI" value="10.17487/RFC5893"/>
        </reference>

        <reference anchor="RFC5895" target="https://www.rfc-editor.org/info/rfc5895">
          <front>
            <title>Mapping Characters for Internationalized Domain Names in Applications (IDNA) 2008</title>
            <author initials="P." surname="Resnick"/>
            <author initials="P." surname="Hoffman"/>
            <date year="2010" month="September"/>
          </front>
          <seriesInfo name="RFC" value="5895"/>
          <seriesInfo name="DOI" value="10.17487/RFC5895"/>
        </reference>

        <reference anchor="RFC6055" target="https://www.rfc-editor.org/info/rfc6055">
          <front>
            <title>IAB Thoughts on Encodings for Internationalized Domain Names</title>
            <author initials="D." surname="Thaler"/>
            <author initials="J." surname="Klensin"/>
            <author initials="S." surname="Cheshire"/>
            <date year="2011" month="February"/>
          </front>
          <seriesInfo name="RFC" value="6055"/>
          <seriesInfo name="DOI" value="10.17487/RFC6055"/>
        </reference>

        <reference anchor="RFC6066" target="https://www.rfc-editor.org/info/rfc6066">
          <front>
            <title>Transport Layer Security (TLS) Extensions: Extension Definitions</title>
            <author initials="D." surname="Eastlake 3rd"/>
            <date year="2011" month="January"/>
          </front>
          <seriesInfo name="RFC" value="6066"/>
          <seriesInfo name="DOI" value="10.17487/RFC6066"/>
        </reference>

        <reference anchor="RFC6762" target="https://www.rfc-editor.org/info/rfc6762">
          <front>
            <title>Multicast DNS</title>
            <author initials="S." surname="Cheshire"/>
            <author initials="M." surname="Krochmal"/>
            <date year="2013" month="February"/>
          </front>
          <seriesInfo name="RFC" value="6762"/>
          <seriesInfo name="DOI" value="10.17487/RFC6762"/>
        </reference>

        <reference anchor="RFC8753" target="https://www.rfc-editor.org/info/rfc8753">
          <front>
            <title>Internationalized Domain Names for Applications (IDNA) Review for New Unicode Versions</title>
            <author initials="J." surname="Klensin"/>
            <author initials="P." surname="Faltstrom"/>
            <date year="2020" month="April"/>
          </front>
          <seriesInfo name="RFC" value="8753"/>
          <seriesInfo name="DOI" value="10.17487/RFC8753"/>
        </reference>

        <reference anchor="RFC9525" target="https://www.rfc-editor.org/info/rfc9525">
          <front>
            <title>Service Identity in TLS</title>
            <author initials="P." surname="Saint-Andre"/>
            <author initials="R." surname="Salz"/>
            <date year="2023" month="November"/>
          </front>
          <seriesInfo name="RFC" value="9525"/>
          <seriesInfo name="DOI" value="10.17487/RFC9525"/>
        </reference>

        <reference anchor="UTS39" target="https://www.unicode.org/reports/tr39/">
          <front>
            <title>Unicode Security Mechanisms</title>
            <author>
              <organization>The Unicode Consortium</organization>
            </author>
            <date/>
          </front>
          <refcontent>Unicode Technical Standard #39</refcontent>
        </reference>

        <reference anchor="WHATWG-URL" target="https://url.spec.whatwg.org/">
          <front>
            <title>URL Living Standard</title>
            <author>
              <organization>WHATWG</organization>
            </author>
            <date/>
          </front>
        </reference>

        <reference anchor="DENIC2010" target="https://www.denic.de/en/whats-new/press-releases/article/german-alphabet-in-the-internet-now-complete-with-eszett-effective-16-november-the-letter-eszett-w/">
          <front>
            <title>German Alphabet In The Internet Now Complete With Eszett</title>
            <author>
              <organization>DENIC eG</organization>
            </author>
            <date year="2010" month="November" day="16"/>
          </front>
          <refcontent>Press release</refcontent>
        </reference>

      </references>
    </references>

    <section anchor="survey">
      <name>Survey of Existing Implementations</name>
      <t>This appendix is informative and records the state observed in
      July 2026; it will age.  Source references are to the respective
      public repositories and vendor documentation at that time.</t>
      <table anchor="survey-table">
        <name>Observed Behavior of Name Resolution Stacks (July 2026)</name>
        <thead>
          <tr><th>Implementation</th><th>Observed behavior</th></tr>
        </thead>
        <tbody>
          <tr>
            <td>Windows (Winsock / NLS)</td>
            <td>Conversion on by default since Windows 8; opt-out via
            AI_DISABLE_IDN_ENCODING.  The native NLS path (IdnToAscii) maps
            "ß" to "ss"; its documentation still cites RFC 3490.  Toward
            enterprise DNS in domain networks, UTF-8 queries are used, per
            the practice described in RFC 6055.</td>
          </tr>
          <tr>
            <td>.NET 5 and later (ICU)</td>
            <td>Nontransitional (UIDNA_NONTRANSITIONAL_TO_ASCII with
            joiner-context checking); diverges from the platform NLS path
            above.</td>
          </tr>
          <tr>
            <td>glibc</td>
            <td>Opt-in via AI_IDN; nontransitional via libidn2 (loaded at
            run time).  Effective table version equals that of the
            installed libidn2; the floor of this document requires
            libidn2 2.3.8 (March 2025) or later.</td>
          </tr>
          <tr>
            <td>musl</td>
            <td>No IDN conversion.  Project documentation states that
            support, when added, will always be enabled rather than
            requiring application options.</td>
          </tr>
          <tr>
            <td>Apple libc (Libinfo)</td>
            <td>No IDN conversion of any kind (source inspection);
            non-ASCII input is passed through as UTF-8 octets.</td>
          </tr>
          <tr>
            <td>WebKit</td>
            <td>UTS #46 via ICU with CheckBidi, joiner-context checking,
            and nontransitional processing, without STD3 rules --
            equivalent to the profile of this document.</td>
          </tr>
          <tr>
            <td>systemd-resolved</td>
            <td>Nontransitional via libidn2, but with a transitional
            fallback when input is disallowed, and a round-trip guard that
            discards conversions which do not round-trip.  Prepares
            per-protocol question forms (UTF-8 and IDNA), matching the
            architecture of this document; the transitional fallback does
            not.</td>
          </tr>
          <tr>
            <td>Go</td>
            <td>net/http converts via x/net/idna (nontransitional); the
            net package itself does not convert.  Tables are Unicode 15.0,
            moving to 17.0 with the Go 1.27 toolchain.</td>
          </tr>
        </tbody>
      </table>
      <t>For POSIX, the natural mapping of this document is: getaddrinfo()
      behaves by default as it does today with the GNU AI_IDN extension;
      AI_IDN becomes a no-op; a standardized counterpart to
      AI_DISABLE_IDN_ENCODING provides the opt-out of
      <xref target="default-on"/>; and the error condition of
      <xref target="errors"/> is surfaced as a distinct EAI_ value.
      Standardization of these interface details is a matter for the
      Austin Group.</t>
    </section>

    <section anchor="test-vectors">
      <name>Test Vectors</name>
      <t>The following vectors illustrate the profile of
      <xref target="conversion-procedure"/> with a table version meeting
      the floor of <xref target="unicode-floor"/>.  They were verified
      against an implementation generated from Unicode 17.0.0 data.  The
      authoritative conformance data is the IdnaTestV2.txt file published
      with <xref target="UTS46"/>.</t>
      <table anchor="vectors-table">
        <name>ToASCII Test Vectors</name>
        <thead>
          <tr><th>Input</th><th>Output</th><th>Remark</th></tr>
        </thead>
        <tbody>
          <tr>
            <td>straße.de</td>
            <td>xn--strae-oqa.de</td>
            <td>Nontransitional: ß is preserved.</td>
          </tr>
          <tr>
            <td>STRAẞE.de</td>
            <td>xn--strae-oqa.de</td>
            <td>Requires table version 15.1 or later; older tables yield
            strasse.de (see <xref target="security-skew"/>).</td>
          </tr>
          <tr>
            <td>faß.de</td>
            <td>xn--fa-hia.de</td>
            <td>Transitional processing would yield fass.de and is
            forbidden.</td>
          </tr>
          <tr>
            <td>bloß.de</td>
            <td>xn--blo-7ka.de</td>
            <td></td>
          </tr>
          <tr>
            <td>müller-straße.de (input in NFD)</td>
            <td>xn--mller-strae-46a18a.de</td>
            <td>Processing normalizes; callers need not supply NFC.</td>
          </tr>
          <tr>
            <td>σοφός.gr</td>
            <td>xn--0xagbn4a.gr</td>
            <td rowspan="2">Residual case asymmetry of final sigma
            (<xref target="security-residual"/>).</td>
          </tr>
          <tr>
            <td>ΣΟΦΌΣ.gr</td>
            <td>xn--0xahbl4a.gr</td>
          </tr>
          <tr>
            <td>日本語。ＪＰ</td>
            <td>xn--wgv71a119e.jp</td>
            <td>Ideographic and fullwidth separators and characters are
            mapped by the processing itself.</td>
          </tr>
          <tr>
            <td>_dmarc.straße.de</td>
            <td>_dmarc.xn--strae-oqa.de</td>
            <td>UseSTD3ASCIIRules=false admits the underscore label.</td>
          </tr>
          <tr>
            <td>_sip._tcp.example.com</td>
            <td>_sip._tcp.example.com</td>
            <td>ASCII fast path (<xref target="ascii-fastpath"/>): no
            processing at all.</td>
          </tr>
          <tr>
            <td>xn--strae-oqa.de</td>
            <td>xn--strae-oqa.de</td>
            <td>ASCII fast path: existing A-labels are never
            re-mapped.</td>
          </tr>
          <tr>
            <td>⒈example.com</td>
            <td>error</td>
            <td>U+2488 is disallowed; fails closed per
            <xref target="fail-closed"/>.</td>
          </tr>
        </tbody>
      </table>
    </section>


    <section anchor="acknowledgements" numbered="false">
      <name>Acknowledgements</name>
      <t>The analysis in this document benefited from the public source
      code and issue trackers of the projects surveyed in
      <xref target="survey"/>.  Reviewers and contributors will be
      acknowledged here as the document progresses.</t>
    </section>

  </back>
</rfc>
