Changeset 121883 in webkit
- Timestamp:
- Jul 4, 2012 11:45:37 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 11 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r121879 r121883 1 2012-07-04 Mike West <mkwst@chromium.org> 2 3 Implement the script-nonce Content Security Policy directive. 4 https://bugs.webkit.org/show_bug.cgi?id=89577 5 6 Reviewed by Adam Barth. 7 8 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-allowed-expected.txt: Added. 9 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-allowed.html: Added. 10 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-badnonce-expected.txt: Added. 11 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-badnonce.html: Added. 12 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-blocked-expected.txt: Added. 13 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-blocked.html: Added. 14 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-emptynonce-expected.txt: Added. 15 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-emptynonce.html: Added. 16 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-scriptsrc-blocked-expected.txt: Added. 17 * http/tests/security/contentSecurityPolicy/1.1/scriptnonce-scriptsrc-blocked.html: Added. 18 * http/tests/security/contentSecurityPolicy/resources/echo-script-src.pl: 19 Adding noncy goodness to the echo script. 20 * http/tests/security/contentSecurityPolicy/resources/multiple-iframe-test.js: 21 (test): 22 * platform/gtk/TestExpectations: 23 Skipping 1.1 tests on GTK (missed it in r121879). 24 1 25 2012-07-04 Mike West <mkwst@chromium.org> 2 26 -
trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/echo-script-src.pl
r78058 r121883 11 11 ($text, $replacement) = ($replacement, $text) if $cgi->param('should_run') eq 'no'; 12 12 13 my $nonce = ""; 14 if ($cgi->param('nonce') ne '') { 15 $nonce = "nonce='".$cgi->param('nonce')."'"; 16 } 17 18 13 19 print "<!DOCTYPE html>\n"; 14 20 print "<html>\n"; … … 17 23 print "$text\n"; 18 24 print "</div>\n"; 19 print "<script src=\"".$cgi->param('q')."\"></script>\n";25 print "<script $nonce src=\"".$cgi->param('q')."\"></script>\n"; 20 26 print "</body>\n"; 21 27 print "</html>\n"; -
trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/multiple-iframe-test.js
r120174 r121883 16 16 "&csp=" + escape(current[1]) + 17 17 "&q=" + baseURL + escape(current[2]); 18 if (current[3]) 19 iframe.src += "&nonce=" + escape(current[3]); 20 18 21 iframe.onload = test; 19 22 document.body.appendChild(iframe); -
trunk/LayoutTests/platform/gtk/TestExpectations
r121874 r121883 342 342 // Disable webaudio codec tests, including proprietary codecs. 343 343 BUGWK88794 SKIP : webaudio/codec-tests = PASS 344 345 // Content Security Policy 1.1 (ENABLE_CSP_NEXT) is not enabled 346 BUGWK85558 SKIP : http/tests/security/contentSecurityPolicy/1.1 = TEXT 344 347 345 348 ////////////////////////////////////////////////////////////////////////////////////////// -
trunk/Source/WebCore/ChangeLog
r121882 r121883 1 2012-07-04 Mike West <mkwst@chromium.org> 2 3 Implement the script-nonce Content Security Policy directive. 4 https://bugs.webkit.org/show_bug.cgi?id=89577 5 6 Reviewed by Adam Barth. 7 8 This patch implements the (experimental) script-nonce Content Security 9 Policy directive from the 1.1 spec, which allows for selective 10 execution of script by specifying a "nonce" attribute for the 11 script tag. Script is only loaded and executed if it both matches the 12 nonce and matches the script-src whitelist (if present). 13 14 The implementation is gated on the ENABLE_CSP_NEXT flag, which is 15 currently disabled for all ports other than Chromium. 16 17 Spec: https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#script-nonce--experimental 18 19 Tests: http/tests/security/contentSecurityPolicy/1.1/scriptnonce-allowed.html 20 http/tests/security/contentSecurityPolicy/1.1/scriptnonce-badnonce.html 21 http/tests/security/contentSecurityPolicy/1.1/scriptnonce-blocked.html 22 http/tests/security/contentSecurityPolicy/1.1/scriptnonce-emptynonce.html 23 http/tests/security/contentSecurityPolicy/1.1/scriptnonce-scriptsrc-blocked.html 24 25 * dom/ScriptElement.cpp: 26 (WebCore::ScriptElement::requestScript): 27 (WebCore::ScriptElement::executeScript): 28 Passing the nonce attribute through to check against CSP. 29 * html/HTMLAttributeNames.in: 30 * html/HTMLScriptElement.idl: 31 Adding the `nonce` attribute to the script tag. 32 * page/ContentSecurityPolicy.cpp: 33 (CSPDirectiveList): 34 (WebCore::CSPDirectiveList::logInvalidNonce): 35 (WebCore): 36 (WebCore::CSPDirectiveList::checkNonceAndReportViolation): 37 (WebCore::CSPDirectiveList::allowJavaScriptURLs): 38 (WebCore::CSPDirectiveList::allowInlineEventHandlers): 39 If a nonce is set, deny JavaScript URLs and inline event handlers. 40 (WebCore::CSPDirectiveList::allowScriptNonce): 41 (WebCore::CSPDirectiveList::parseScriptNonce): 42 (WebCore::CSPDirectiveList::addDirective): 43 (WebCore::isAllowedByAllWithNonce): 44 (WebCore::ContentSecurityPolicy::allowScriptNonce): 45 * page/ContentSecurityPolicy.h: 46 (WebCore): 47 1 48 2012-07-04 Gyuyoung Kim <gyuyoung.kim@samsung.com> 2 49 -
trunk/Source/WebCore/dom/ScriptElement.cpp
r118585 r121883 251 251 if (!m_element->inDocument() || m_element->document() != originalDocument) 252 252 return false; 253 if (!m_element->document()->contentSecurityPolicy()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr), m_element->document()->url(), m_startLineNumber, m_element->document()->completeURL(sourceUrl))) 254 return false; 253 255 254 256 ASSERT(!m_cachedScript); … … 280 282 281 283 if (sourceCode.isEmpty()) 284 return; 285 286 if (!m_element->document()->contentSecurityPolicy()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr), m_element->document()->url(), m_startLineNumber)) 282 287 return; 283 288 -
trunk/Source/WebCore/html/HTMLAttributeNames.in
r117662 r121883 159 159 name 160 160 nohref 161 nonce 161 162 noresize 162 163 noshade -
trunk/Source/WebCore/html/HTMLScriptElement.idl
r111359 r121883 30 30 attribute [Reflect] DOMString type; 31 31 attribute [Reflect] DOMString crossOrigin; 32 attribute [Reflect, Conditional=CSP_NEXT] DOMString nonce; 32 33 }; 33 34 } -
trunk/Source/WebCore/page/ContentSecurityPolicy.cpp
r120684 r121883 34 34 #include "InspectorInstrumentation.h" 35 35 #include "InspectorValues.h" 36 #include "KURL.h" 36 37 #include "PingLoader.h" 37 38 #include "SchemeRegistry.h" … … 551 552 bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine) const; 552 553 bool allowEval(PassRefPtr<ScriptCallStack>) const; 554 bool allowScriptNonce(const String& nonce, const String& contextURL, const WTF::OrdinalNumber& contextLine, const KURL&) const; 553 555 554 556 bool allowScriptFromSource(const KURL&) const; … … 568 570 bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value); 569 571 void parseReportURI(const String& name, const String& value); 572 void parseScriptNonce(const String& name, const String& value); 570 573 void addDirective(const String& name, const String& value); 571 574 void applySandboxPolicy(const String& name, const String& sandboxPolicy); … … 577 580 void logUnrecognizedDirective(const String& name) const; 578 581 void logDuplicateDirective(const String& name) const; 582 void logInvalidNonce(const String& nonce) const; 579 583 bool checkEval(CSPDirective*) const; 580 584 581 585 bool checkInlineAndReportViolation(CSPDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const; 586 bool checkNonceAndReportViolation(const String& nonce, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const; 582 587 bool checkEvalAndReportViolation(CSPDirective*, const String& consoleMessage, const String& contextURL = String(), const WTF::OrdinalNumber& contextLine = WTF::OrdinalNumber::beforeFirst(), PassRefPtr<ScriptCallStack> = 0) const; 583 588 bool checkSourceAndReportViolation(CSPDirective*, const KURL&, const String& type) const; … … 602 607 603 608 Vector<KURL> m_reportURIs; 609 String m_scriptNonce; 604 610 }; 605 611 … … 691 697 } 692 698 699 void CSPDirectiveList::logInvalidNonce(const String& nonce) const 700 { 701 String message = makeString("Ignoring invalid Content Security Policy script nonce: '", nonce, "'.\n"); 702 m_scriptExecutionContext->addConsoleMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message); 703 } 704 693 705 bool CSPDirectiveList::checkEval(CSPDirective* directive) const 694 706 { … … 706 718 return true; 707 719 reportViolation(directive->text(), consoleMessage + "\"" + directive->text() + "\".\n", KURL(), contextURL, contextLine); 720 return denyIfEnforcingPolicy(); 721 } 722 723 bool CSPDirectiveList::checkNonceAndReportViolation(const String& nonce, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine) const 724 { 725 if (m_scriptNonce.isEmpty() || nonce.stripWhiteSpace() == m_scriptNonce) 726 return true; 727 reportViolation(m_scriptNonce, consoleMessage + "\"script-nonce " + m_scriptNonce + "\".\n", KURL(), contextURL, contextLine); 708 728 return denyIfEnforcingPolicy(); 709 729 } … … 729 749 { 730 750 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: ")); 731 return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine); 751 return (checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine) 752 && checkNonceAndReportViolation(String(), consoleMessage, contextURL, contextLine)); 732 753 } 733 754 … … 735 756 { 736 757 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline event handler because it violates the following Content Security Policy directive: ")); 737 return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine); 758 return (checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine) 759 && checkNonceAndReportViolation(String(), consoleMessage, contextURL, contextLine)); 738 760 } 739 761 … … 754 776 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate script because it violates the following Content Security Policy directive: ")); 755 777 return checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, String(), WTF::OrdinalNumber::beforeFirst(), callStack); 778 } 779 780 bool CSPDirectiveList::allowScriptNonce(const String& nonce, const String& contextURL, const WTF::OrdinalNumber& contextLine, const KURL& url) const 781 { 782 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute script because it violates the following Content Security Policy directive: ")); 783 if (url.isEmpty()) 784 return checkNonceAndReportViolation(nonce, consoleMessage, contextURL, contextLine); 785 return checkNonceAndReportViolation(nonce, "Refused to load '" + url.string() + "' because it violates the following Content Security Policy directive: ", contextURL, contextLine); 756 786 } 757 787 … … 899 929 } 900 930 931 void CSPDirectiveList::parseScriptNonce(const String& name, const String& value) 932 { 933 if (!m_scriptNonce.isEmpty()) { 934 logDuplicateDirective(name); 935 return; 936 } 937 938 String nonce; 939 const UChar* position = value.characters(); 940 const UChar* end = position + value.length(); 941 942 skipWhile<isASCIISpace>(position, end); 943 const UChar* nonceBegin = position; 944 if (position == end) { 945 logInvalidNonce(String()); 946 return; 947 } 948 skipWhile<isNotASCIISpace>(position, end); 949 if (nonceBegin < position) 950 nonce = String(nonceBegin, position - nonceBegin); 951 952 // Trim off trailing whitespace: If we're not at the end of the string, log 953 // an error. 954 skipWhile<isASCIISpace>(position, end); 955 if (position < end) 956 logInvalidNonce(value); 957 else 958 m_scriptNonce = nonce; 959 } 960 901 961 void CSPDirectiveList::setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirective>& directive) 902 962 { … … 922 982 DEFINE_STATIC_LOCAL(String, defaultSrc, ("default-src")); 923 983 DEFINE_STATIC_LOCAL(String, scriptSrc, ("script-src")); 984 #if ENABLE(CSP_NEXT) 985 DEFINE_STATIC_LOCAL(String, scriptNonce, ("script-nonce")); 986 #endif 924 987 DEFINE_STATIC_LOCAL(String, objectSrc, ("object-src")); 925 988 DEFINE_STATIC_LOCAL(String, frameSrc, ("frame-src")); … … 956 1019 else if (equalIgnoringCase(name, reportURI)) 957 1020 parseReportURI(name, value); 1021 #if ENABLE(CSP_NEXT) 1022 else if (equalIgnoringCase(name, scriptNonce)) 1023 parseScriptNonce(name, value); 1024 #endif 958 1025 else 959 1026 logUnrecognizedDirective(name); … … 1017 1084 } 1018 1085 1086 template<bool (CSPDirectiveList::*allowed)(const String&, const String&, const WTF::OrdinalNumber&, const KURL&) const> 1087 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const String& nonce, const String& contextURL, const WTF::OrdinalNumber& contextLine, const KURL& url) 1088 { 1089 for (size_t i = 0; i < policies.size(); ++i) { 1090 if (!(policies[i].get()->*allowed)(nonce, contextURL, contextLine, url)) 1091 return false; 1092 } 1093 return true; 1094 } 1095 1019 1096 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&) const> 1020 1097 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& url) … … 1057 1134 } 1058 1135 1136 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce, const String& contextURL, const WTF::OrdinalNumber& contextLine, const KURL& url) const 1137 { 1138 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_policies, nonce, contextURL, contextLine, url); 1139 } 1140 1059 1141 bool ContentSecurityPolicy::allowScriptFromSource(const KURL& url) const 1060 1142 { -
trunk/Source/WebCore/page/ContentSecurityPolicy.h
r118585 r121883 27 27 #define ContentSecurityPolicy_h 28 28 29 #include "KURL.h" 29 30 #include <wtf/PassOwnPtr.h> 30 31 #include <wtf/RefCounted.h> … … 41 42 class ScriptCallStack; 42 43 class ScriptExecutionContext; 43 class KURL;44 44 45 45 typedef Vector<OwnPtr<CSPDirectiveList> > CSPDirectiveListVector; … … 72 72 bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine) const; 73 73 bool allowEval(PassRefPtr<ScriptCallStack>) const; 74 bool allowScriptNonce(const String& nonce, const String& contextURL, const WTF::OrdinalNumber& contextLine, const KURL& = KURL()) const; 74 75 75 76 bool allowScriptFromSource(const KURL&) const;
Note: See TracChangeset
for help on using the changeset viewer.