Chromium Code Reviews| Index: third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| index af63db5eb78f94f47517d4b626e8efbaf69fc257..ee81f1333d4cf94723cf68b45f76f65e5df9d70b 100644 |
| --- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| +++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp |
| @@ -72,6 +72,27 @@ |
| namespace blink { |
| +namespace { |
| + |
| +// Helper function that returns true if the given |header_type| should be |
| +// checked when the CheckHeaderType is |check_header_type|. |
| +bool CheckHeaderTypeMatches( |
| + ContentSecurityPolicy::CheckHeaderType check_header_type, |
| + ContentSecurityPolicyHeaderType header_type) { |
| + switch (check_header_type) { |
| + case ContentSecurityPolicy::CheckHeaderType::kCheckAll: |
| + return true; |
| + case ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly: |
| + return header_type == kContentSecurityPolicyHeaderTypeReport; |
| + case ContentSecurityPolicy::CheckHeaderType::kCheckEnforce: |
| + return header_type == kContentSecurityPolicyHeaderTypeEnforce; |
| + } |
| + NOTREACHED(); |
| + return false; |
| +} |
| + |
| +} // namespace |
| + |
| bool ContentSecurityPolicy::IsNonceableElement(const Element* element) { |
| if (RuntimeEnabledFeatures::hideNonceContentAttributeEnabled() && |
| isHTMLScriptElement(element)) { |
| @@ -459,12 +480,15 @@ template <bool (CSPDirectiveList::*allowFromURL)( |
| bool IsAllowedByAll(const CSPDirectiveListVector& policies, |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + ContentSecurityPolicy::CheckHeaderType check_header_type) { |
| if (ContentSecurityPolicy::ShouldBypassContentSecurityPolicy(url)) |
| return true; |
| bool is_allowed = true; |
| for (const auto& policy : policies) { |
| + if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType())) |
| + continue; |
| is_allowed &= |
| (policy.Get()->*allowFromURL)(url, redirect_status, reporting_policy); |
| } |
| @@ -481,12 +505,15 @@ bool IsAllowedByAll(const CSPDirectiveListVector& policies, |
| const KURL& url, |
| const String& nonce, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + ContentSecurityPolicy::CheckHeaderType check_header_type) { |
| if (ContentSecurityPolicy::ShouldBypassContentSecurityPolicy(url)) |
| return true; |
| bool is_allowed = true; |
| for (const auto& policy : policies) { |
| + if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType())) |
| + continue; |
| is_allowed &= (policy.Get()->*allowFromURLWithNonce)( |
| url, nonce, redirect_status, reporting_policy); |
| } |
| @@ -506,7 +533,8 @@ bool IsAllowedByAll(const CSPDirectiveListVector& policies, |
| const IntegrityMetadataSet& hashes, |
| ParserDisposition parser_disposition, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + ContentSecurityPolicy::CheckHeaderType check_header_type) { |
| if (ContentSecurityPolicy::ShouldBypassContentSecurityPolicy(url)) { |
| // If we're running experimental features, bypass CSP only for |
| // non-parser-inserted resources whose scheme otherwise bypasses CSP. If |
| @@ -523,6 +551,8 @@ bool IsAllowedByAll(const CSPDirectiveListVector& policies, |
| bool is_allowed = true; |
| for (const auto& policy : policies) { |
| + if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType())) |
| + continue; |
| is_allowed &= (policy.Get()->*allowFromURLWithNonceAndParser)( |
| url, nonce, hashes, parser_disposition, redirect_status, |
| reporting_policy); |
| @@ -707,7 +737,8 @@ bool ContentSecurityPolicy::AllowScriptFromSource( |
| const IntegrityMetadataSet& hashes, |
| ParserDisposition parser_disposition, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| if (ShouldBypassContentSecurityPolicy(url)) { |
| UseCounter::Count( |
| GetDocument(), |
| @@ -717,7 +748,7 @@ bool ContentSecurityPolicy::AllowScriptFromSource( |
| } |
| return IsAllowedByAll<&CSPDirectiveList::AllowScriptFromSource>( |
| policies_, url, nonce, hashes, parser_disposition, redirect_status, |
| - reporting_policy); |
| + reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowScriptWithHash(const String& source, |
| @@ -736,9 +767,11 @@ bool ContentSecurityPolicy::AllowRequestWithoutIntegrity( |
| WebURLRequest::RequestContext context, |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| for (const auto& policy : policies_) { |
| - if (!policy->AllowRequestWithoutIntegrity(context, url, redirect_status, |
| + if (CheckHeaderTypeMatches(check_header_type, policy->HeaderType()) && |
| + !policy->AllowRequestWithoutIntegrity(context, url, redirect_status, |
| reporting_policy)) |
| return false; |
| } |
| @@ -752,53 +785,63 @@ bool ContentSecurityPolicy::AllowRequest( |
| const IntegrityMetadataSet& integrity_metadata, |
| ParserDisposition parser_disposition, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| if (integrity_metadata.IsEmpty() && |
| !AllowRequestWithoutIntegrity(context, url, redirect_status, |
| - reporting_policy)) |
| + reporting_policy, check_header_type)) { |
| return false; |
| + } |
| switch (context) { |
| case WebURLRequest::kRequestContextAudio: |
| case WebURLRequest::kRequestContextTrack: |
| case WebURLRequest::kRequestContextVideo: |
| - return AllowMediaFromSource(url, redirect_status, reporting_policy); |
| + return AllowMediaFromSource(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextBeacon: |
| case WebURLRequest::kRequestContextEventSource: |
| case WebURLRequest::kRequestContextFetch: |
| case WebURLRequest::kRequestContextXMLHttpRequest: |
| case WebURLRequest::kRequestContextSubresource: |
| - return AllowConnectToSource(url, redirect_status, reporting_policy); |
| + return AllowConnectToSource(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextEmbed: |
| case WebURLRequest::kRequestContextObject: |
| - return AllowObjectFromSource(url, redirect_status, reporting_policy); |
| + return AllowObjectFromSource(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextFavicon: |
| case WebURLRequest::kRequestContextImage: |
| case WebURLRequest::kRequestContextImageSet: |
| - return AllowImageFromSource(url, redirect_status, reporting_policy); |
| + return AllowImageFromSource(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextFont: |
| - return AllowFontFromSource(url, redirect_status, reporting_policy); |
| + return AllowFontFromSource(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextForm: |
| - return AllowFormAction(url, redirect_status, reporting_policy); |
| + return AllowFormAction(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextFrame: |
| case WebURLRequest::kRequestContextIframe: |
| - return AllowFrameFromSource(url, redirect_status, reporting_policy); |
| + return AllowFrameFromSource(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextImport: |
| case WebURLRequest::kRequestContextScript: |
| case WebURLRequest::kRequestContextXSLT: |
| return AllowScriptFromSource(url, nonce, integrity_metadata, |
| parser_disposition, redirect_status, |
| - reporting_policy); |
| + reporting_policy, check_header_type); |
| case WebURLRequest::kRequestContextManifest: |
| - return AllowManifestFromSource(url, redirect_status, reporting_policy); |
| + return AllowManifestFromSource(url, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextServiceWorker: |
| case WebURLRequest::kRequestContextSharedWorker: |
| case WebURLRequest::kRequestContextWorker: |
| return AllowWorkerContextFromSource(url, redirect_status, |
| - reporting_policy); |
| + reporting_policy, check_header_type); |
| case WebURLRequest::kRequestContextStyle: |
| - return AllowStyleFromSource(url, nonce, redirect_status, |
| - reporting_policy); |
| + return AllowStyleFromSource(url, nonce, redirect_status, reporting_policy, |
| + check_header_type); |
| case WebURLRequest::kRequestContextCSPReport: |
| case WebURLRequest::kRequestContextDownload: |
| case WebURLRequest::kRequestContextHyperlink: |
| @@ -825,110 +868,126 @@ void ContentSecurityPolicy::UsesStyleHashAlgorithms(uint8_t algorithms) { |
| bool ContentSecurityPolicy::AllowObjectFromSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| return IsAllowedByAll<&CSPDirectiveList::AllowObjectFromSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowFrameFromSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| return IsAllowedByAll<&CSPDirectiveList::AllowFrameFromSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowImageFromSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| if (ShouldBypassContentSecurityPolicy(url, SchemeRegistry::kPolicyAreaImage)) |
| return true; |
| return IsAllowedByAll<&CSPDirectiveList::AllowImageFromSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowStyleFromSource( |
| const KURL& url, |
| const String& nonce, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| if (ShouldBypassContentSecurityPolicy(url, SchemeRegistry::kPolicyAreaStyle)) |
| return true; |
| return IsAllowedByAll<&CSPDirectiveList::AllowStyleFromSource>( |
| - policies_, url, nonce, redirect_status, reporting_policy); |
| + policies_, url, nonce, redirect_status, reporting_policy, |
| + check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowFontFromSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| return IsAllowedByAll<&CSPDirectiveList::AllowFontFromSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowMediaFromSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| return IsAllowedByAll<&CSPDirectiveList::AllowMediaFromSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowConnectToSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| return IsAllowedByAll<&CSPDirectiveList::AllowConnectToSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowFormAction( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| return IsAllowedByAll<&CSPDirectiveList::AllowFormAction>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowBaseURI( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| SecurityViolationReportingPolicy reporting_policy) const { |
| + // `base-uri` isn't affected by 'upgrade-insecure-requests', so we'll check |
| + // both report-only and enforce headers here. |
| return IsAllowedByAll<&CSPDirectiveList::AllowBaseURI>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, |
| + ContentSecurityPolicy::CheckHeaderType::kCheckAll); |
| } |
| bool ContentSecurityPolicy::AllowWorkerContextFromSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure the |
| // impact of this backwards-incompatible change. |
|
Mike West
2017/04/19 08:42:13
Nit: Can you add a `// TODO(mkwst): We reverted th
estark
2017/04/19 16:23:54
Done.
|
| if (Document* document = this->GetDocument()) { |
| UseCounter::Count(*document, UseCounter::kWorkerSubjectToCSP); |
| if (IsAllowedByAll<&CSPDirectiveList::AllowWorkerFromSource>( |
| policies_, url, redirect_status, |
| - SecurityViolationReportingPolicy::kSuppressReporting) && |
| + SecurityViolationReportingPolicy::kSuppressReporting, |
| + check_header_type) && |
| !IsAllowedByAll<&CSPDirectiveList::AllowScriptFromSource>( |
| policies_, url, AtomicString(), IntegrityMetadataSet(), |
| kNotParserInserted, redirect_status, |
| - SecurityViolationReportingPolicy::kSuppressReporting)) { |
| + SecurityViolationReportingPolicy::kSuppressReporting, |
| + check_header_type)) { |
| UseCounter::Count(*document, |
| UseCounter::kWorkerAllowedByChildBlockedByScript); |
| } |
| } |
| return IsAllowedByAll<&CSPDirectiveList::AllowWorkerFromSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowManifestFromSource( |
| const KURL& url, |
| RedirectStatus redirect_status, |
| - SecurityViolationReportingPolicy reporting_policy) const { |
| + SecurityViolationReportingPolicy reporting_policy, |
| + CheckHeaderType check_header_type) const { |
| return IsAllowedByAll<&CSPDirectiveList::AllowManifestFromSource>( |
| - policies_, url, redirect_status, reporting_policy); |
| + policies_, url, redirect_status, reporting_policy, check_header_type); |
| } |
| bool ContentSecurityPolicy::AllowAncestors( |