RFC 9512

YAML Media Type

πŸ“… published February 2024, from ietf

πŸ“œ RFC 9512: YAML Media Type πŸŽ€

okay bestie, title block time πŸ’… this one is an Informational doc (so it's not a Standards Track spec, just published for info vibes 🧚). It's from the IETF, approved by the IESG, and it has the ISSN 2070-1721. It is dated February 2024 πŸ“

The authors are R. Polli (DTD, Italian Government), E. Wilde (Axway), and E. Aro (Mozilla) ✨ Nothing here obsoletes or updates any other RFC, so it's a fresh registration 🌸

The whole point of this doc is that YAML finally gets its own application/yaml media type and +yaml structured syntax suffix registered with IANA πŸ¦‹ Before this, YAML was everywhere (hi, APIs πŸ‘‘) but it had no official registration. Now it does πŸ’–


Abstract

This doc registers the application/yaml media type and the +yaml structured syntax suffix with IANA πŸŽ€ Both are for document components serialized according to the YAML spec πŸ’œ

Status of This Memo

Real talk, this is not an Internet Standards Track spec. It's published purely for informational purposes 🌈

It is still a product of the IETF, meaning it reflects consensus of the IETF community, got public review, and was approved for publication by the IESG 🫢 Not every IESG-approved doc is a candidate for an Internet Standard though, so see Section 2 of RFC 7841 for that πŸ’…

For current status, errata, or to send feedback, check https://www.rfc-editor.org/info/rfc9512 🧚

Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved πŸ”’

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as of the publication date πŸ“œ Please actually read those, bestie, because they explain your rights and restrictions πŸ™ˆ Any Code Components pulled out of this doc must include Revised BSD License text (see Section 4.e of the Trust Legal Provisions) and come without warranty, per the Revised BSD License πŸ’€

Table of Contents

1.  Introduction
  1.1.  Notational Conventions
  1.2.  Fragment Identification
    1.2.1.  Fragment Identification via Alias Nodes
2.  Media Type and Structured Syntax Suffix Registrations
  2.1.  Media Type application/yaml
  2.2.  The +yaml Structured Syntax Suffix
3.  Interoperability Considerations
  3.1.  YAML Is an Evolving Language
  3.2.  YAML Streams
  3.3.  Filename Extension
  3.4.  YAML and JSON
  3.5.  Fragment Identifiers
4.  Security Considerations
  4.1.  Arbitrary Code Execution
  4.2.  Resource Exhaustion
  4.3.  YAML Streams
  4.4.  Expressing Booleans
5.  IANA Considerations
6.  References
  6.1.  Normative References
  6.2.  Informative References
Appendix A.  Examples Related to Fragment Identifier
        Interoperability
  A.1.  Unreferenceable Nodes
  A.2.  Referencing a Missing Node
  A.3.  Representation Graph with Anchors and Cyclic References
Acknowledgements
Authors' Addresses

1. Introduction ✨

1.1. Notational Conventions πŸ¦‹

Okay so the BCP 14 key words are MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL πŸ’… They only mean the BCP 14 thing (per BCP 14 [RFC2119] [RFC8174]) when they're in ALL CAPS, like they are here 🌸

"content negotiation" and "resource" mean what they mean in [HTTP] 🧚 "fragment" and "fragment identifier" mean what they mean in [URI] ✨

These YAML terms also mean what they mean in [YAML]: "presentation", "stream", "YAML document", "representation graph", "tag", "serialization detail", "node", "alias node", "anchor", and "anchor name" πŸŽ€

Any figure with YAML code always starts with a %YAML directive so it's easier to read πŸ“œ

1.2. Fragment Identification 🌈

A fragment identifies a node in a stream. Literally that's the whole idea πŸ’œ

A fragment identifier that starts with "*" gets read as a YAML alias node (see Section 1.2.1) πŸ¦‹

For single-document YAML streams, a fragment identifier that's empty or starts with "/" is read as a JSON Pointer [JSON-POINTER], and it gets evaluated on the YAML representation graph, traversing alias nodes along the way 🧚 The empty fragment identifier points at the root node, no cap 🌸 This syntax can only reach YAML nodes sitting on a path made of nodes that are interoperable with the JSON data model (see Section 3.4) πŸ’…

A fragment identifier is not guaranteed to point at an existing node πŸ™ˆ So applications SHOULD define how they handle an unresolved alias node 🫢

1.2.1. Fragment Identification via Alias Nodes ✨

This section explains how to use alias nodes (see Sections 3.2.2.2 and 7.1 of [YAML]) as fragment identifiers to point at nodes πŸŽ€

You can represent a YAML alias node in a URI fragment identifier by encoding it into bytes with UTF-8 [UTF-8]. Percent-encoding those characters is not allowed by the fragment rule in Section 3.5 of [URI] πŸ’€

If more than one node matches a fragment identifier, the first match is the one that gets selected 🌸

If you care about fragment identifier interoperability:

  • You SHOULD limit alias nodes to characters that don't need encoding to be used as URI fragment identifiers. This is generally doable since anchor names are a serialization detail πŸ¦‹
  • You SHOULD NOT use alias nodes that match multiple nodes πŸ™ˆ

Check out this example resource πŸ‘‘ The relative reference (see Section 4.2 of [URI]) file.yaml#*foo points to the first alias node *foo, which points at the node with value scalar and not the one in the second document πŸ’– Meanwhile, file.yaml#*document_2 points at the root node of the second document, which is {one: [a, sequence]} ✨

%YAML 1.2
---
one: &foo scalar
two: &bar
  - some
  - sequence
  - items
...
%YAML 1.2
---
&document_2
one: &foo [a, sequence]

Figure 1: A YAML Stream Containing Two YAML Documents πŸ“

2. Media Type and Structured Syntax Suffix Registrations πŸ¦‹

This section has the info IANA needs to register the application/yaml media type and the +yaml structured syntax suffix per [MEDIATYPE] πŸ’…

2.1. Media Type application/yaml 🌸

The media type for YAML is application/yaml, and the info below is the registration form for it πŸŽ€

Type name:  application

Subtype name:  yaml

Required parameters:  N/A

Optional parameters:  N/A; unrecognized parameters should be ignored.

Encoding considerations:  binary

Security considerations:  See Section 4 of this document.

Interoperability considerations:  See Section 3 of this document.

Published specification:  [YAML], this document

Applications that use this media type:  Applications that need a
   human-friendly, cross-language, and Unicode-based data
   serialization language designed around the common data types of
   dynamic programming languages.

Fragment identifier considerations:  See Section 1.2 of this
   document.

Additional information:

   Deprecated alias names for this type:  application/x-yaml, text/
      yaml, and text/x-yaml.  These names are used but are not
      registered.
   Magic number(s):  N/A
   File extension(s):  "yaml" (preferred) and "yml".  See Section 3.3
      of this document.
   Macintosh file type code(s):  N/A
   Windows Clipboard Name:  YAML

Person and email address to contact for further information:  See the
   Authors' Addresses section of this document.

Intended usage:  COMMON

Restrictions on usage:  None

Author:  See the Authors' Addresses section of this document.

Change controller:  IETF

2.2. The +yaml Structured Syntax Suffix πŸ’–

The suffix +yaml MAY be used with any media type whose representation follows the one established for application/yaml ✨ The structured syntax suffix registration form is below, and see [MEDIATYPE] for what each part means 🧚

Name:  YAML Ain't Markup Language (YAML)

+suffix:  +yaml

References:  [YAML], this document

Encoding considerations:  Same as application/yaml

Interoperability considerations:  Same as application/yaml

Fragment identifier considerations:  Unlike application/yaml, there
   is no fragment identification syntax defined for +yaml.

   A specific xxx/yyy+yaml media type needs to define the syntax and
   semantics for fragment identifiers because the ones defined for
   application/yaml do not apply unless explicitly expressed.

Security considerations:  Same as application/yaml

Contact:  httpapi@ietf.org or art@ietf.org

Author:  See the Authors' Addresses section of this document.

Change controller:  IETF

3. Interoperability Considerations 🌈

3.1. YAML Is an Evolving Language πŸ’œ

YAML is an evolving language πŸ¦‹ Over time some features get added and others get removed πŸ’…

The application/yaml media type registration is independent of the YAML version 🌸 That means content negotiation works for version-independent YAML resources 🫢

Implementers who care about features tied to a specific YAML version can say which version in their YAML documents with the %YAML directive (see Section 6.8.1 of [YAML]) πŸŽ€

3.2. YAML Streams 🧚

A YAML stream can hold zero or more YAML documents ✨

When an application that only expects single-document streams receives a multi-document stream, it SHOULD signal an error instead of quietly ignoring the extra documents πŸ™ˆ

Current implementations treat different documents in a stream as independent, kind of like JSON text sequences (see [RFC7464]) πŸ¦‹ Stuff like anchors is not guaranteed to be referenceable across different documents πŸ’€

3.3. Filename Extension πŸ“

The "yaml" filename extension is the preferred one, because it's the most popular and widely used on the web πŸ‘‘ The "yml" filename extension is still used too 🌸 Using both extensions in the same context might cause interoperability issues, like when both a "config.yaml" and a "config.yml" are present 😭

Heads up: the rest of this RFC (sections 3.4 onward, the Security Considerations, IANA Considerations, References, and the Appendix) is coming in part 2 🫢 Stay tuned, bestie πŸ’–

3.4. YAML and JSON πŸŽ€

okay so when you use flow collection styles (see Section 7.4 of [YAML]), a YAML document can look basically like JSON [JSON] πŸ‘€ which means similar interoperability considerations apply, bestie.

when you're using YAML as a more efficient way to serialize info that's meant to be consumed as JSON, anything that isn't in the representation graph and counts as presentation or serialization details (see Section 3.2 of [YAML]) can be discarded πŸ—‘οΈ that includes comments (see Section 3.2.3.3 of [YAML]), directives, and alias nodes (see Section 7.1 of [YAML]) that don't have a JSON counterpart. no cap, it's a glow-up for file size but you gotta know what you're dropping ✨

 %YAML 1.2
---
# This comment will be lost
# when serializing in JSON.
Title:
  type: string
  maxLength: &text_limit 64

Name:
  type: string
  maxLength: *text_limit  # Replaced by the value 64.
       Figure 2: JSON Replaces Alias Nodes with Static Values

implementers need to make sure the relevant info won't get lost during processing πŸ’… for example, they might be totally fine with alias nodes getting swapped out for static values. that's the vibe.

in some cases, an implementer might wanna define a list of allowed YAML features, because these ones might have interoperability issues with [JSON] πŸ₯Ί

  • multi-document YAML streams
  • non-UTF-8 encoding. Before encoding YAML streams in UTF-16 or UTF-32, it is important to note that Section 8.1 of [JSON] mandates the use of UTF-8 when exchanging JSON texts between systems that are not part of a closed ecosystem and that Section 5.2 of [YAML] recommends the use of UTF-8.
  • mapping keys that are not strings
  • cyclic references represented using anchors (see Section 4.2 and Figure 4)
  • .inf and .nan float values, since JSON does not support them
  • non-JSON types, including the ones associated with tags like !!timestamp that were included in the default schema of older YAML versions
  • tags in general, specifically ones that do not map to JSON types, e.g., custom and local tags such as !!python/object and !mytag (see Section 2.4 of [YAML])
 %YAML 1.2
---
non-json-keys:
  0: a number
  [0, 1]: a sequence
  ? {k: v}
  : a map
---
non-json-keys:
  !date 2020-01-01: a timestamp
non-json-value: !date 2020-01-01
...
    Figure 3: Example of Mapping Keys and Values Not Supported in
                 JSON in a Multi-Document YAML Stream

3.5. Fragment Identifiers πŸ”

so, to let fragment identifiers travel through alias nodes, the YAML representation graph has to be generated before the fragment identifier gets evaluated 🧠 and it's really important that this evaluation doesn't cause the issues mentioned in Sections 3.4 and 4, like infinite loops and unexpected code execution. yikes, no thank you 😭

implementers need to consider that the YAML version and the supported features (e.g., merge keys) can change how the representation graph gets generated (see Figure 9). it's giving "the details matter" energy πŸ’œ

in Section 1.2, this document extends the use of specifications based on the JSON data model with support for YAML fragment identifiers. the point is to improve interoperability for practices that are already super established, like writing OpenAPI documents [OAS] in YAML 🌈

Appendix A gives a non-exhaustive list of examples to help readers understand the interoperability issues related to fragment identifiers. go check it out, it's lowkey the best part πŸ¦‹


4. Security Considerations 🚨

okay bestie, this part is serious, so let's be real. security requirements for both media types and media type suffixes are discussed in Section 4.6 of [MEDIATYPE] πŸ”

4.1. Arbitrary Code Execution πŸ’€

care should be used when using YAML tags, because resolving them might trigger unexpected code execution. this is not the time to be casual πŸ™…β€β™€οΈ

code execution in deserializers should be disabled by default and only enabled explicitly. in the latter case, the implementation should make sure (for example, via specific functions) that the code execution results in strictly bounded time/memory limits. lowkey the most important rule in this whole doc πŸ›‘οΈ

many implementations already provide safe deserializers that address these issues, so go use those 🫢

4.2. Resource Exhaustion πŸŒ€

YAML documents are rooted, connected, directed graphs and can contain reference cycles, so they can't be treated as simple trees (see Section 3.2.1 of [YAML]). an implementation that treats them as simple trees risks going into an infinite loop while traversing the YAML representation graph 😱 this can happen:

  • when trying to serialize it as JSON, or
  • when searching/identifying nodes using specifications based on the JSON data model (e.g., [JSON-POINTER]).
 %YAML 1.2
---
x: &x
  y: *x
                    Figure 4: A Cyclic Document

even if a representation graph isn't cyclic, treating it as a simple tree could still lead to improper behaviors, like triggering an Exponential Data Expansion (e.g., a Billion Laughs Attack) πŸ₯΄

 %YAML 1.2
---
x1: &a1 ["a", "a"]
x2: &a2 [*a1, *a1]
x3: &a3 [*a2, *a2]
                Figure 5: A Billion Laughs Document

this can be handled using processors that limit the anchor recursion depth and validate the input before processing it. even so, it's important to carefully test whatever implementation you're going to use πŸ§ͺ the same considerations apply when serializing a YAML representation graph in a format that doesn't support reference cycles (see Section 3.4).

4.3. YAML Streams 🌊

incremental parsing and processing of a YAML stream can produce partial results and then later indicate failure to parse the rest of the stream. to avoid partial processing, implementers might prefer validating and processing all the documents in a stream at the same time πŸ™Œ

repeated parsing and re-encoding of a YAML stream can result in document delimiters (e.g., --- or ...) being added or removed, and in anchor names and other serialization details being modified. that can break signature validation, and that's a whole mood πŸ’”

4.4. Expressing Booleans βœ…

Section 10.3.2 of [YAML] specifies that only the scalars matching the regular expression true|True|TRUE|false|False|FALSE are interpreted as booleans. older YAML versions were more tolerant (e.g., interpreting NO and N as False and interpreting YES and Y as True) πŸ™ƒ when the older syntax is used, a YAML implementation could then interpret {insecure: n} as {insecure: "n"} instead of {insecure: false}. using the syntax defined in Section 10.3.2 of [YAML] prevents these issues, so stick with it πŸ’–


5. IANA Considerations πŸ“‹

IANA has updated the "Media Types" registry (https://www.iana.org/assignments/media-types) with the registration information in Section 2.1 for the media type application/yaml.

IANA has also updated the "Structured Syntax Suffixes" registry (https://www.iana.org/assignments/media-type-structured-suffix) with the registration information in Section 2.2 for the structured syntax suffix +yaml. registry glow-up achieved ✨


6. References πŸ“š

6.1. Normative References

[HTTP]     Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
           Ed., "HTTP Semantics", STD 97, RFC 9110,
           DOI 10.17487/RFC9110, June 2022,
           <https://www.rfc-editor.org/info/rfc9110>.

[JSON]     Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
           Interchange Format", STD 90, RFC 8259,
           DOI 10.17487/RFC8259, December 2017,
           <https://www.rfc-editor.org/info/rfc8259>.

[JSON-POINTER]
           Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed.,
           "JavaScript Object Notation (JSON) Pointer", RFC 6901,
           DOI 10.17487/RFC6901, April 2013,
           <https://www.rfc-editor.org/info/rfc6901>.

[MEDIATYPE]
           Freed, N., Klensin, J., and T. Hansen, "Media Type
           Specifications and Registration Procedures", BCP 13,
           RFC 6838, DOI 10.17487/RFC6838, January 2013,
           <https://www.rfc-editor.org/info/rfc6838>.

[OAS]      Miller, D., Whitlock, J., Gardiner, M., Ralphson, M.,
           Ratovsky, R., and U. Sarid, "OpenAPI Specification",
           v3.0.0, 26 July 2017.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[URI]      Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66,
           RFC 3986, DOI 10.17487/RFC3986, January 2005,
           <https://www.rfc-editor.org/info/rfc3986>.

[UTF-8]    Yergeau, F., "UTF-8, a transformation format of ISO
           10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November
           2003, <https://www.rfc-editor.org/info/rfc3629>.

[YAML]     Ben-Kiki, O., Evans, C., dot Net, I., MΓΌller, T.,
           Antoniou, P., Aro, E., and T. Smith, "YAML Ain't Markup
           Language Version 1.2", 1 October 2021,
           <https://yaml.org/spec/1.2.2/>.

6.2. Informative References

[RFC7464]  Williams, N., "JavaScript Object Notation (JSON) Text
           Sequences", RFC 7464, DOI 10.17487/RFC7464, February 2015,
           <https://www.rfc-editor.org/info/rfc7464>.

A.1. Unreferenceable Nodes πŸ™ˆ

this example shows a couple of YAML nodes that can't be referenced based on the JSON data model, since their mapping keys aren't strings πŸ₯²

 %YAML 1.2
---
a-map-cannot:
  ? {be: expressed}
  : with a JSON Pointer

0: no numeric mapping keys in JSON
  Figure 6: Example of YAML Nodes That Are Not Referenceable Based
                       on JSON Data Model

A.2. Referencing a Missing Node πŸ‘»

in this example, the fragment #/0 doesn't reference an existing node. oof, ghosted πŸ’€

 %YAML 1.2
---
0: "JSON Pointer `#/0` references a string mapping key."
   Figure 7: Example of a JSON Pointer That Does Not Reference an
                           Existing Node

A.3. Representation Graph with Anchors and Cyclic References 🌈

in this YAML document, the #/foo/bar/baz fragment identifier traverses the representation graph and references the string you. moreover, the cyclic reference means there are infinite fragment identifiers #/foo/bat/../bat/bar referencing the &anchor node. it's giving infinite possibilities, literally πŸŒ€

 %YAML 1.2
---
anchor: &anchor
  baz: you
foo: &foo
  bar: *anchor
  bat: *foo
      Figure 8: Example of a Cyclic Reference and Alias Nodes

many YAML implementations will resolve the merge key "<<:" (https://yaml.org/type/merge.html) defined in YAML 1.1 in the representation graph. this means the fragment #/book/author/given_name references the string Federico, and the fragment #/book/<< will not reference any existing node. the merge key plot twist is real 🫣

 %YAML 1.1
---
# Many implementations use merge keys.
the-viceroys: &the-viceroys
  title: The Viceroys
  author:
    given_name: Federico
    family_name: De Roberto
book:
  <<: *the-viceroys
  title: The Illusion
                Figure 9: Example of YAML Merge Keys

Acknowledgements ✨

Huge thanks to Erik Wilde and David Biesack, who were the OG contributors to this spec 🫢 And a big shoutout to Darrel Miller and Rich Salz for backing it during the adoption phase πŸ’…

This doc is lowkey built on a LOT of conversation, both inside and outside the HTTPAPI Working Group 🌸 The following people helped make it better by opening pull requests, reporting bugs, asking the smart questions, drafting or reviewing text, and weighing in on open issues: Tina (tinita) MΓΌller πŸ¦‹, Ben Hutton 🧚, Carsten Bormann πŸ‘‘, Manu Sporny πŸ”₯, and Jason Desrosiers πŸ’œ. Main character energy, all of you πŸŽ€

Authors' Addresses πŸ“

  • Roberto Polli πŸ’–
    • Digital Transformation Department, Italian Government
    • Italy
    • Email: robipolli@gmail.com
  • Erik Wilde 🌈
    • Axway
    • Switzerland
    • Email: erik.wilde@dret.net
  • Eemeli Aro ⭐
    • Mozilla
    • Finland
    • Email: eemeli@gmail.com
πŸ“¦ where this page comes from