| Dominic Farolino | f0c2701 | 2019-06-27 10:47:44 | [diff] [blame] | 1 | <!DOCTYPE html> |
| 2 | <meta charset=utf-8> |
| 3 | <title>Subresource Integrity</title> |
| 4 | <script src="/resources/testharness.js"></script> |
| 5 | <script src="/resources/testharnessreport.js"></script> |
| 6 | <script src="/resources/sriharness.js"></script> |
| 7 | <script src="/common/utils.js"></script> |
| 8 | <script src="/subresource-integrity/sri-test-helpers.sub.js"></script> |
| 9 | |
| 10 | <div id="log"></div> |
| 11 | |
| 12 | <div id="container"></div> |
| 13 | <script> |
| 14 | // This is a list of information for each preload destination. The information |
| 15 | // is used in a loop iterating over the below tests, so that each test is run |
| 16 | // for each destination. |
| 17 | const preload_destination_info = [ |
| 18 | { |
| 19 | destination: 'script', ext: '.js', supports_sri: true, |
| 20 | sha256: 'sha256-Bu681KMnQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA=', |
| 21 | sha384: 'sha384-cINXh+nCzEHPWzXS7eoT+vYMBpyqczOybRLNU3XAButFWCRhHT5hLByIbPRqIm2f', |
| 22 | sha512: 'sha512-KZdenhzBd7X7Q/vmaOSyvFz1CGdoVt26xzCZjlkU9lfBEK+V/ougGys7iYDi0+tOHIQSQa87bIqx95R7GU7I9Q==' |
| 23 | }, |
| 24 | { |
| 25 | destination: 'style', ext: '.css', supports_sri: true, |
| 26 | sha256: 'sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=', |
| 27 | sha384: 'sha384-wDAWxH4tOWBwAwHfBn9B7XuNmFxHTMeigAMwn0iVQ0zq3FtmYMLxihcGnU64CwcX', |
| 28 | sha512: 'sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w==' |
| 29 | }, |
| Dominic Farolino | 550b9db | 2019-07-05 08:44:23 | [diff] [blame] | 30 | { |
| 31 | destination: 'image', ext: '.png', supports_sri: false, |
| 32 | sha256: 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=', |
| 33 | sha384: 'sha384-OLBgp1GsljhM2TJ+sbHjaiH9txEUvgdDTAzHv2P24donTt6/529l+9Ua0vFImLlb', |
| 34 | sha512: 'sha512-z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg==' |
| 35 | }, |
| Dominic Farolino | f0c2701 | 2019-06-27 10:47:44 | [diff] [blame] | 36 | // TODO(domfarolino): Add more destinations. |
| 37 | ]; |
| 38 | |
| 39 | for (const info of preload_destination_info) { |
| 40 | const {destination, ext, supports_sri, sha256, sha384, sha512} = info; |
| 41 | |
| 42 | // Preload + Subresource Integrity tests. These tests work by passing some |
| 43 | // destination-specific information (defined in |preload_destination_info|) |
| 44 | // to the below tests, which do the following: |
| 45 | // Create a <link rel="preload"> for the given destination, with the |
| 46 | // specified `integrity`. After this has either loaded or failed to load, |
| 47 | // the subresource element corresponding to |destination| will be created, |
| 48 | // attempting to re-use the preloaded resource. `integrity` may be specified |
| 49 | // on the subresource elements that support SRI as well. The subresource |
| 50 | // will either load or fail to load, and the result will be compared with an |
| 51 | // expectation passed to the test. |
| 52 | SRIPreloadTest( |
| 53 | true, /* preload_sri_success */ |
| 54 | true, /* subresource_sri_success */ |
| 55 | `Same-origin ${destination} with correct sha256 hash.`, /* name */ |
| 56 | destination, /* destination */ |
| 57 | same_origin_prefix + destination + ext + `?${token()}`, /* resource_url (for preload + subresource) */ |
| 58 | {integrity: sha256}, /* link_attrs */ |
| 59 | {} /* subresource_attrs */ |
| 60 | ) |
| 61 | |
| 62 | SRIPreloadTest( |
| 63 | true, |
| 64 | true, |
| 65 | `Same-origin ${destination} with correct sha384 hash.`, |
| 66 | destination, |
| 67 | same_origin_prefix + destination + ext + `?${token()}`, |
| 68 | {integrity: sha384}, |
| 69 | {} |
| 70 | ) |
| 71 | |
| 72 | SRIPreloadTest( |
| 73 | true, |
| 74 | true, |
| 75 | `Same-origin ${destination} with correct sha512 hash.`, |
| 76 | destination, |
| 77 | same_origin_prefix + destination + ext + `?${token()}`, |
| 78 | {integrity: sha512}, |
| 79 | {} |
| 80 | ) |
| 81 | |
| 82 | SRIPreloadTest( |
| 83 | true, |
| 84 | true, |
| 85 | `Same-origin ${destination} with empty integrity.`, |
| 86 | destination, |
| 87 | same_origin_prefix + destination + ext + `?${token()}`, |
| 88 | {}, |
| 89 | {} |
| 90 | ) |
| 91 | |
| 92 | SRIPreloadTest( |
| 93 | false, |
| 94 | false, |
| 95 | `Same-origin ${destination} with incorrect hash.`, |
| 96 | destination, |
| 97 | same_origin_prefix + destination + ext + `?${token()}`, |
| 98 | {integrity: "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"}, |
| 99 | {} |
| 100 | ) |
| 101 | |
| 102 | SRIPreloadTest( |
| 103 | true, |
| 104 | true, |
| 105 | `Same-origin ${destination} with multiple sha256 hashes, including correct.`, |
| 106 | destination, |
| 107 | same_origin_prefix + destination + ext + `?${token()}`, |
| 108 | {integrity: `${sha256} sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead`}, |
| 109 | {} |
| 110 | ) |
| 111 | |
| 112 | SRIPreloadTest( |
| 113 | true, |
| 114 | true, |
| 115 | `Same-origin ${destination} with multiple sha256 hashes, including unknown algorithm.`, |
| 116 | destination, |
| 117 | same_origin_prefix + destination + ext + `?${token()}`, |
| 118 | {integrity: `${sha256} foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead`}, |
| 119 | {} |
| 120 | ) |
| 121 | |
| 122 | SRIPreloadTest( |
| 123 | true, |
| 124 | true, |
| 125 | `Same-origin ${destination} with sha256 mismatch, sha512 match`, |
| 126 | destination, |
| 127 | same_origin_prefix + destination + ext + `?${token()}`, |
| 128 | {integrity: `${sha512} sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead`}, |
| 129 | {} |
| 130 | ) |
| 131 | |
| 132 | SRIPreloadTest( |
| 133 | false, |
| 134 | false, |
| 135 | `Same-origin ${destination} with sha256 match, sha512 mismatch`, |
| 136 | destination, |
| 137 | same_origin_prefix + destination + ext + `?${token()}`, |
| 138 | {integrity: `sha512-deadbeefspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== ${sha256}`}, |
| 139 | {} |
| 140 | ) |
| 141 | |
| 142 | SRIPreloadTest( |
| 143 | true, |
| 144 | true, |
| 145 | `<crossorigin='anonymous'> ${destination} with correct hash, ACAO: *`, |
| 146 | destination, |
| 147 | xorigin_prefix + destination + ext + `?${token()}` + anonymous, |
| 148 | {integrity: sha256, crossOrigin: 'anonymous'}, |
| 149 | {crossOrigin: "anonymous"} |
| 150 | ) |
| 151 | |
| 152 | SRIPreloadTest( |
| 153 | false, |
| 154 | false, |
| 155 | `<crossorigin='anonymous'> ${destination} with incorrect hash, ACAO: *`, |
| 156 | destination, |
| 157 | xorigin_prefix + destination + ext + `?${token()}` + anonymous, |
| 158 | {integrity: "sha256-sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead", crossOrigin: "anonymous"}, |
| 159 | {crossOrigin: "anonymous"} |
| 160 | ) |
| 161 | |
| 162 | SRIPreloadTest( |
| 163 | true, |
| 164 | true, |
| 165 | `<crossorigin='use-credentials'> ${destination} with correct hash, CORS-eligible`, |
| 166 | destination, |
| 167 | xorigin_prefix + destination + ext + `?${token()}` + use_credentials, |
| 168 | {integrity: sha256, crossOrigin: "use-credentials"}, |
| 169 | {crossOrigin: "use-credentials"} |
| 170 | ) |
| 171 | |
| 172 | SRIPreloadTest( |
| 173 | false, |
| 174 | false, |
| 175 | `<crossorigin='use-credentials'> ${destination} with incorrect hash CORS-eligible`, |
| 176 | destination, |
| 177 | xorigin_prefix + destination + ext + `?${token()}` + use_credentials, |
| 178 | {integrity: "sha256-deadbeef2S+pTRZgiw3DWrhC6JLDlt2zRyGpwH7unU8=", crossOrigin: "use-credentials"}, |
| 179 | {crossOrigin: "use-credentials"} |
| 180 | ) |
| 181 | |
| 182 | SRIPreloadTest( |
| 183 | false, |
| 184 | false, |
| 185 | `<crossorigin='anonymous'> ${destination} with CORS-ineligible resource`, |
| 186 | destination, |
| 187 | // not piping ACAO header makes this CORS-ineligible |
| 188 | xorigin_prefix + destination + ext + `?${token()}`, |
| 189 | {integrity: sha256, crossOrigin: "anonymous"}, |
| 190 | {crossOrigin: "anonymous"} |
| 191 | ) |
| 192 | |
| 193 | SRIPreloadTest( |
| 194 | false, |
| 195 | false, |
| 196 | `Cross-origin ${destination}, not CORS request, with correct hash`, |
| 197 | destination, |
| 198 | xorigin_prefix + destination + ext + `?${token()}` + anonymous, |
| 199 | {integrity: sha256}, |
| 200 | {} |
| 201 | ) |
| 202 | |
| 203 | SRIPreloadTest( |
| 204 | false, |
| 205 | false, |
| 206 | `Cross-origin ${destination}, not CORS request, with hash mismatch`, |
| 207 | destination, |
| 208 | xorigin_prefix + destination + ext + `?${token()}` + anonymous, |
| 209 | {integrity: "sha256-deadbeef01Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0="}, |
| 210 | {} |
| 211 | ) |
| 212 | |
| 213 | SRIPreloadTest( |
| 214 | true, |
| 215 | true, |
| 216 | `Cross-origin ${destination}, empty integrity`, |
| 217 | destination, |
| 218 | xorigin_prefix + destination + ext + `?${token()}` + anonymous, |
| 219 | {}, |
| 220 | {} |
| 221 | ) |
| 222 | |
| 223 | SRIPreloadTest( |
| 224 | true, |
| 225 | true, |
| 226 | `Same-origin ${destination} with correct hash, options.`, |
| 227 | destination, |
| 228 | same_origin_prefix + destination + ext + `?${token()}`, |
| 229 | {integrity: `${sha256}?foo=bar?spam=eggs`}, |
| 230 | {} |
| 231 | ) |
| 232 | |
| 233 | SRIPreloadTest( |
| 234 | true, |
| 235 | true, |
| 236 | `Same-origin ${destination} with unknown algorithm only.`, |
| 237 | destination, |
| 238 | same_origin_prefix + destination + ext + `?${token()}`, |
| 239 | {integrity: "foo666-8aBiAJl3ukQwSJ6eTs5wl6hGjnOtyXjcTRdAf89uIfY="}, |
| 240 | {} |
| 241 | ) |
| 242 | |
| 243 | // The below tests are specific to subresource destinations that support |
| 244 | // SRI. See |supports_sri|. |
| 245 | if (supports_sri) { |
| 246 | |
| 247 | SRIPreloadTest( |
| 248 | true, |
| 249 | true, |
| 250 | `Same-origin ${destination} with matching digest re-uses preload with matching digest.`, |
| 251 | destination, |
| 252 | same_origin_prefix + destination + ext + `?${token()}`, |
| 253 | {integrity: sha256}, |
| 254 | {integrity: sha256} |
| 255 | ) |
| 256 | |
| 257 | SRIPreloadTest( |
| 258 | true, |
| 259 | false, |
| 260 | `Same-origin ${destination} with non-matching digest does not re-use preload with matching digest.`, |
| 261 | destination, |
| 262 | same_origin_prefix + destination + ext + `?${token()}`, |
| 263 | {integrity: sha256}, |
| 264 | {integrity: "sha256-deadbeefQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA="} |
| 265 | ) |
| 266 | |
| 267 | SRIPreloadTest( |
| 268 | false, |
| 269 | true, |
| 270 | `Same-origin ${destination} with matching digest does not re-use preload with non-matching digest.`, |
| 271 | destination, |
| 272 | same_origin_prefix + destination + ext + `?${token()}`, |
| 273 | {integrity: "sha256-deadbeefQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA="}, |
| 274 | {integrity: sha256} |
| 275 | ) |
| 276 | |
| 277 | SRIPreloadTest( |
| 278 | false, |
| 279 | false, |
| 280 | `Same-origin ${destination} with non-matching digest does not re-use preload with non-matching digest.`, |
| 281 | destination, |
| 282 | same_origin_prefix + destination + ext + `?${token()}`, |
| 283 | {integrity: "sha256-deadbeefQ15RYHFvsYdWumweeFAw0hJDTFt9seErghA="}, |
| 284 | {integrity: "sha256-deaddeadbeefYHFvsYdWumweeFAw0hJDTFt9seErghA="} |
| 285 | ) |
| 286 | |
| 287 | } // if. |
| 288 | |
| 289 | } // for-of. |
| 290 | </script> |