bool DocLoader::canRequest(CachedResource::Type type, const KURL& url) { // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case CachedResource::ImageResource: case CachedResource::CSSStyleSheet: case CachedResource::Script: case CachedResource::FontResource: // These types of resources can be loaded from any origin. // FIXME: Are we sure about CachedResource::FontResource? break; #if ENABLE(XSLT) case CachedResource::XSLStyleSheet: #endif #if ENABLE(XBL) case CachedResource::XBL: #endif #if ENABLE(XSLT) || ENABLE(XBL) if (!m_doc->securityOrigin()->canRequest(url)) { printAccessDeniedMessage(url); return false; } break; #endif default: ASSERT_NOT_REACHED(); break; } return true; }
bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url, bool forPreload) { if (!document()->securityOrigin()->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(document()->frame(), url.string()); LOG(ResourceLoading, "CachedResourceLoader::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return 0; } // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case CachedResource::ImageResource: case CachedResource::CSSStyleSheet: case CachedResource::Script: case CachedResource::FontResource: case CachedResource::RawResource: #if ENABLE(LINK_PREFETCH) case CachedResource::LinkPrefetch: case CachedResource::LinkPrerender: case CachedResource::LinkSubresource: #endif #if ENABLE(VIDEO_TRACK) case CachedResource::TextTrackResource: #endif #if ENABLE(CSS_SHADERS) case CachedResource::ShaderResource: #endif // These types of resources can be loaded from any origin. // FIXME: Are we sure about CachedResource::FontResource? break; #if ENABLE(XSLT) case CachedResource::XSLStyleSheet: if (!m_document->securityOrigin()->canRequest(url)) { printAccessDeniedMessage(url); return false; } break; #endif } switch (type) { #if ENABLE(XSLT) case CachedResource::XSLStyleSheet: #endif case CachedResource::Script: if (!m_document->contentSecurityPolicy()->allowScriptFromSource(url)) return false; if (frame()) { Settings* settings = frame()->settings(); if (!frame()->loader()->client()->allowScriptFromSource(!settings || settings->isScriptEnabled(), url)) { frame()->loader()->client()->didNotAllowScript(); return false; } } break; #if ENABLE(CSS_SHADERS) case CachedResource::ShaderResource: // Since shaders are referenced from CSS Styles use the same rules here. #endif case CachedResource::CSSStyleSheet: if (!m_document->contentSecurityPolicy()->allowStyleFromSource(url)) return false; break; case CachedResource::ImageResource: if (!m_document->contentSecurityPolicy()->allowImageFromSource(url)) return false; if (frame()) { Settings* settings = frame()->settings(); if (!frame()->loader()->client()->allowImage(!settings || settings->areImagesEnabled(), url)) return false; } break; case CachedResource::FontResource: { if (!m_document->contentSecurityPolicy()->allowFontFromSource(url)) return false; break; } case CachedResource::RawResource: #if ENABLE(LINK_PREFETCH) case CachedResource::LinkPrefetch: case CachedResource::LinkPrerender: case CachedResource::LinkSubresource: #endif break; #if ENABLE(VIDEO_TRACK) case CachedResource::TextTrackResource: // Cues aren't called out in the CPS spec yet, but they only work with a media element // so use the media policy. if (!m_document->contentSecurityPolicy()->allowMediaFromSource(url)) return false; break; #endif } // Last of all, check for insecure content. We do this last so that when // folks block insecure content with a CSP policy, they don't get a warning. // They'll still get a warning in the console about CSP blocking the load. // FIXME: Should we consider forPreload here? if (!checkInsecureContent(type, url)) return false; return true; }
bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url, bool forPreload) { if (!document()->securityOrigin()->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(document()->frame(), url.string()); LOG(ResourceLoading, "CachedResourceLoader::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return 0; } // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case CachedResource::ImageResource: case CachedResource::CSSStyleSheet: case CachedResource::Script: #if ENABLE(SVG) case CachedResource::SVGDocumentResource: #endif case CachedResource::FontResource: #if ENABLE(LINK_PREFETCH) case CachedResource::LinkPrefetch: case CachedResource::LinkPrerender: case CachedResource::LinkSubresource: #endif // These types of resources can be loaded from any origin. // FIXME: Are we sure about CachedResource::FontResource? break; #if ENABLE(XSLT) case CachedResource::XSLStyleSheet: if (!m_document->securityOrigin()->canRequest(url)) { printAccessDeniedMessage(url); return false; } break; #endif } // Given that the load is allowed by the same-origin policy, we should // check whether the load passes the mixed-content policy. // // FIXME: Should we consider forPreload here? if (!checkInsecureContent(type, url)) return false; // FIXME: Consider letting the embedder block mixed content loads. switch (type) { case CachedResource::Script: if (!m_document->contentSecurityPolicy()->allowScriptFromSource(url)) return false; break; #if ENABLE(XSLT) case CachedResource::XSLStyleSheet: #endif case CachedResource::CSSStyleSheet: if (!m_document->contentSecurityPolicy()->allowStyleFromSource(url)) return false; break; case CachedResource::ImageResource: if (!m_document->contentSecurityPolicy()->allowImageFromSource(url)) return false; break; #if ENABLE(SVG) case CachedResource::SVGDocumentResource: #endif case CachedResource::FontResource: { if (!m_document->contentSecurityPolicy()->allowFontFromSource(url)) return false; break; } #if ENABLE(LINK_PREFETCH) case CachedResource::LinkPrefetch: case CachedResource::LinkPrerender: case CachedResource::LinkSubresource: break; #endif } return true; }
bool DocLoader::canRequest(CachedResource::Type type, const KURL& url) { // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case CachedResource::ImageResource: case CachedResource::CSSStyleSheet: case CachedResource::Script: case CachedResource::FontResource: // These types of resources can be loaded from any origin. // FIXME: Are we sure about CachedResource::FontResource? break; #if ENABLE(XSLT) case CachedResource::XSLStyleSheet: #endif #if ENABLE(XBL) case CachedResource::XBL: #endif #if ENABLE(XSLT) || ENABLE(XBL) if (!m_doc->securityOrigin()->canRequest(url)) { printAccessDeniedMessage(url); return false; } break; #endif default: ASSERT_NOT_REACHED(); break; } // Given that the load is allowed by the same-origin policy, we should // check whether the load passes the mixed-content policy. // // Note: Currently, we always allow mixed content, but we generate a // callback to the FrameLoaderClient in case the embedder wants to // update any security indicators. // switch (type) { case CachedResource::Script: #if ENABLE(XSLT) case CachedResource::XSLStyleSheet: #endif #if ENABLE(XBL) case CachedResource::XBL: #endif // These resource can inject script into the current document. if (Frame* f = frame()) f->loader()->checkIfRunInsecureContent(m_doc->securityOrigin(), url); break; case CachedResource::ImageResource: case CachedResource::CSSStyleSheet: case CachedResource::FontResource: { // These resources can corrupt only the frame's pixels. if (Frame* f = frame()) { Frame* top = f->tree()->top(); top->loader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), url); } break; } default: ASSERT_NOT_REACHED(); break; } // FIXME: Consider letting the embedder block mixed content loads. return true; }
ResourceRequestBlockedReason FrameFetchContext::canRequestInternal(Resource::Type type, const ResourceRequest& resourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forPreload, FetchRequest::OriginRestriction originRestriction, ResourceRequest::RedirectStatus redirectStatus) const { if (InspectorInstrumentation::shouldBlockRequest(frame(), resourceRequest)) return ResourceRequestBlockedReasonInspector; SecurityOrigin* securityOrigin = options.securityOrigin.get(); if (!securityOrigin && m_document) securityOrigin = m_document->getSecurityOrigin(); if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin && !securityOrigin->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return ResourceRequestBlockedReasonOther; } // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case Resource::MainResource: case Resource::Image: case Resource::CSSStyleSheet: case Resource::Script: case Resource::Font: case Resource::Raw: case Resource::LinkPrefetch: case Resource::LinkPreload: case Resource::TextTrack: case Resource::ImportResource: case Resource::Media: case Resource::Manifest: // By default these types of resources can be loaded from any origin. // FIXME: Are we sure about Resource::Font? if (originRestriction == FetchRequest::RestrictToSameOrigin && !securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; case Resource::XSLStyleSheet: ASSERT(RuntimeEnabledFeatures::xsltEnabled()); case Resource::SVGDocument: if (!securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; } // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP() || options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; // Don't send CSP messages for preloads, we might never actually display those items. ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendReport; if (m_document) { DCHECK(m_document->contentSecurityPolicy()); if (!shouldBypassMainWorldCSP && !m_document->contentSecurityPolicy()->allowRequest(resourceRequest.requestContext(), url, options.contentSecurityPolicyNonce, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; } if (type == Resource::Script || type == Resource::ImportResource) { ASSERT(frame()); if (!frame()->loader().client()->allowScriptFromSource(!frame()->settings() || frame()->settings()->scriptEnabled(), url)) { frame()->loader().client()->didNotAllowScript(); // TODO(estark): Use a different ResourceRequestBlockedReason // here, since this check has nothing to do with // CSP. https://crbug.com/600795 return ResourceRequestBlockedReasonCSP; } } else if (type == Resource::Media || type == Resource::TextTrack) { ASSERT(frame()); if (!frame()->loader().client()->allowMedia(url)) return ResourceRequestBlockedReasonOther; } // SVG Images have unique security rules that prevent all subresource requests // except for data urls. if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChromeClient() && !url.protocolIsData()) return ResourceRequestBlockedReasonOrigin; // Measure the number of legacy URL schemes ('ftp://') and the number of embedded-credential // ('http://*****:*****@...') resources embedded as subresources. in the hopes that we can // block them at some point in the future. if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { ASSERT(frame()->document()); if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !SchemeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->getSecurityOrigin()->protocol())) UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmbeddedAsSubresource); if (!url.user().isEmpty() || !url.pass().isEmpty()) UseCounter::count(frame()->document(), UseCounter::RequestedSubresourceWithEmbeddedCredentials); } // Check for mixed content. We do this second-to-last so that when folks block // mixed content with a CSP policy, they don't get a warning. They'll still // get a warning in the console about CSP blocking the load. MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; if (MixedContentChecker::shouldBlockFetch(frame(), resourceRequest, url, mixedContentReporting)) return ResourceRequestBlockedReasonMixedContent; // Let the client have the final say into whether or not the load should proceed. DocumentLoader* documentLoader = masterDocumentLoader(); if (documentLoader && documentLoader->subresourceFilter() && type != Resource::MainResource && type != Resource::ImportResource && !documentLoader->subresourceFilter()->allowLoad(url, resourceRequest.requestContext())) return ResourceRequestBlockedReasonSubresourceFilter; return ResourceRequestBlockedReasonNone; }
ResourceRequestBlockedReason FrameFetchContext::canRequestInternal(Resource::Type type, const ResourceRequest& resourceRequest, const KURL& url, const ResourceLoaderOptions& options, bool forPreload, FetchRequest::OriginRestriction originRestriction) const { InstrumentingAgents* agents = InspectorInstrumentation::instrumentingAgentsFor(frame()); if (agents && agents->inspectorResourceAgent()) { if (agents->inspectorResourceAgent()->shouldBlockRequest(resourceRequest)) return ResourceRequestBlockedReasonInspector; } SecurityOrigin* securityOrigin = options.securityOrigin.get(); if (!securityOrigin && m_document) securityOrigin = m_document->securityOrigin(); if (originRestriction != FetchRequest::NoOriginRestriction && securityOrigin && !securityOrigin->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(frame(), url.elidedString()); WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return ResourceRequestBlockedReasonOther; } // Some types of resources can be loaded only from the same origin. Other // types of resources, like Images, Scripts, and CSS, can be loaded from // any URL. switch (type) { case Resource::MainResource: case Resource::Image: case Resource::CSSStyleSheet: case Resource::Script: case Resource::Font: case Resource::Raw: case Resource::LinkPrefetch: case Resource::LinkSubresource: case Resource::LinkPreload: case Resource::TextTrack: case Resource::ImportResource: case Resource::Media: // By default these types of resources can be loaded from any origin. // FIXME: Are we sure about Resource::Font? if (originRestriction == FetchRequest::RestrictToSameOrigin && !securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; case Resource::XSLStyleSheet: ASSERT(RuntimeEnabledFeatures::xsltEnabled()); case Resource::SVGDocument: if (!securityOrigin->canRequest(url)) { printAccessDeniedMessage(url); return ResourceRequestBlockedReasonOrigin; } break; } // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved. bool shouldBypassMainWorldCSP = frame()->script().shouldBypassMainWorldCSP() || options.contentSecurityPolicyOption == DoNotCheckContentSecurityPolicy; // Don't send CSP messages for preloads, we might never actually display those items. ContentSecurityPolicy::ReportingStatus cspReporting = forPreload ? ContentSecurityPolicy::SuppressReport : ContentSecurityPolicy::SendReport; // As of CSP2, for requests that are the results of redirects, the match // algorithm should ignore the path component of the URL. ContentSecurityPolicy::RedirectStatus redirectStatus = resourceRequest.followedRedirect() ? ContentSecurityPolicy::DidRedirect : ContentSecurityPolicy::DidNotRedirect; // m_document can be null, but not in any of the cases where csp is actually used below. // ImageResourceTest.MultipartImage crashes w/o the m_document null check. // I believe it's the Resource::Raw case. const ContentSecurityPolicy* csp = m_document ? m_document->contentSecurityPolicy() : nullptr; // FIXME: This would be cleaner if moved this switch into an allowFromSource() // helper on this object which took a Resource::Type, then this block would // collapse to about 10 lines for handling Raw and Script special cases. switch (type) { case Resource::XSLStyleSheet: ASSERT(RuntimeEnabledFeatures::xsltEnabled()); ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; case Resource::Script: case Resource::ImportResource: ASSERT(ContentSecurityPolicy::isScriptResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowScriptFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; if (!frame()->loader().client()->allowScriptFromSource(!frame()->settings() || frame()->settings()->scriptEnabled(), url)) { frame()->loader().client()->didNotAllowScript(); return ResourceRequestBlockedReasonCSP; } break; case Resource::CSSStyleSheet: ASSERT(ContentSecurityPolicy::isStyleResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowStyleFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; case Resource::SVGDocument: case Resource::Image: ASSERT(ContentSecurityPolicy::isImageResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowImageFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; case Resource::Font: { ASSERT(ContentSecurityPolicy::isFontResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowFontFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; break; } case Resource::MainResource: case Resource::Raw: case Resource::LinkPrefetch: case Resource::LinkSubresource: case Resource::LinkPreload: break; case Resource::Media: case Resource::TextTrack: ASSERT(ContentSecurityPolicy::isMediaResource(resourceRequest)); if (!shouldBypassMainWorldCSP && !csp->allowMediaFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; if (!frame()->loader().client()->allowMedia(url)) return ResourceRequestBlockedReasonOther; break; } // SVG Images have unique security rules that prevent all subresource requests // except for data urls. if (type != Resource::MainResource && frame()->chromeClient().isSVGImageChromeClient() && !url.protocolIsData()) return ResourceRequestBlockedReasonOrigin; // FIXME: Once we use RequestContext for CSP (http://crbug.com/390497), remove this extra check. if (resourceRequest.requestContext() == WebURLRequest::RequestContextManifest) { if (!shouldBypassMainWorldCSP && !csp->allowManifestFromSource(url, redirectStatus, cspReporting)) return ResourceRequestBlockedReasonCSP; } // Measure the number of legacy URL schemes ('ftp://') and the number of embedded-credential // ('http://*****:*****@...') resources embedded as subresources. in the hopes that we can // block them at some point in the future. if (resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel) { ASSERT(frame()->document()); if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !SchemeRegistry::shouldTreatURLSchemeAsLegacy(frame()->document()->securityOrigin()->protocol())) UseCounter::count(frame()->document(), UseCounter::LegacyProtocolEmbeddedAsSubresource); if (!url.user().isEmpty() || !url.pass().isEmpty()) UseCounter::count(frame()->document(), UseCounter::RequestedSubresourceWithEmbeddedCredentials); } // Measure the number of pages that load resources after a redirect // when a CSP is active, to see if implementing CSP // 'unsafe-redirect' is feasible. if (csp && csp->isActive() && resourceRequest.frameType() != WebURLRequest::FrameTypeTopLevel && resourceRequest.frameType() != WebURLRequest::FrameTypeAuxiliary && redirectStatus == ContentSecurityPolicy::DidRedirect) { ASSERT(frame()->document()); UseCounter::count(frame()->document(), UseCounter::ResourceLoadedAfterRedirectWithCSP); } // Last of all, check for mixed content. We do this last so that when // folks block mixed content with a CSP policy, they don't get a warning. // They'll still get a warning in the console about CSP blocking the load. MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ? MixedContentChecker::SuppressReport : MixedContentChecker::SendReport; if (MixedContentChecker::shouldBlockFetch(MixedContentChecker::effectiveFrameForFrameType(frame(), resourceRequest.frameType()), resourceRequest, url, mixedContentReporting)) return ResourceRequestBlockedReasonMixedContent; return ResourceRequestBlockedReasonNone; }