tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

attr-security.html (11672B)


      1 <!DOCTYPE html>
      2 <title>CSS Values and Units Test: attr() security limitations</title>
      3 <link rel="help" href="https://drafts.csswg.org/css-values-5/#attr-security">
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 
      7 <style>
      8  @property --some-string {
      9    syntax: "<string>";
     10    inherits: false;
     11    initial-value: "empty";
     12  }
     13  @property --some-string-list {
     14    syntax: "<string>+";
     15    inherits: false;
     16    initial-value: "empty";
     17  }
     18  div {
     19    --condition-val: 3;
     20    --str: text;
     21    --true: true;
     22    --some-string: attr(data-foo);
     23    --some-string-list: "https://does-not-exist2.test/404.png" attr(data-foo);
     24    --some-other-url: attr(data-foo);
     25    --image-set-valid:  url("https://does-not-exist.test/404.png") type(attr(data-foo));
     26    --image-set-invalid: attr(data-foo type(<url>)) 1x;
     27  }
     28 </style>
     29 
     30 <html>
     31  <body>
     32    <div id="attr"></div>
     33  </body>
     34 </html>
     35 
     36 <script>
     37    function test_attr(property, attrString, attrValue, expectedValue) {
     38        var elem = document.getElementById("attr");
     39        elem.setAttribute("data-foo", attrValue);
     40        elem.style.setProperty(property, attrString);
     41 
     42        test(() => {
     43            assert_equals(window.getComputedStyle(elem).getPropertyValue(property),
     44                          expectedValue);
     45        }, `'${property}: ${attrString}' with data-foo="${attrValue}"`);
     46 
     47        elem.style.setProperty(property, null);
     48    }
     49 
     50    function test_registered_custom_property(customPropertyName, customPropertySyntax, customPropertyInitialValue,
     51                                             attrValue, expectedValue) {
     52      window.CSS.registerProperty({
     53        name: customPropertyName,
     54        syntax: customPropertySyntax,
     55        inherits: false,
     56        initialValue: customPropertyInitialValue,
     57      });
     58      var elem = document.getElementById("attr");
     59      elem.setAttribute("data-foo", attrValue);
     60      var attrString = "attr(data-foo type(" + customPropertySyntax + "))";
     61      elem.style.setProperty(customPropertyName, attrString);
     62      test(() => {
     63          assert_equals(window.getComputedStyle(elem).getPropertyValue(customPropertyName),
     64                        expectedValue);
     65      }, `'${customPropertyName}: ${attrString}' with data-foo="${attrValue}"`);
     66      elem.style.setProperty(customPropertyName, null);
     67    }
     68 
     69    // Direct use.
     70    test_attr('--x',
     71              'image-set(attr(data-foo))',
     72              'https://does-not-exist.test/404.png',
     73              'image-set("https://does-not-exist.test/404.png")');
     74    test_attr('background-image',
     75              'image-set(attr(data-foo))',
     76              'https://does-not-exist.test/404.png',
     77              'none');
     78    test_attr('background-image',
     79              'image-set("https://does-not-exist.test/404.png")',
     80              'https://does-not-exist.test/404.png',
     81              'image-set(url("https://does-not-exist.test/404.png") 1dppx)');
     82 
     83    test_attr('--x',
     84              'src(attr(data-foo))',
     85              'https://does-not-exist.test/404.png',
     86              'src("https://does-not-exist.test/404.png")');
     87    test_attr('background-image',
     88              'src(attr(data-foo))',
     89              'https://does-not-exist.test/404.png',
     90              'none');
     91    test_attr('background-image',
     92              'src("https://does-not-exist.test/404.png")',
     93              'https://does-not-exist.test/404.png',
     94              'src(url("https://does-not-exist.test/404.png"))');
     95 
     96    // The following string() function is under discussion in the working group and does not exist yet.
     97    test_attr('--x',
     98              'src(string("https://does-not-exist.test" attr(data-foo)))',
     99              '/404.png',
    100              'src(string("https://does-not-exist.test" "/404.png"))');
    101    test_attr('background-image',
    102              'src(string("https://does-not-exist.test" attr(data-foo)))',
    103              '/404.png',
    104              'none');
    105    test_attr('background-image',
    106              'src(string("https://does-not-exist.test/""404.png"))',
    107              '/404.png',
    108              'src(url("https://does-not-exist.test/404.png"))');
    109 
    110    test_attr('--x',
    111              'attr(data-foo type(<url>))',
    112              'url(https://does-not-exist.test/404.png)',
    113              'url("https://does-not-exist.test/404.png")');
    114    test_attr('background-image',
    115              'attr(data-foo type(<url>))',
    116              'url(https://does-not-exist.test/404.png)',
    117              'none');
    118    test_attr('background-image',
    119              'url("https://does-not-exist.test/404.png")',
    120              'url(https://does-not-exist.test/404.png)',
    121              'url("https://does-not-exist.test/404.png")');
    122 
    123    test_attr('--x',
    124              'image(attr(data-foo))',
    125              'https://does-not-exist.test/404.png',
    126              'image("https://does-not-exist.test/404.png")');
    127    test_attr('background-image',
    128              'image(attr(data-foo))',
    129              'https://does-not-exist.test/404.png',
    130              'none');
    131    test_attr('background-image',
    132              'image("https://does-not-exist.test/404.png")',
    133              'https://does-not-exist.test/404.png',
    134              'image(url("https://does-not-exist.test/404.png"))');
    135 
    136    test_attr('background-image',
    137              'url(https://does-not-exist.test/404.png), attr(data-foo type(<image>))',
    138              'linear-gradient(#000000, #ffffff)',
    139              'url("https://does-not-exist.test/404.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 255, 255))');
    140 
    141    // The remaining tests use image-set(), but should be equivalent for image() etc.
    142 
    143    // Test in a fallback.
    144    test_attr('--x',
    145              'image-set(var(--y, attr(data-foo)))',
    146              'https://does-not-exist.test/404.png',
    147              'image-set("https://does-not-exist.test/404.png")');
    148    test_attr('background-image',
    149              'image-set(var(--y, attr(data-foo)))',
    150              'https://does-not-exist.test/404.png',
    151              'none');
    152 
    153    // Test via a registered custom property.
    154    test_attr('--x',
    155              'image-set(var(--some-string))',
    156              'https://does-not-exist.test/404.png',
    157              'image-set("https://does-not-exist.test/404.png")');
    158    test_attr('background-image',
    159              'image-set(var(--some-string))',
    160              'https://does-not-exist.test/404.png',
    161              'none');
    162 
    163    // Test via a registered custom property (list).
    164    test_attr('--x',
    165              'image-set(var(--some-string-list))',
    166              'https://does-not-exist.test/404.png',
    167              'image-set("https://does-not-exist2.test/404.png" "https://does-not-exist.test/404.png")');
    168    test_attr('background-image',
    169              'image-set(var(--some-string-list))',
    170              'https://does-not-exist.test/404.png',
    171              'none');
    172    test_registered_custom_property('--registered-url', '<url>', 'url("https://does-not-exist.test/empty-url")', 'https://does-not-exist.test/404.png', 'url("https://does-not-exist.test/empty-url")');
    173    test_registered_custom_property('--registered-color', '<color>', 'red', 'blue', 'rgb(0, 0, 255)');
    174 
    175    // Test via a non-registered custom property.
    176    test_attr('--x',
    177              'image-set(var(--some-other-url))',
    178              'https://does-not-exist.test/404.png',
    179              'image-set("https://does-not-exist.test/404.png")');
    180    test_attr('background-image',
    181              'image-set(var(--some-other-url))',
    182              'https://does-not-exist.test/404.png',
    183              'none');
    184 
    185    // Test multiple token substitution
    186    test_attr('background-image',
    187              'attr(data-foo type(*))',
    188              'url(https://does-not-exist.test/404.png), linear-gradient(black, white)',
    189              'none');
    190 
    191    // Test total attr()-tainting for substitution values
    192    test_attr('background-image',
    193              'image-set(var(--image-set-valid))',
    194              'image/jpeg',
    195              'none');
    196    test_attr('background-image',
    197              'image-set(var(--image-set-invalid))',
    198              'https://does-not-exist.test/404.png',
    199              'none');
    200 
    201    // Test attr-tainting carries through if() function.
    202    test_attr('--x',
    203              'image-set(if(style(--true): attr(data-foo);))',
    204              'https://does-not-exist.test/404.png',
    205              'image-set("https://does-not-exist.test/404.png")');
    206    test_attr('background-image',
    207              'image-set(if(style(--true): attr(data-foo);))',
    208              'https://does-not-exist.test/404.png',
    209              'none');
    210    test_attr('background-image',
    211              `image-set(
    212                if(style(--true): url(https://does-not-exist-2.test/404.png);
    213                   else: attr(data-foo);))`,
    214              'https://does-not-exist-2.test/404.png',
    215              'image-set(url("https://does-not-exist-2.test/404.png") 1dppx)');
    216    test_attr('background-image',
    217              `image-set(
    218                if(style(--some-string): url(https://does-not-exist.test/404.png);))`,
    219              'https://does-not-exist.test/404.png',
    220              'none');
    221    test_attr('background-image',
    222              `image-set(
    223                if(style(--condition-val: attr(data-foo type(*))): url(https://does-not-exist.test/404.png);))`,
    224              '3',
    225              'none');
    226    test_attr('background-image',
    227              `image-set(
    228                if(style(--condition-val: attr(data-foo type(*))): url(https://does-not-exist.test/404.png);
    229                   style(--true): url(https://does-not-exist.test/404.png);
    230                   else: url(https://does-not-exist.test/404.png);))`,
    231              '1',
    232              'none');
    233    test_attr('background-image',
    234              `image-set(if(style(--true): url(https://does-not-exist.test/404.png);
    235                            style(--condition-val): url(https://does-not-exist.test/404.png);
    236                            else: url(https://does-not-exist.test/404.png);))`,
    237              'attr(data-foo type(*))',
    238              'image-set(url("https://does-not-exist.test/404.png") 1dppx)');
    239    test_attr('background-image',
    240              `image-set(
    241                if(style(--condition-val: if(style(--true): attr(data-foo type(*));)): url(https://does-not-exist.test/404.png);))`,
    242              '3',
    243              'none');
    244    test_attr('--x',
    245              `image-set(if(style(--condition-val: if(style(--true): attr(data-foo type(*));)): url(https://does-not-exist.test/404.png);))`,
    246              '3',
    247              'image-set(url(https://does-not-exist.test/404.png))');
    248    test_attr('--x',
    249              `image-set(if(style(--condition-val >= attr(data-foo type(*))): url(https://does-not-exist.test/404.png);))`,
    250              '3',
    251              'image-set(url(https://does-not-exist.test/404.png))');
    252    test_attr('background-image',
    253              `image-set(
    254                if(style(--condition-val >= attr(data-foo type(*))): url(https://does-not-exist.test/404.png);))`,
    255              '3',
    256              'none');
    257    test_attr('background-image',
    258              `image-set(
    259                if(style(--condition-val < attr(data-foo type(*))): url(https://does-not-exist.test/404.png);))`,
    260              '3',
    261              'none');
    262    test_attr('background-image',
    263              `image-set(
    264                if(style(--str < attr(data-foo type(*))): url(https://does-not-exist.test/404.png);))`,
    265              '3',
    266              'none');
    267    test_attr('background-image',
    268              `image-set(
    269                if(style(--condition-val < attr(data-foo type(*))): url(https://does-not-exist.test/404.png);))`,
    270              'text',
    271              'none');
    272 </script>