@@ -635,6 +635,51 @@ Variables in Shorthand Properties</h3>
635635 if any of the longhand subproperties for that shorthand have <a>pending-substitution values</a>
636636 then the serialized value of the shorthand must be the empty string.
637637
638+ <h3 id=long-variables>
639+ Safely Handling Overly-Long Variables</h3>
640+
641+ Naively implemented,
642+ ''var()'' functions can be used in a variation of the "billion laughs attack":
643+
644+ <div class=example>
645+ <pre lang=css>
646+ .foo {
647+ --prop1: lol;
648+ --prop2: var(--prop1) var(--prop1);
649+ --prop3: var(--prop2) var(--prop2);
650+ --prop4: var(--prop3) var(--prop3);
651+ /* etc */
652+ }
653+ </pre>
654+
655+ In this short example, ''--prop4'' ’s computed value is ''lol lol lol lol lol lol lol lol'' ,
656+ containing 8 copies of the original ''lol'' .
657+ Every additional level added to this doubles the number of identifiers;
658+ extending it to a mere 30 levels,
659+ the work of a few minutes by hand,
660+ would make ''--prop30'' contain <em> nearly a billion instances</em> of the identifier.
661+ </div>
662+
663+ To avoid this sort of attack,
664+ UAs must impose a UA-defined limit on the allowed length of the token stream
665+ that a ''var()'' function expands into.
666+ If a ''var()'' would expand into a longer token stream than this limit,
667+ it instead makes the property it's expanding into
668+ [=invalid at computed-value time=] .
669+
670+ This specification does not define what size limit should be imposed.
671+ However, since there are valid use-cases for custom properties that contain a kilobyte or more of text,
672+ it's recommended that the limit be set relatively high.
673+
674+ Note: The general principle that UAs are allowed to violate standards due to resource constraints
675+ is still generally true here;
676+ a UA might, separately, have limits on how long of a custom property they can support,
677+ or how large of an identifier they can support.
678+ This section calls out this attack specifically
679+ because of its long history,
680+ and the fact that it can be done without any of the pieces
681+ <em> seeming</em> to be too large on first inspection.
682+
638683
639684
640685<!--
@@ -706,5 +751,9 @@ Privacy and Security Considerations {#priv-sec}
706751===============================================
707752
708753This specification defines a purely author-level mechanism for passing styling information around within a page they control.
754+ As such, there are no new privacy considerations.
709755
710- As such, there are no new privacy or security considerations.
756+ [[#long-variables]] calls out a long-standing Denial-of-Service attack
757+ that can be mounted against "macro-expansion"-like mechanisms,
758+ such as the ''var()'' function,
759+ and mandates a defense against that attack.
0 commit comments