appendices.md
August 11, 2025 · View on GitHub
Appendices
Security Considerations
Unicode MessageFormat patterns are meant to allow a message to include any string value which users might normally wish to use in their environment. Programming languages and other environments vary in what characters are permitted to appear in a valid string. In many cases, certain types of characters, such as invisible control characters, require escaping by these host formats. In other cases, strings are not permitted to contain certain characters at all. Since messages are subject to the restrictions and limitations of their host environments, their serializations and resource formats, that might be sufficient to prevent most problems. However, MessageFormat itself does not supply such a restriction.
MessageFormat messages permit nearly all Unicode code points to appear in literals, including the text portions of a pattern. This means that it can be possible for a message to contain invisible characters (such as bidirectional controls, ASCII control characters in the range U+0000 to U+001F, or characters that might be interpreted as escapes or syntax in the host format) that abnormally affect the display of the message when viewed as source code, or in resource formats or translation tools, but do not generate errors from MessageFormat parsers or processing APIs.
Bidirectional text containing right-to-left characters (such as used for Arabic or Hebrew) also poses a potential source of confusion for users. Since MessageFormat's syntax makes use of keywords and symbols that are left-to-right or consist of neutral characters (including characters subject to mirroring under the Unicode Bidirectional Algorithm), it is possible to create messages that, when displayed in source code, or in resource formats or translation tools, have a misleading appearance or are difficult to parse visually.
For more information, see [UTS#55] Unicode Source Code Handling.
MessageFormat implementations might allow end-users to install selectors, functions, or markup from third-party sources. Such functionality can be a vector for various exploits, including buffer overflow, code injection, user tracking, fingerprinting, and other types of bad behavior. Any installed code needs to be appropriately sandboxed. In addition, end-users need to be aware of the risks involved.
Non-normative Examples
Pattern Selection Examples
Selection Example 1
Presuming a minimal implementation which only supports :string function
which matches keys by using string comparison,
and a formatting context in which
the variable reference $foo resolves to the string 'foo' and
the variable reference $bar resolves to the string 'bar',
pattern selection proceeds as follows for this message:
.input {$foo :string}
.input {$bar :string}
.match $foo $bar
bar bar {{All bar}}
foo foo {{All foo}}
* * {{Otherwise}}
- Each selector is resolved, yielding the list
res={foo, bar}. bestVariantis set toUNSET.keysis set to{bar, bar}.matchis set to SelectorsMatch({foo, bar},{bar, bar}). The result of SelectorsMatch({foo, bar},{bar, bar}) is determined as follows:resultis set to true.iis set to 0.kis set to the stringbar.selis set to a resolved value corresponding to the stringfoo.- Match(
sel,'bar') is false. - The result of SelectorsMatch(
{foo, bar},{bar, bar}) is false. Thus,matchis set to false.
keysis set to{foo, foo}.matchis set to SelectorsMatch({foo, bar},{foo, foo}). The result of SelectorsMatch({foo, bar},{foo, foo}) is determined as follows:resultis set to true.iis set to 0.kis set to the stringfoo.selis set to a resolved value corresponding to the stringfoo.- Match(
sel,'foo') is true. iis set to 1.kis set to the stringfoo.selis set to a resolved value corresponding to the stringbar.- Match(
sel,'bar') is false. - The result of SelectorsMatch(
{foo, bar},{foo, foo}) is false.
keysis set to* *.- The result of SelectorsMatch(
{foo, bar},{*, *}) is determined as follows:resultis set to true.iis set to 0.iis set to 1.iis set to 2.- The result of SelectorsMatch(
{foo, bar},{*, *}) is true.
bestVariantis set to the variant* * {{Otherwise}}- The pattern
Otherwiseis selected.
Selection Example 2
Alternatively, with the same implementation and formatting context as in Example 1, pattern selection would proceed as follows for this message:
.input {$foo :string}
.input {$bar :string}
.match $foo $bar
* bar {{Any and bar}}
foo * {{Foo and any}}
foo bar {{Foo and bar}}
* * {{Otherwise}}
- Each selector is resolved, yielding the list
res={foo, bar}. bestVariantis set toUNSET.keysis set to{*, bar}.matchis set to SelectorsMatch({foo, bar},{*, bar}) The result of SelectorsMatch({foo, bar},{*, bar}) is determined as follows:resultis set to true.iis set to 0.iis set to 1.kis set to the stringbar.selis set to a resolved value corresponding to the stringbar.- Match(
sel,'bar') is true. iis set to 2.- The result of SelectorsMatch(
{foo, bar},{*, bar}) is true.
bestVariantis set to the variant* bar {{Any and bar}}.keysis set to{foo, *}.matchis set to SelectorsMatch({foo, bar},{foo, *}). The result of SelectorsMatch({foo, bar},{foo, *}) is determined as follows:resultis set to true.iis set to 0.kis set to the stringfoo.selis set to a resolved value corresponding to the stringfoo.- Match(
sel,'foo') is true. iis set to 1.iis set to 2.- The result of SelectorsMatch(
{foo, bar},{foo, *}) is true.
bestVariantKeysis set to{*, bar}.- SelectorsCompare(
{foo, bar},{foo, *},{*, bar}) is determined as follows:resultis set to false.iis set to 0.key1is set tofoo.key2is set to'*'- The result of SelectorsCompare(
{foo, bar},{foo, *},{*, bar}) is true.
bestVariantis set tofoo * {{Foo and any}}.keysis set to{foo, bar}.matchis set to SelectorsMatch({foo, bar},{foo, bar}).matchis true (details elided)
bestVariantKeysis set to{foo, *}.- SelectorsCompare(
{foo, bar},{foo, bar},{foo, *}) is determined as follows:resultis set to false.iis set to 0.key1is set tofoo.key2is set tofoo.k1is set tofoo.k2is set tofoo.selis set to a resolved value corresponding tofoo.iis set to 1.key1is set tobar.key2is set to*.- The result of SelectorsCompare(
{foo, bar},{foo, bar},{foo, *}) is true.
bestVariantis set tofoo bar {{Foo and bar}}.keysis set to* *.matchis set to true (details elided).bestVariantKeysis set tofoo bar.- SelectorsCompare(
{foo, bar},{*, *},{foo, bar}} is false (details elided).
The pattern {{Foo and bar}} is selected.
Selection Example 3
A more-complex example is the matching found in selection APIs
such as ICU's PluralFormat.
Suppose that this API is represented here by the function :number.
This :number function can match a given numeric value to a specific number literal
and also to a plural category (zero, one, two, few, many, other)
according to locale rules defined in CLDR.
Given a variable reference $count whose value resolves to the number 1
and an en (English) locale,
the pattern selection proceeds as follows for this message:
.input {$count :number}
.match $count
one {{Category match for {$count}}}
1 {{Exact match for {$count}}}
* {{Other match for {$count}}}
- Each selector is resolved, yielding the list
{1}. bestVariantis set toUNSET.keysis set to{one}.matchis set to SelectorsMatch({1},{one}). The result of SelectorsMatch({1},{one}) is determined as follows:resultis set to true.iis set to 0.kis set toone.selis set to1.- Match(
sel,one) is true. iis set to 1.- The result of SelectorsMatch(
{1},{one}) is true.
bestVariantis set toone {{Category match for {$count}}}.keysis set to1.matchis set to SelectorsMatch({1},{one}).- The details are the same as the previous case,
as Match(
sel,1) is also true.
- The details are the same as the previous case,
as Match(
bestVariantKeysis set to{one}.- SelectorsCompare(
{1},{1},{one}) is determined as follows:resultis set to false.iis set to 0.key1is set to1.key2is set toone.k1is set to1.k2is set toone.selis set to1.resultis set to BetterThan(sel,1,one), which is true.- NOTE: The specification of the
:numberselector function states that the exact match1is a better match than the category matchone.
- NOTE: The specification of the
bestVariantis set to1 {{Exact match for {$count}}}.
keysis set to*- Details elided; since
*is the catch-all key, BetterThan({1},{1},{*}) is false.
- Details elided; since
- The pattern
{{Exact match for {$count}}}is selected.
Acknowledgments
Special thanks to the following people for their contributions to making the Unicode MessageFormat Standard. The following people contributed to our github repo and are listed in order by contribution size:
Addison Phillips, Eemeli Aro, Romulo Cintra, Tim Chevalier, Stanisław Małolepszy, Elango Cheran, Richard Gibson, Mark Davis, Mihai Niță, Steven R. Loomis, Shane F. Carr, Matt Radbourne, Caleb Maclennan, David Filip, Christopher Dieringer, Danny Gleckler, Bruno Haible, Daniel Minor, George Rhoten, Ujjwal Sharma, Markus Scherer, Lionel Rowe, Luca Casonato, Daniel Ehrenberg, Zibi Braniecki, and Rafael Xavier de Souza.
Eemeli Aro is the current chair of the working group. Addison Phillips was chair of the working group from January 2023 to July 2025. Prior to 2023, the group was governed by a chair group, consisting of Romulo Cintra, Elango Cheran, Mihai Niță, David Filip, Nicolas Bouvrette, Stanisław Małolepszy, Rafael Xavier de Souza, Addison Phillips, and Daniel Minor. Romulo Cintra chaired the chair group.