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

Unified 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: 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp
index d90f9266bb2925e3255599e4c592c0aeadb5c845..6532029981e205b6771ec2c20d206c4ea95a1355 100644
--- a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp
@@ -173,6 +173,51 @@ bool CSPDirectiveList::checkAncestors(SourceListDirective* directive, LocalFrame
return true;
}
+bool CSPDirectiveList::checkIntegrityPresence(WebURLRequest::RequestContext context, const IntegrityMetadataSet& integrityMetadata) const
+{
+ if (!integrityMetadata.isEmpty())
+ return true;
+
+ if (m_requireSRIFor.isEmpty())
+ return true;
+
+ for (const auto& token : m_requireSRIFor) {
+ if (equalIgnoringCase(token, "script")) {
+ if (context == WebURLRequest::RequestContextScript || context == WebURLRequest::RequestContextImport) {
+ if (integrityMetadata.isEmpty())
+ return false;
+ }
+ } else if (equalIgnoringCase(token, "style")) {
+ if (context == WebURLRequest::RequestContextStyle) {
+ if (integrityMetadata.isEmpty())
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool CSPDirectiveList::checkIntegrityPresenceAndReportViolation(WebURLRequest::RequestContext context, const KURL& url, const IntegrityMetadataSet& integrityMetadata) const
+{
+ if (checkIntegrityPresence(context, integrityMetadata))
+ return true;
+ String resourceType;
+ if (context == WebURLRequest::RequestContextScript || context == WebURLRequest::RequestContextImport)
jww 2016/06/11 22:45:12 Treating RequestContextImport as guaranteed to be
Sergey Shekyan 2016/06/20 07:12:00 I inherited the logic that RequestContextImport is
Mike West 2016/06/20 08:11:37 Right. Contexts are from an earlier version of Fet
+ resourceType = "script";
+ else if (context == WebURLRequest::RequestContextStyle)
+ resourceType = "stylesheet";
+ reportViolation(ContentSecurityPolicy::RequireSRIFor, ContentSecurityPolicy::RequireSRIFor, "Refused to load the " + resourceType + " '" + url.elidedString() + "' because 'require-sri-for' directive requires integrity attribute be present for all " + resourceType + "s.", url, ResourceRequest::RedirectStatus::NoRedirect);
Mike West 2016/06/10 09:25:15 `NoRedirect` probably isn't correct here, as I thi
Sergey Shekyan 2016/06/20 07:11:59 Acknowledged.
+ return denyIfEnforcingPolicy();
+}
+
+bool CSPDirectiveList::allowRequestWithoutMetadata(WebURLRequest::RequestContext context, const KURL& url, const IntegrityMetadataSet& integrityMetadata, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+ if (reportingStatus == ContentSecurityPolicy::SendReport) {
+ return checkIntegrityPresenceAndReportViolation(context, url, integrityMetadata);
+ }
+ return checkIntegrityPresence(context, integrityMetadata);
+}
+
bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const
{
if (!directive)
@@ -551,6 +596,62 @@ bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, Stri
return true;
}
+void CSPDirectiveList::parseRequireSRIFor(const String& name, const String& value)
+{
+ if (!m_requireSRIFor.isEmpty()) {
+ m_policy->reportDuplicateDirective(name);
+ return;
+ }
+ StringBuilder tokenErrors;
+ StringBuilder validTokens;
+ unsigned numberOfTokenErrors = 0;
+ Vector<UChar> characters;
+ value.appendTo(characters);
+
+ const UChar* position = characters.data();
+ const UChar* end = position + characters.size();
+
+ while (position < end) {
+ skipWhile<UChar, isASCIISpace>(position, end);
+
+ const UChar* tokenBegin = position;
+ skipWhile<UChar, isNotASCIISpace>(position, end);
+
+ if (tokenBegin < position) {
+ String token = String(tokenBegin, position - tokenBegin);
+ if (equalIgnoringCase(token, "script") || equalIgnoringCase(token, "style")) {
+ m_requireSRIFor.append(token);
+ if (!validTokens.isEmpty())
+ validTokens.append(' ');
+ validTokens.append(token);
+ } else {
+ if (numberOfTokenErrors)
+ tokenErrors.append(", \'");
+ else
+ tokenErrors.append('\'');
+ tokenErrors.append(token);
+ tokenErrors.append('\'');
+ numberOfTokenErrors++;
+ }
+ }
+ }
+
+ if (numberOfTokenErrors == 0)
+ return;
+
+ String invalidTokensErrorMessage;
+ if (numberOfTokenErrors > 1)
+ tokenErrors.append(" are invalid 'require-sri-for' tokens.");
+ else
+ tokenErrors.append(" is an invalid 'require-sri-for' token.");
+
+ invalidTokensErrorMessage = tokenErrors.toString();
+
+ if (!invalidTokensErrorMessage.isEmpty()) {
jww 2016/06/11 22:45:12 I think inavildTokensErrorMessage cannot be empty
Sergey Shekyan 2016/06/20 07:12:00 Acknowledged.
+ m_policy->reportInvalidRequireSRIForTokens(invalidTokensErrorMessage);
+ }
+}
+
void CSPDirectiveList::parseReportURI(const String& name, const String& value)
{
if (!m_reportEndpoints.isEmpty()) {
@@ -824,6 +925,8 @@ void CSPDirectiveList::addDirective(const String& name, const String& value)
setCSPDirective<SourceListDirective>(name, value, m_manifestSrc);
} else if (equalIgnoringCase(name, ContentSecurityPolicy::TreatAsPublicAddress)) {
treatAsPublicAddress(name, value);
+ } else if (equalIgnoringCase(name, ContentSecurityPolicy::RequireSRIFor)) {
+ parseRequireSRIFor(name, value);
Mike West 2016/06/10 09:25:15 This functionality should be hidden behind the exp
Sergey Shekyan 2016/06/20 07:12:00 Acknowledged.
} else {
m_policy->reportUnsupportedDirective(name);
}

Powered by Google App Engine
This is Rietveld 408576698