Changeset 216347 in webkit


Ignore:
Timestamp:
May 7, 2017 3:24:48 AM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Implement Subresource Integrity (SRI)
https://bugs.webkit.org/show_bug.cgi?id=148363
LayoutTests/imported/w3c:

Patch by Sam Weinig <sam@webkit.org> on 2017-05-07
Reviewed by Daniel Bates.

  • web-platform-tests/html/dom/reflection-metadata-expected.txt:
  • web-platform-tests/html/dom/reflection-misc-expected.txt:

Update results now that we support the reflected 'integrity' property.

Source/WebCore:

<rdar://problem/18945879>

Patch by Sam Weinig <sam@webkit.org> on 2017-05-07
Reviewed by Daniel Bates.

Tests: http/tests/subresource-integrity/sri-disabled-with-setting.html

http/tests/subresource-integrity/sri-enabled-with-setting.html
http/tests/subresource-integrity/sri-script-cors.html
http/tests/subresource-integrity/sri-style-cors.html

  • CMakeLists.txt:
  • WebCore.xcodeproj/project.pbxproj:

Add new files.

  • dom/LoadableClassicScript.cpp:

(WebCore::LoadableClassicScript::create):
(WebCore::LoadableClassicScript::notifyFinished):

  • dom/LoadableClassicScript.h:
  • dom/LoadableScript.h:
  • dom/ScriptElement.cpp:

(WebCore::ScriptElement::requestClassicScript):
Store integrity metadata in the script fetcher so it can be passed to
the checked when script load finishes.

  • html/HTMLAttributeNames.in:

Add 'integrity'.

  • html/HTMLLinkElement.cpp:

(WebCore::HTMLLinkElement::process):
When requesting a stylesheet, cache the integrity metadata so it can
be used when the load completes (accessing the attribute at load completion
time is incorrect, as a script might have changed the attributes value since
the request was made).

(WebCore::HTMLLinkElement::setCSSStyleSheet):
Add an integrity check using the cached integrity metadata when a load
finishes.

  • html/HTMLLinkElement.h:

Add cached integrity metadata member.

  • html/HTMLLinkElement.idl:
  • html/HTMLScriptElement.idl:

Add integrity property.

  • html/parser/HTMLParserIdioms.h:

(WebCore::isNotHTMLSpace):
Templatize isNotHTMLSpace so it can work for both UChar and LChar.

  • loader/ResourceCryptographicDigest.cpp:

(WebCore::parseCryptographicDigestImpl):
(WebCore::parseEncodedCryptographicDigestImpl):
(WebCore::parseEncodedCryptographicDigest):
(WebCore::decodeEncodedResourceCryptographicDigest):

  • loader/ResourceCryptographicDigest.h:

Add concept of an encoded digest to more closely model the spec so that hashes
that match the grammar but are invalid (say, mixing base64 and base64URL) make
it through the algorithm longer, and don't cause us to load something that should
be blocked.

  • loader/SubresourceIntegrity.cpp: Added.
  • loader/SubresourceIntegrity.h: Added.

Add implementation of Subresource Integrity metadata validation allowing
for a CachedResource and integrity metadata to be passed for validation.

  • page/Settings.in:

Add setting for Subresource Integrity, defaulted to enabled.

LayoutTests:

<rdar://problem/18945879>

Patch by Sam Weinig <sam@webkit.org> on 2017-05-07
Reviewed by Daniel Bates.

Add tests for Subresource Integrity based off the ones from Web
Platform Tests. They have been changed to:

  • Split <link> and <script> testing.
  • Add additional tests:
    • Integrity hashes using base64URL encoding.
    • Integrity hashes using mixed base64 and base64URL encoding.
    • Integrity metadata that does not conform to the grammar at all.
    • Multiple valid, but only one matching, integrity hashes.
    • Non-matching integrity hash with options.
  • Run one at a time, so console output is consistent.

We can/should upstream these changes, but this avoids the possibility that
an update of the imported web-platform-tests could cause these tests to fail.

Also adds tests that show the Subresource Integrity setting works correctly.

  • http/tests/subresource-integrity: Added.
  • http/tests/subresource-integrity/.htaccess: Added.
  • http/tests/subresource-integrity/resources: Added.
  • http/tests/subresource-integrity/resources/alternate.css: Added.
  • http/tests/subresource-integrity/resources/crossorigin-anon-script.js: Added.
  • http/tests/subresource-integrity/resources/crossorigin-anon-style.css: Added.
  • http/tests/subresource-integrity/resources/crossorigin-creds-script.js: Added.
  • http/tests/subresource-integrity/resources/crossorigin-creds-style.css: Added.
  • http/tests/subresource-integrity/resources/crossorigin-ineligible-script.js: Added.
  • http/tests/subresource-integrity/resources/crossorigin-ineligible-style.css: Added.
  • http/tests/subresource-integrity/resources/matching-digest.js: Added.
  • http/tests/subresource-integrity/resources/non-matching-digest.js: Added.
  • http/tests/subresource-integrity/resources/sri-utilities.js: Added.
  • http/tests/subresource-integrity/resources/style.css: Added.
  • http/tests/subresource-integrity/sri-disabled-with-setting-expected.txt: Added.
  • http/tests/subresource-integrity/sri-disabled-with-setting.html: Added.
  • http/tests/subresource-integrity/sri-enabled-with-setting-expected.txt: Added.
  • http/tests/subresource-integrity/sri-enabled-with-setting.html: Added.
  • http/tests/subresource-integrity/sri-script-expected.txt: Added.
  • http/tests/subresource-integrity/sri-script.html: Added.
  • http/tests/subresource-integrity/sri-style-expected.txt: Added.
  • http/tests/subresource-integrity/sri-style.html: Added.
