Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(245)

Side by Side Diff: third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp

Issue 2056183002: Implement the `require-sri-for` CSP directive (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: addressed comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/frame/csp/CSPDirectiveList.h" 5 #include "core/frame/csp/CSPDirectiveList.h"
6 6
7 #include "bindings/core/v8/SourceLocation.h" 7 #include "bindings/core/v8/SourceLocation.h"
8 #include "core/dom/Document.h" 8 #include "core/dom/Document.h"
9 #include "core/dom/SecurityContext.h" 9 #include "core/dom/SecurityContext.h"
10 #include "core/dom/SpaceSplitString.h" 10 #include "core/dom/SpaceSplitString.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 , m_headerType(type) 48 , m_headerType(type)
49 , m_headerSource(source) 49 , m_headerSource(source)
50 , m_reportOnly(false) 50 , m_reportOnly(false)
51 , m_hasSandboxPolicy(false) 51 , m_hasSandboxPolicy(false)
52 , m_reflectedXSSDisposition(ReflectedXSSUnset) 52 , m_reflectedXSSDisposition(ReflectedXSSUnset)
53 , m_didSetReferrerPolicy(false) 53 , m_didSetReferrerPolicy(false)
54 , m_referrerPolicy(ReferrerPolicyDefault) 54 , m_referrerPolicy(ReferrerPolicyDefault)
55 , m_strictMixedContentCheckingEnforced(false) 55 , m_strictMixedContentCheckingEnforced(false)
56 , m_upgradeInsecureRequests(false) 56 , m_upgradeInsecureRequests(false)
57 , m_treatAsPublicAddress(false) 57 , m_treatAsPublicAddress(false)
58 , m_requireSRIFor(0)
58 { 59 {
59 m_reportOnly = type == ContentSecurityPolicyHeaderTypeReport; 60 m_reportOnly = type == ContentSecurityPolicyHeaderTypeReport;
60 } 61 }
61 62
62 CSPDirectiveList* CSPDirectiveList::create(ContentSecurityPolicy* policy, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType type, ContentSec urityPolicyHeaderSource source) 63 CSPDirectiveList* CSPDirectiveList::create(ContentSecurityPolicy* policy, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType type, ContentSec urityPolicyHeaderSource source)
63 { 64 {
64 CSPDirectiveList* directives = new CSPDirectiveList(policy, type, source); 65 CSPDirectiveList* directives = new CSPDirectiveList(policy, type, source);
65 directives->parse(begin, end); 66 directives->parse(begin, end);
66 67
67 if (!directives->checkEval(directives->operativeDirective(directives->m_scri ptSrc.get()))) { 68 if (!directives->checkEval(directives->operativeDirective(directives->m_scri ptSrc.get()))) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 // 167 //
167 // TODO(mkwst): Move this check up into the browser process. See 168 // TODO(mkwst): Move this check up into the browser process. See
168 // https://crbug.com/555418. 169 // https://crbug.com/555418.
169 KURL url(KURL(), current->securityContext()->getSecurityOrigin()->toStri ng()); 170 KURL url(KURL(), current->securityContext()->getSecurityOrigin()->toStri ng());
170 if (!directive->allows(url, ResourceRequest::RedirectStatus::NoRedirect) ) 171 if (!directive->allows(url, ResourceRequest::RedirectStatus::NoRedirect) )
171 return false; 172 return false;
172 } 173 }
173 return true; 174 return true;
174 } 175 }
175 176
177 bool CSPDirectiveList::checkRequestWithoutIntegrity(WebURLRequest::RequestContex t context) const
178 {
179 if (m_requireSRIFor == RequireSRIForToken::None)
180 return true;
181 // SRI specification (https://w3c.github.io/webappsec-subresource-integrity/ #apply-algorithm-to-request)
182 // says to match token with request's destination with the token.
183 // Keep this logic aligned with ContentSecurityPolicy::allowRequest
184 if ((m_requireSRIFor & RequireSRIForToken::Script)
185 && (context == WebURLRequest::RequestContextScript || context == WebURLR equest::RequestContextImport
186 || context == WebURLRequest::RequestContextServiceWorker
Mike West 2016/06/21 07:29:36 Is this what `git cl format` came up with? Because
Sergey Shekyan 2016/06/22 06:25:14 Acknowledged.
187 || context == WebURLRequest::RequestContextSharedWorker
188 || context == WebURLRequest::RequestContextWorker))
189 return false;
Mike West 2016/06/21 07:29:36 Please add {} for multi-line clauses.
Sergey Shekyan 2016/06/22 06:25:14 Acknowledged.
190 if ((m_requireSRIFor & RequireSRIForToken::Style) && context == WebURLReques t::RequestContextStyle)
191 return false;
192 return true;
193 }
194
195 bool CSPDirectiveList::checkRequestWithoutIntegrityAndReportViolation(WebURLRequ est::RequestContext context, const KURL& url, ResourceRequest::RedirectStatus re directStatus) const
196 {
197 if (checkRequestWithoutIntegrity(context))
198 return true;
199 String resourceType;
200 switch (context) {
201 case WebURLRequest::RequestContextScript:
202 case WebURLRequest::RequestContextImport:
203 resourceType = "script";
204 break;
205 case WebURLRequest::RequestContextStyle:
206 resourceType = "stylesheet";
207 break;
208 case WebURLRequest::RequestContextServiceWorker:
209 resourceType = "service worker";
210 break;
211 case WebURLRequest::RequestContextSharedWorker:
212 resourceType = "shared worker";
213 break;
214 case WebURLRequest::RequestContextWorker:
215 resourceType = "worker";
216 break;
217 default:
218 break;
219 }
220 reportViolation(ContentSecurityPolicy::RequireSRIFor, ContentSecurityPolicy: :RequireSRIFor, "Refused to load the " + resourceType + " '" + url.elidedString( ) + "' because 'require-sri-for' directive requires integrity attribute be prese nt for all " + resourceType + "s.", url, redirectStatus);
221 return denyIfEnforcingPolicy();
222 }
223
224 bool CSPDirectiveList::allowRequestWithoutIntegrity(WebURLRequest::RequestContex t context, const KURL& url, ResourceRequest::RedirectStatus redirectStatus, Cont entSecurityPolicy::ReportingStatus reportingStatus) const
225 {
226 if (reportingStatus == ContentSecurityPolicy::SendReport)
227 return checkRequestWithoutIntegrityAndReportViolation(context, url, redi rectStatus);
228 return checkRequestWithoutIntegrity(context);
229 }
230
176 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const 231 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const
177 { 232 {
178 if (!directive) 233 if (!directive)
179 return true; 234 return true;
180 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) 235 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
181 return false; 236 return false;
182 return directive->allows(type); 237 return directive->allows(type);
183 } 238 }
184 239
185 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* d irective) const 240 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* d irective) const
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 } 599 }
545 600
546 // The directive-value may be empty. 601 // The directive-value may be empty.
547 if (valueBegin == position) 602 if (valueBegin == position)
548 return true; 603 return true;
549 604
550 value = String(valueBegin, position - valueBegin); 605 value = String(valueBegin, position - valueBegin);
551 return true; 606 return true;
552 } 607 }
553 608
609 void CSPDirectiveList::parseRequireSRIFor(const String& name, const String& valu e)
610 {
611 if (m_requireSRIFor != 0) {
612 m_policy->reportDuplicateDirective(name);
613 return;
614 }
615 StringBuilder tokenErrors;
616 unsigned numberOfTokenErrors = 0;
617 Vector<UChar> characters;
618 value.appendTo(characters);
619
620 const UChar* position = characters.data();
621 const UChar* end = position + characters.size();
622
623 while (position < end) {
624 skipWhile<UChar, isASCIISpace>(position, end);
625
626 const UChar* tokenBegin = position;
627 skipWhile<UChar, isNotASCIISpace>(position, end);
628
629 if (tokenBegin < position) {
630 String token = String(tokenBegin, position - tokenBegin);
631 if (equalIgnoringCase(token, "script")) {
632 m_requireSRIFor |= RequireSRIForToken::Script;
633 } else if (equalIgnoringCase(token, "style")) {
634 m_requireSRIFor |= RequireSRIForToken::Style;
635 } else {
636 if (numberOfTokenErrors)
637 tokenErrors.append(", \'");
638 else
639 tokenErrors.append('\'');
640 tokenErrors.append(token);
641 tokenErrors.append('\'');
642 numberOfTokenErrors++;
643 }
644 }
645 }
646
647 if (numberOfTokenErrors == 0)
648 return;
649
650 String invalidTokensErrorMessage;
651 if (numberOfTokenErrors > 1)
652 tokenErrors.append(" are invalid 'require-sri-for' tokens.");
653 else
654 tokenErrors.append(" is an invalid 'require-sri-for' token.");
655
656 invalidTokensErrorMessage = tokenErrors.toString();
657
658 DCHECK(!invalidTokensErrorMessage.isEmpty());
659
660 m_policy->reportInvalidRequireSRIForTokens(invalidTokensErrorMessage);
661 }
662
554 void CSPDirectiveList::parseReportURI(const String& name, const String& value) 663 void CSPDirectiveList::parseReportURI(const String& name, const String& value)
555 { 664 {
556 if (!m_reportEndpoints.isEmpty()) { 665 if (!m_reportEndpoints.isEmpty()) {
557 m_policy->reportDuplicateDirective(name); 666 m_policy->reportDuplicateDirective(name);
558 return; 667 return;
559 } 668 }
560 669
561 // Remove report-uri in meta policies, per https://www.w3.org/TR/CSP2/#deliv ery-html-meta-element. 670 // Remove report-uri in meta policies, per https://www.w3.org/TR/CSP2/#deliv ery-html-meta-element.
562 if (m_headerSource == ContentSecurityPolicyHeaderSourceMeta) { 671 if (m_headerSource == ContentSecurityPolicyHeaderSourceMeta) {
563 UseCounter::count(m_policy->document(), UseCounter::InvalidReportUriDire ctiveInMetaCSP); 672 UseCounter::count(m_policy->document(), UseCounter::InvalidReportUriDire ctiveInMetaCSP);
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { 926 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) {
818 parseReferrer(name, value); 927 parseReferrer(name, value);
819 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq uests)) { 928 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq uests)) {
820 enableInsecureRequestsUpgrade(name, value); 929 enableInsecureRequestsUpgrade(name, value);
821 } else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedConte nt)) { 930 } else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedConte nt)) {
822 enforceStrictMixedContentChecking(name, value); 931 enforceStrictMixedContentChecking(name, value);
823 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) { 932 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) {
824 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); 933 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc);
825 } else if (equalIgnoringCase(name, ContentSecurityPolicy::TreatAsPublicAddre ss)) { 934 } else if (equalIgnoringCase(name, ContentSecurityPolicy::TreatAsPublicAddre ss)) {
826 treatAsPublicAddress(name, value); 935 treatAsPublicAddress(name, value);
936 } else if (equalIgnoringCase(name, ContentSecurityPolicy::RequireSRIFor) && m_policy->experimentalFeaturesEnabled()) {
937 parseRequireSRIFor(name, value);
827 } else { 938 } else {
828 m_policy->reportUnsupportedDirective(name); 939 m_policy->reportUnsupportedDirective(name);
829 } 940 }
830 } 941 }
831 942
832 DEFINE_TRACE(CSPDirectiveList) 943 DEFINE_TRACE(CSPDirectiveList)
833 { 944 {
834 visitor->trace(m_policy); 945 visitor->trace(m_policy);
835 visitor->trace(m_pluginTypes); 946 visitor->trace(m_pluginTypes);
836 visitor->trace(m_baseURI); 947 visitor->trace(m_baseURI);
837 visitor->trace(m_childSrc); 948 visitor->trace(m_childSrc);
838 visitor->trace(m_connectSrc); 949 visitor->trace(m_connectSrc);
839 visitor->trace(m_defaultSrc); 950 visitor->trace(m_defaultSrc);
840 visitor->trace(m_fontSrc); 951 visitor->trace(m_fontSrc);
841 visitor->trace(m_formAction); 952 visitor->trace(m_formAction);
842 visitor->trace(m_frameAncestors); 953 visitor->trace(m_frameAncestors);
843 visitor->trace(m_frameSrc); 954 visitor->trace(m_frameSrc);
844 visitor->trace(m_imgSrc); 955 visitor->trace(m_imgSrc);
845 visitor->trace(m_mediaSrc); 956 visitor->trace(m_mediaSrc);
846 visitor->trace(m_manifestSrc); 957 visitor->trace(m_manifestSrc);
847 visitor->trace(m_objectSrc); 958 visitor->trace(m_objectSrc);
848 visitor->trace(m_scriptSrc); 959 visitor->trace(m_scriptSrc);
849 visitor->trace(m_styleSrc); 960 visitor->trace(m_styleSrc);
850 } 961 }
851 962
852 963
853 } // namespace blink 964 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698