Location:
trunk
Files:
24 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r216342 r216347  
     12017-05-07  Sam Weinig  <sam@webkit.org>
     2
     3        Implement Subresource Integrity (SRI)
     4        https://bugs.webkit.org/show_bug.cgi?id=148363
     5        <rdar://problem/18945879>
     6
     7        Reviewed by Daniel Bates.
     8
     9        Add tests for Subresource Integrity based off the ones from Web
     10        Platform Tests. They have been changed to:
     11        - Split <link> and <script> testing.
     12        - Add additional tests:
     13            - Integrity hashes using base64URL encoding.
     14            - Integrity hashes using mixed base64 and base64URL encoding.
     15            - Integrity metadata that does not conform to the grammar at all.
     16            - Multiple valid, but only one matching, integrity hashes.
     17            - Non-matching integrity hash with options.
     18        - Run one at a time, so console output is consistent.
     19       
     20        We can/should upstream these changes, but this avoids the possibility that
     21        an update of the imported web-platform-tests could cause these tests to fail.
     22       
     23        Also adds tests that show the Subresource Integrity setting works correctly.
     24
     25        * http/tests/subresource-integrity: Added.
     26        * http/tests/subresource-integrity/.htaccess: Added.
     27        * http/tests/subresource-integrity/resources: Added.
     28        * http/tests/subresource-integrity/resources/alternate.css: Added.
     29        * http/tests/subresource-integrity/resources/crossorigin-anon-script.js: Added.
     30        * http/tests/subresource-integrity/resources/crossorigin-anon-style.css: Added.
     31        * http/tests/subresource-integrity/resources/crossorigin-creds-script.js: Added.
     32        * http/tests/subresource-integrity/resources/crossorigin-creds-style.css: Added.
     33        * http/tests/subresource-integrity/resources/crossorigin-ineligible-script.js: Added.
     34        * http/tests/subresource-integrity/resources/crossorigin-ineligible-style.css: Added.
     35        * http/tests/subresource-integrity/resources/matching-digest.js: Added.
     36        * http/tests/subresource-integrity/resources/non-matching-digest.js: Added.
     37        * http/tests/subresource-integrity/resources/sri-utilities.js: Added.
     38        * http/tests/subresource-integrity/resources/style.css: Added.
     39        * http/tests/subresource-integrity/sri-disabled-with-setting-expected.txt: Added.
     40        * http/tests/subresource-integrity/sri-disabled-with-setting.html: Added.
     41        * http/tests/subresource-integrity/sri-enabled-with-setting-expected.txt: Added.
     42        * http/tests/subresource-integrity/sri-enabled-with-setting.html: Added.
     43        * http/tests/subresource-integrity/sri-script-expected.txt: Added.
     44        * http/tests/subresource-integrity/sri-script.html: Added.
     45        * http/tests/subresource-integrity/sri-style-expected.txt: Added.
     46        * http/tests/subresource-integrity/sri-style.html: Added.
     47
    1482017-05-06  Myles C. Maxfield  <mmaxfield@apple.com>
    249
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r216195 r216347  
     12017-05-07  Sam Weinig  <sam@webkit.org>
     2
     3        Implement Subresource Integrity (SRI)
     4        https://bugs.webkit.org/show_bug.cgi?id=148363
     5
     6        Reviewed by Daniel Bates.
     7
     8        * web-platform-tests/html/dom/reflection-metadata-expected.txt:
     9        * web-platform-tests/html/dom/reflection-misc-expected.txt:
     10        Update results now that we support the reflected 'integrity' property.
     11
    1122017-05-04  Daniel Bates  <dabates@apple.com>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/dom/reflection-metadata-expected.txt

    r210823 r216347  
    12081208PASS link.nonce: IDL set to object "test-toString"
    12091209PASS link.nonce: IDL set to object "test-valueOf"
    1210 FAIL link.integrity: typeof IDL attribute assert_equals: expected "string" but got "undefined"
    1211 FAIL link.integrity: IDL get with DOM attribute unset assert_equals: expected (string) "" but got (undefined) undefined
    1212 FAIL link.integrity: setAttribute() to "" assert_equals: IDL get expected (string) "" but got (undefined) undefined
    1213 FAIL link.integrity: setAttribute() to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " assert_equals: IDL get expected (string) " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " but got (undefined) undefined
    1214 FAIL link.integrity: setAttribute() to undefined assert_equals: IDL get expected (string) "undefined" but got (undefined) undefined
    1215 FAIL link.integrity: setAttribute() to 7 assert_equals: IDL get expected (string) "7" but got (undefined) undefined
    1216 FAIL link.integrity: setAttribute() to 1.5 assert_equals: IDL get expected (string) "1.5" but got (undefined) undefined
    1217 FAIL link.integrity: setAttribute() to true assert_equals: IDL get expected (string) "true" but got (undefined) undefined
    1218 FAIL link.integrity: setAttribute() to false assert_equals: IDL get expected (string) "false" but got (undefined) undefined
    1219 FAIL link.integrity: setAttribute() to object "[object Object]" assert_equals: IDL get expected (string) "[object Object]" but got (undefined) undefined
    1220 FAIL link.integrity: setAttribute() to NaN assert_equals: IDL get expected (string) "NaN" but got (undefined) undefined
    1221 FAIL link.integrity: setAttribute() to Infinity assert_equals: IDL get expected (string) "Infinity" but got (undefined) undefined
    1222 FAIL link.integrity: setAttribute() to -Infinity assert_equals: IDL get expected (string) "-Infinity" but got (undefined) undefined
    1223 FAIL link.integrity: setAttribute() to "\0" assert_equals: IDL get expected (string) "\0" but got (undefined) undefined
    1224 FAIL link.integrity: setAttribute() to null assert_equals: IDL get expected (string) "null" but got (undefined) undefined
    1225 FAIL link.integrity: setAttribute() to object "test-toString" assert_equals: IDL get expected (string) "test-toString" but got (undefined) undefined
    1226 FAIL link.integrity: setAttribute() to object "test-valueOf" assert_equals: IDL get expected (string) "test-valueOf" but got (undefined) undefined
    1227 FAIL link.integrity: IDL set to "" assert_equals: getAttribute() expected "" but got "test-valueOf"
    1228 FAIL link.integrity: IDL set to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " assert_equals: getAttribute() expected " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " but got "test-valueOf"
    1229 FAIL link.integrity: IDL set to undefined assert_equals: getAttribute() expected "undefined" but got "test-valueOf"
    1230 FAIL link.integrity: IDL set to 7 assert_equals: getAttribute() expected "7" but got "test-valueOf"
    1231 FAIL link.integrity: IDL set to 1.5 assert_equals: getAttribute() expected "1.5" but got "test-valueOf"
    1232 FAIL link.integrity: IDL set to true assert_equals: getAttribute() expected "true" but got "test-valueOf"
    1233 FAIL link.integrity: IDL set to false assert_equals: getAttribute() expected "false" but got "test-valueOf"
    1234 FAIL link.integrity: IDL set to object "[object Object]" assert_equals: getAttribute() expected "[object Object]" but got "test-valueOf"
    1235 FAIL link.integrity: IDL set to NaN assert_equals: getAttribute() expected "NaN" but got "test-valueOf"
    1236 FAIL link.integrity: IDL set to Infinity assert_equals: getAttribute() expected "Infinity" but got "test-valueOf"
    1237 FAIL link.integrity: IDL set to -Infinity assert_equals: getAttribute() expected "-Infinity" but got "test-valueOf"
    1238 FAIL link.integrity: IDL set to "\0" assert_equals: getAttribute() expected "\0" but got "test-valueOf"
    1239 FAIL link.integrity: IDL set to null assert_equals: getAttribute() expected "null" but got "test-valueOf"
    1240 FAIL link.integrity: IDL set to object "test-toString" assert_equals: getAttribute() expected "test-toString" but got "test-valueOf"
    1241 FAIL link.integrity: IDL set to object "test-valueOf" assert_equals: IDL get expected (string) "test-valueOf" but got (object) object "test-valueOf"
     1210PASS link.integrity: typeof IDL attribute
     1211PASS link.integrity: IDL get with DOM attribute unset
     1212PASS link.integrity: setAttribute() to ""
     1213PASS link.integrity: setAttribute() to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo "
     1214PASS link.integrity: setAttribute() to undefined
     1215PASS link.integrity: setAttribute() to 7
     1216PASS link.integrity: setAttribute() to 1.5
     1217PASS link.integrity: setAttribute() to true
     1218PASS link.integrity: setAttribute() to false
     1219PASS link.integrity: setAttribute() to object "[object Object]"
     1220PASS link.integrity: setAttribute() to NaN
     1221PASS link.integrity: setAttribute() to Infinity
     1222PASS link.integrity: setAttribute() to -Infinity
     1223PASS link.integrity: setAttribute() to "\0"
     1224PASS link.integrity: setAttribute() to null
     1225PASS link.integrity: setAttribute() to object "test-toString"
     1226PASS link.integrity: setAttribute() to object "test-valueOf"
     1227PASS link.integrity: IDL set to ""
     1228PASS link.integrity: IDL set to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo "
     1229PASS link.integrity: IDL set to undefined
     1230PASS link.integrity: IDL set to 7
     1231PASS link.integrity: IDL set to 1.5
     1232PASS link.integrity: IDL set to true
     1233PASS link.integrity: IDL set to false
     1234PASS link.integrity: IDL set to object "[object Object]"
     1235PASS link.integrity: IDL set to NaN
     1236PASS link.integrity: IDL set to Infinity
     1237PASS link.integrity: IDL set to -Infinity
     1238PASS link.integrity: IDL set to "\0"
     1239PASS link.integrity: IDL set to null
     1240PASS link.integrity: IDL set to object "test-toString"
     1241PASS link.integrity: IDL set to object "test-valueOf"
    12421242PASS link.hreflang: typeof IDL attribute
    12431243PASS link.hreflang: IDL get with DOM attribute unset
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/dom/reflection-misc-expected.txt

    r212202 r216347  
    780780PASS script.nonce: IDL set to object "test-toString"
    781781PASS script.nonce: IDL set to object "test-valueOf"
    782 FAIL script.integrity: typeof IDL attribute assert_equals: expected "string" but got "undefined"
    783 FAIL script.integrity: IDL get with DOM attribute unset assert_equals: expected (string) "" but got (undefined) undefined
    784 FAIL script.integrity: setAttribute() to "" assert_equals: IDL get expected (string) "" but got (undefined) undefined
    785 FAIL script.integrity: setAttribute() to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " assert_equals: IDL get expected (string) " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " but got (undefined) undefined
    786 FAIL script.integrity: setAttribute() to undefined assert_equals: IDL get expected (string) "undefined" but got (undefined) undefined
    787 FAIL script.integrity: setAttribute() to 7 assert_equals: IDL get expected (string) "7" but got (undefined) undefined
    788 FAIL script.integrity: setAttribute() to 1.5 assert_equals: IDL get expected (string) "1.5" but got (undefined) undefined
    789 FAIL script.integrity: setAttribute() to true assert_equals: IDL get expected (string) "true" but got (undefined) undefined
    790 FAIL script.integrity: setAttribute() to false assert_equals: IDL get expected (string) "false" but got (undefined) undefined
    791 FAIL script.integrity: setAttribute() to object "[object Object]" assert_equals: IDL get expected (string) "[object Object]" but got (undefined) undefined
    792 FAIL script.integrity: setAttribute() to NaN assert_equals: IDL get expected (string) "NaN" but got (undefined) undefined
    793 FAIL script.integrity: setAttribute() to Infinity assert_equals: IDL get expected (string) "Infinity" but got (undefined) undefined
    794 FAIL script.integrity: setAttribute() to -Infinity assert_equals: IDL get expected (string) "-Infinity" but got (undefined) undefined
    795 FAIL script.integrity: setAttribute() to "\0" assert_equals: IDL get expected (string) "\0" but got (undefined) undefined
    796 FAIL script.integrity: setAttribute() to null assert_equals: IDL get expected (string) "null" but got (undefined) undefined
    797 FAIL script.integrity: setAttribute() to object "test-toString" assert_equals: IDL get expected (string) "test-toString" but got (undefined) undefined
    798 FAIL script.integrity: setAttribute() to object "test-valueOf" assert_equals: IDL get expected (string) "test-valueOf" but got (undefined) undefined
    799 FAIL script.integrity: IDL set to "" assert_equals: getAttribute() expected "" but got "test-valueOf"
    800 FAIL script.integrity: IDL set to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " assert_equals: getAttribute() expected " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo " but got "test-valueOf"
    801 FAIL script.integrity: IDL set to undefined assert_equals: getAttribute() expected "undefined" but got "test-valueOf"
    802 FAIL script.integrity: IDL set to 7 assert_equals: getAttribute() expected "7" but got "test-valueOf"
    803 FAIL script.integrity: IDL set to 1.5 assert_equals: getAttribute() expected "1.5" but got "test-valueOf"
    804 FAIL script.integrity: IDL set to true assert_equals: getAttribute() expected "true" but got "test-valueOf"
    805 FAIL script.integrity: IDL set to false assert_equals: getAttribute() expected "false" but got "test-valueOf"
    806 FAIL script.integrity: IDL set to object "[object Object]" assert_equals: getAttribute() expected "[object Object]" but got "test-valueOf"
    807 FAIL script.integrity: IDL set to NaN assert_equals: getAttribute() expected "NaN" but got "test-valueOf"
    808 FAIL script.integrity: IDL set to Infinity assert_equals: getAttribute() expected "Infinity" but got "test-valueOf"
    809 FAIL script.integrity: IDL set to -Infinity assert_equals: getAttribute() expected "-Infinity" but got "test-valueOf"
    810 FAIL script.integrity: IDL set to "\0" assert_equals: getAttribute() expected "\0" but got "test-valueOf"
    811 FAIL script.integrity: IDL set to null assert_equals: getAttribute() expected "null" but got "test-valueOf"
    812 FAIL script.integrity: IDL set to object "test-toString" assert_equals: getAttribute() expected "test-toString" but got "test-valueOf"
    813 FAIL script.integrity: IDL set to object "test-valueOf" assert_equals: IDL get expected (string) "test-valueOf" but got (object) object "test-valueOf"
     782PASS script.integrity: typeof IDL attribute
     783PASS script.integrity: IDL get with DOM attribute unset
     784PASS script.integrity: setAttribute() to ""
     785PASS script.integrity: setAttribute() to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo "
     786PASS script.integrity: setAttribute() to undefined
     787PASS script.integrity: setAttribute() to 7
     788PASS script.integrity: setAttribute() to 1.5
     789PASS script.integrity: setAttribute() to true
     790PASS script.integrity: setAttribute() to false
     791PASS script.integrity: setAttribute() to object "[object Object]"
     792PASS script.integrity: setAttribute() to NaN
     793PASS script.integrity: setAttribute() to Infinity
     794PASS script.integrity: setAttribute() to -Infinity
     795PASS script.integrity: setAttribute() to "\0"
     796PASS script.integrity: setAttribute() to null
     797PASS script.integrity: setAttribute() to object "test-toString"
     798PASS script.integrity: setAttribute() to object "test-valueOf"
     799PASS script.integrity: IDL set to ""
     800PASS script.integrity: IDL set to " \0\x01\x02\x03\x04\x05\x06\x07 \b\t\n\v\f\r\x0e\x0f \x10\x11\x12\x13\x14\x15\x16\x17 \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f  foo "
     801PASS script.integrity: IDL set to undefined
     802PASS script.integrity: IDL set to 7
     803PASS script.integrity: IDL set to 1.5
     804PASS script.integrity: IDL set to true
     805PASS script.integrity: IDL set to false
     806PASS script.integrity: IDL set to object "[object Object]"
     807PASS script.integrity: IDL set to NaN
     808PASS script.integrity: IDL set to Infinity
     809PASS script.integrity: IDL set to -Infinity
     810PASS script.integrity: IDL set to "\0"
     811PASS script.integrity: IDL set to null
     812PASS script.integrity: IDL set to object "test-toString"
     813PASS script.integrity: IDL set to object "test-valueOf"
    814814PASS script.event: typeof IDL attribute
    815815PASS script.event: IDL get with DOM attribute unset
  • trunk/Source/WebCore/CMakeLists.txt

    r216234 r216347  
    19741974    loader/SinkDocument.cpp
    19751975    loader/SubframeLoader.cpp
     1976    loader/SubresourceIntegrity.cpp
    19761977    loader/SubresourceLoader.cpp
    19771978    loader/TextResourceDecoder.cpp
  • trunk/Source/WebCore/ChangeLog

    r216343 r216347  
     12017-05-07  Sam Weinig  <sam@webkit.org>
     2
     3        Implement Subresource Integrity (SRI)
     4        https://bugs.webkit.org/show_bug.cgi?id=148363
     5        <rdar://problem/18945879>
     6
     7        Reviewed by Daniel Bates.
     8
     9        Tests: http/tests/subresource-integrity/sri-disabled-with-setting.html
     10               http/tests/subresource-integrity/sri-enabled-with-setting.html
     11               http/tests/subresource-integrity/sri-script-cors.html
     12               http/tests/subresource-integrity/sri-style-cors.html
     13
     14        * CMakeLists.txt:
     15        * WebCore.xcodeproj/project.pbxproj:
     16        Add new files.
     17
     18        * dom/LoadableClassicScript.cpp:
     19        (WebCore::LoadableClassicScript::create):
     20        (WebCore::LoadableClassicScript::notifyFinished):
     21        * dom/LoadableClassicScript.h:
     22        * dom/LoadableScript.h:
     23        * dom/ScriptElement.cpp:
     24        (WebCore::ScriptElement::requestClassicScript):
     25        Store integrity metadata in the script fetcher so it can be passed to
     26        the checked when script load finishes.
     27
     28        * html/HTMLAttributeNames.in:
     29        Add 'integrity'.
     30
     31        * html/HTMLLinkElement.cpp:
     32        (WebCore::HTMLLinkElement::process):
     33        When requesting a stylesheet, cache the integrity metadata so it can
     34        be used when the load completes (accessing the attribute at load completion
     35        time is incorrect, as a script might have changed the attributes value since
     36        the request was made).
     37
     38        (WebCore::HTMLLinkElement::setCSSStyleSheet):
     39        Add an integrity check using the cached integrity metadata when a load
     40        finishes.
     41
     42        * html/HTMLLinkElement.h:
     43        Add cached integrity metadata member.
     44
     45        * html/HTMLLinkElement.idl:
     46        * html/HTMLScriptElement.idl:
     47        Add integrity property.
     48
     49        * html/parser/HTMLParserIdioms.h:
     50        (WebCore::isNotHTMLSpace):
     51        Templatize isNotHTMLSpace so it can work for both UChar and LChar.
     52
     53        * loader/ResourceCryptographicDigest.cpp:
     54        (WebCore::parseCryptographicDigestImpl):
     55        (WebCore::parseEncodedCryptographicDigestImpl):
     56        (WebCore::parseEncodedCryptographicDigest):
     57        (WebCore::decodeEncodedResourceCryptographicDigest):
     58        * loader/ResourceCryptographicDigest.h:
     59        Add concept of an encoded digest to more closely model the spec so that hashes
     60        that match the grammar but are invalid (say, mixing base64 and base64URL) make
     61        it through the algorithm longer, and don't cause us to load something that should
     62        be blocked.
     63
     64        * loader/SubresourceIntegrity.cpp: Added.
     65        * loader/SubresourceIntegrity.h: Added.
     66        Add implementation of Subresource Integrity metadata validation allowing
     67        for a CachedResource and integrity metadata to be passed for validation.
     68
     69        * page/Settings.in:
     70        Add setting for Subresource Integrity, defaulted to enabled.
     71
    1722017-05-07  Michael Catanzaro  <mcatanzaro@igalia.com>
    273
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r216234 r216347  
    32413241                7CE9A12B1EA2F1DB00651AD1 /* IDLAttributes.json in Headers */ = {isa = PBXBuildFile; fileRef = A83B533814F399BB00720D9D /* IDLAttributes.json */; settings = {ATTRIBUTES = (Private, ); }; };
    32423242                7CEF26191D6A931700BE905D /* JSCryptoCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CEF26181D6A92E300BE905D /* JSCryptoCustom.cpp */; };
     3243                7CF1589B1EBC4CFD00D4BFB7 /* SubresourceIntegrity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CF158991EBBCDC700D4BFB7 /* SubresourceIntegrity.cpp */; };
    32433244                7CF930E71E01F9B400BAFFBE /* PaymentHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF930E61E01F9AD00BAFFBE /* PaymentHeaders.h */; settings = {ATTRIBUTES = (Private, ); }; };
    32443245                7CFDC57C1AC1D80500E24A57 /* ContentExtensionError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CFDC57A1AC1D80500E24A57 /* ContentExtensionError.cpp */; };
     
    1126911270                7CE6CBFC187F394900D46BF5 /* FormatConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatConverter.cpp; sourceTree = "<group>"; };
    1127011271                7CEF26181D6A92E300BE905D /* JSCryptoCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCryptoCustom.cpp; sourceTree = "<group>"; };
     11272                7CF158991EBBCDC700D4BFB7 /* SubresourceIntegrity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SubresourceIntegrity.cpp; sourceTree = "<group>"; };
     11273                7CF1589A1EBBCDC700D4BFB7 /* SubresourceIntegrity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubresourceIntegrity.h; sourceTree = "<group>"; };
    1127111274                7CF930E61E01F9AD00BAFFBE /* PaymentHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PaymentHeaders.h; sourceTree = "<group>"; };
    1127211275                7CFDC57A1AC1D80500E24A57 /* ContentExtensionError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionError.cpp; sourceTree = "<group>"; };
     
    2380223805                                D000ED2511C1B9CD00C47726 /* SubframeLoader.cpp */,
    2380323806                                D000ED2611C1B9CD00C47726 /* SubframeLoader.h */,
     23807                                7CF158991EBBCDC700D4BFB7 /* SubresourceIntegrity.cpp */,
     23808                                7CF1589A1EBBCDC700D4BFB7 /* SubresourceIntegrity.h */,
    2380423809                                93E227DF0AF589AD00D48324 /* SubresourceLoader.cpp */,
    2380523810                                656D37300ADBA5DE00A4554D /* SubresourceLoader.h */,
     
    3186231867                                511EF2D117F0FDF100E4FA16 /* JSIDBObjectStoreCustom.cpp in Sources */,
    3186331868                                511EF2C817F0FD3500E4FA16 /* JSIDBOpenDBRequest.cpp in Sources */,
     31869                                7CF1589B1EBC4CFD00D4BFB7 /* SubresourceIntegrity.cpp in Sources */,
    3186431870                                511EF2C917F0FD3500E4FA16 /* JSIDBRequest.cpp in Sources */,
    3186531871                                511EF2CA17F0FD3500E4FA16 /* JSIDBTransaction.cpp in Sources */,
  • trunk/Source/WebCore/dom/LoadableClassicScript.cpp

    r216217 r216347  
    2929#include "ScriptElement.h"
    3030#include "ScriptSourceCode.h"
     31#include "SubresourceIntegrity.h"
    3132#include <wtf/NeverDestroyed.h>
    3233#include <wtf/text/StringImpl.h>
     
    3435namespace WebCore {
    3536
    36 Ref<LoadableClassicScript> LoadableClassicScript::create(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
     37Ref<LoadableClassicScript> LoadableClassicScript::create(const String& nonce, const String& integrityMetadata, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
    3738{
    38     return adoptRef(*new LoadableClassicScript(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree));
     39    return adoptRef(*new LoadableClassicScript(nonce, integrityMetadata, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree));
    3940}
    4041
     
    9798#endif
    9899
     100    if (!m_error && !resource.errorOccurred() && !matchIntegrityMetadata(resource, m_integrity)) {
     101        m_error = Error {
     102            ErrorType::FailedIntegrityCheck,
     103            ConsoleMessage { MessageSource::Security, MessageLevel::Error, makeString("Cannot load script ", m_cachedScript->url().stringCenterEllipsizedToLength(), ". Failed integrity metadata check.") }
     104        };
     105    }
     106
    99107    notifyClientFinished();
    100108}
  • trunk/Source/WebCore/dom/LoadableClassicScript.h

    r211280 r216347  
    4242    virtual ~LoadableClassicScript();
    4343
    44     static Ref<LoadableClassicScript> create(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree);
     44    static Ref<LoadableClassicScript> create(const String& nonce, const String& integrity, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree);
    4545    bool isLoaded() const final;
    4646    std::optional<Error> error() const final;
     
    5757
    5858private:
    59     LoadableClassicScript(const String& nonce, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
     59    LoadableClassicScript(const String& nonce, const String& integrity, const String& crossOriginMode, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
    6060        : LoadableScript(nonce, crossOriginMode, charset, initiatorName, isInUserAgentShadowTree)
     61        , m_integrity(integrity)
    6162    {
    6263    }
     
    6667    CachedResourceHandle<CachedScript> m_cachedScript { };
    6768    std::optional<Error> m_error { std::nullopt };
     69    String m_integrity;
    6870};
    6971
  • trunk/Source/WebCore/dom/LoadableScript.h

    r211280 r216347  
    4343        CrossOriginLoad,
    4444        Nosniff,
     45        FailedIntegrityCheck,
    4546    };
    4647
  • trunk/Source/WebCore/dom/ScriptElement.cpp

    r211965 r216347  
    4949#include "ScriptSourceCode.h"
    5050#include "ScriptableDocumentParser.h"
     51#include "Settings.h"
    5152#include "TextNodeTraversal.h"
    5253#include <wtf/StdLibExtras.h>
     
    295296        auto script = LoadableClassicScript::create(
    296297            m_element.attributeWithoutSynchronization(HTMLNames::nonceAttr),
     298            m_element.document().settings().subresourceIntegrityEnabled() ? m_element.attributeWithoutSynchronization(HTMLNames::integrityAttr).string() : emptyString(),
    297299            m_element.attributeWithoutSynchronization(HTMLNames::crossoriginAttr),
    298300            scriptCharset(),
  • trunk/Source/WebCore/html/HTMLAttributeNames.in

    r215989 r216347  
    139139incremental
    140140indeterminate
     141integrity
    141142is
    142143ismap
  • trunk/Source/WebCore/html/HTMLLinkElement.cpp

    r215816 r216347  
    5555#include "StyleScope.h"
    5656#include "StyleSheetContents.h"
     57#include "SubresourceIntegrity.h"
    5758#include <wtf/Ref.h>
    5859#include <wtf/SetForScope.h>
     
    240241    if (m_disabledState != Disabled && treatAsStyleSheet && document().frame() && url.isValid()) {
    241242        String charset = attributeWithoutSynchronization(charsetAttr);
    242         if (charset.isEmpty() && document().frame())
     243        if (charset.isEmpty())
    243244            charset = document().charset();
    244245
     
    276277            priority = ResourceLoadPriority::VeryLow;
    277278
     279        if (document().settings().subresourceIntegrityEnabled())
     280            m_integrityMetadataForPendingSheetRequest = attributeWithoutSynchronization(HTMLNames::integrityAttr);
     281
    278282        ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
    279283        options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set;
     
    283287        CachedResourceRequest request(url, options, priority, WTFMove(charset));
    284288        request.setInitiator(*this);
    285 
    286289        request.setAsPotentiallyCrossOrigin(crossOrigin(), document());
    287290
     
    294297            // The request may have been denied if (for example) the stylesheet is local and the document is remote.
    295298            m_loading = false;
    296             removePendingSheet();
     299            sheetLoaded();
     300            notifyLoadedSheetAndAllCriticalSubresources(false);
    297301        }
    298302    } else if (m_sheet) {
     
    343347        m_styleScope = nullptr;
    344348    }
    345 
    346349}
    347350
     
    376379    // Completing the sheet load may cause scripts to execute.
    377380    Ref<HTMLLinkElement> protectedThis(*this);
     381
     382    if (!cachedStyleSheet->errorOccurred() && !matchIntegrityMetadata(*cachedStyleSheet, m_integrityMetadataForPendingSheetRequest)) {
     383        document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, makeString("Cannot load stylesheet ", cachedStyleSheet->url().stringCenterEllipsizedToLength(), ". Failed integrity metadata check."));
     384
     385        m_loading = false;
     386        sheetLoaded();
     387        notifyLoadedSheetAndAllCriticalSubresources(true);
     388        return;
     389    }
    378390
    379391    CSSParserContext parserContext(document(), baseURL, charset);
  • trunk/Source/WebCore/html/HTMLLinkElement.h

    r214378 r216347  
    136136
    137137    PendingSheetType m_pendingSheetType;
     138    String m_integrityMetadataForPendingSheetRequest;
    138139
    139140    std::unique_ptr<DOMTokenList> m_relList;
    140141};
    141142
    142 } //namespace
     143}
  • trunk/Source/WebCore/html/HTMLLinkElement.idl

    r209644 r216347  
    4343
    4444    [Reflect] attribute DOMString nonce;
     45    [Reflect, EnabledBySetting=SubresourceIntegrity] attribute DOMString integrity;
    4546};
    4647
  • trunk/Source/WebCore/html/HTMLScriptElement.idl

    r211078 r216347  
    3131    [Reflect] attribute DOMString nonce;
    3232    [Reflect] attribute boolean noModule;
     33    [Reflect, EnabledBySetting=SubresourceIntegrity] attribute DOMString integrity;
    3334};
  • trunk/Source/WebCore/html/parser/HTMLParserIdioms.h

    r215914 r216347  
    3939// Space characters as defined by the HTML specification.
    4040template<typename CharacterType> bool isHTMLSpace(CharacterType);
     41template<typename CharacterType> bool isNotHTMLSpace(CharacterType);
    4142template<typename CharacterType> bool isComma(CharacterType);
    4243template<typename CharacterType> bool isHTMLSpaceOrComma(CharacterType);
    4344bool isHTMLLineBreak(UChar);
    44 bool isNotHTMLSpace(UChar);
    4545bool isHTMLSpaceButNotLineBreak(UChar);
    4646
     
    107107}
    108108
     109template<typename CharacterType> inline bool isNotHTMLSpace(CharacterType character)
     110{
     111    return !isHTMLSpace(character);
     112}
     113
    109114inline bool isHTMLLineBreak(UChar character)
    110115{
     
    120125{
    121126    return isComma(character) || isHTMLSpace(character);
    122 }
    123 
    124 inline bool isNotHTMLSpace(UChar character)
    125 {
    126     return !isHTMLSpace(character);
    127127}
    128128
  • trunk/Source/WebCore/loader/ResourceCryptographicDigest.cpp

    r215646 r216347  
    2727#include "ResourceCryptographicDigest.h"
    2828
    29 #include "CachedResource.h"
    30 #include "HTMLParserIdioms.h"
    3129#include "ParsingUtilities.h"
    32 #include "SharedBuffer.h"
    3330#include <pal/crypto/CryptoDigest.h>
    3431#include <wtf/text/Base64.h>
     
    5956
    6057template<typename CharacterType>
    61 std::optional<ResourceCryptographicDigest> parseCryptographicDigestImpl(const CharacterType*& position, const CharacterType* end)
     58static std::optional<ResourceCryptographicDigest> parseCryptographicDigestImpl(const CharacterType*& position, const CharacterType* end)
    6259{
    6360    if (position == end)
     
    9996}
    10097
     98template<typename CharacterType>
     99static std::optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigestImpl(const CharacterType*& position, const CharacterType* end)
     100{
     101    if (position == end)
     102        return std::nullopt;
     103
     104    EncodedResourceCryptographicDigest::Algorithm algorithm;
     105    if (!parseHashAlgorithmAdvancingPosition(position, end, algorithm))
     106        return std::nullopt;
     107
     108    if (!skipExactly<CharacterType>(position, end, '-'))
     109        return std::nullopt;
     110
     111    const CharacterType* beginHashValue = position;
     112    skipWhile<CharacterType, isBase64OrBase64URLCharacter>(position, end);
     113    skipExactly<CharacterType>(position, end, '=');
     114    skipExactly<CharacterType>(position, end, '=');
     115
     116    if (position == beginHashValue)
     117        return std::nullopt;
     118
     119    return EncodedResourceCryptographicDigest { algorithm, String(beginHashValue, position - beginHashValue) };
     120}
     121
     122std::optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const UChar*& begin, const UChar* end)
     123{
     124    return parseEncodedCryptographicDigestImpl(begin, end);
     125}
     126
     127std::optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const LChar*& begin, const LChar* end)
     128{
     129    return parseEncodedCryptographicDigestImpl(begin, end);
     130}
     131
     132std::optional<ResourceCryptographicDigest> decodeEncodedResourceCryptographicDigest(const EncodedResourceCryptographicDigest& encodedDigest)
     133{
     134    Vector<uint8_t> digest;
     135    if (!base64Decode(encodedDigest.digest, digest, Base64ValidatePadding)) {
     136        if (!base64URLDecode(encodedDigest.digest, digest))
     137            return std::nullopt;
     138    }
     139
     140    return ResourceCryptographicDigest { encodedDigest.algorithm, WTFMove(digest) };
     141}
     142
    101143static PAL::CryptoDigest::Algorithm toCryptoDigestAlgorithm(ResourceCryptographicDigest::Algorithm algorithm)
    102144{
  • trunk/Source/WebCore/loader/ResourceCryptographicDigest.h

    r215646 r216347  
    6262};
    6363
     64struct EncodedResourceCryptographicDigest {
     65    using Algorithm = ResourceCryptographicDigest::Algorithm;
     66   
     67    Algorithm algorithm;
     68    String digest;
     69};
     70
    6471std::optional<ResourceCryptographicDigest> parseCryptographicDigest(const UChar*& begin, const UChar* end);
    6572std::optional<ResourceCryptographicDigest> parseCryptographicDigest(const LChar*& begin, const LChar* end);
     73
     74std::optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const UChar*& begin, const UChar* end);
     75std::optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const LChar*& begin, const LChar* end);
     76
     77std::optional<ResourceCryptographicDigest> decodeEncodedResourceCryptographicDigest(const EncodedResourceCryptographicDigest&);
    6678
    6779ResourceCryptographicDigest cryptographicDigestForBytes(ResourceCryptographicDigest::Algorithm, const char* bytes, size_t length);
  • trunk/Source/WebCore/page/Settings.in

    r216154 r216347  
    291291
    292292langAttributeAwareFormControlUIEnabled initial=false
     293
     294subresourceIntegrityEnabled initial=true
Note: See TracChangeset for help on using the changeset viewer.