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

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

Issue 2436003002: CSP: Add 'script-sample' to violation reports. (Closed)
Patch Set: Rebase. Created 3 years, 10 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 /* 1 /*
2 * Copyright (C) 2011 Google, Inc. All rights reserved. 2 * Copyright (C) 2011 Google, Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 bool isAllowed = true; 412 bool isAllowed = true;
413 for (const auto& policy : policies) 413 for (const auto& policy : policies)
414 isAllowed &= 414 isAllowed &=
415 (policy.get()->*allowed)(scriptState, reportingStatus, exceptionStatus); 415 (policy.get()->*allowed)(scriptState, reportingStatus, exceptionStatus);
416 return isAllowed; 416 return isAllowed;
417 } 417 }
418 418
419 template <bool (CSPDirectiveList::*allowed)( 419 template <bool (CSPDirectiveList::*allowed)(
420 Element*, 420 Element*,
421 const String&, 421 const String&,
422 const String&,
422 const WTF::OrdinalNumber&, 423 const WTF::OrdinalNumber&,
423 ContentSecurityPolicy::ReportingStatus) const> 424 ContentSecurityPolicy::ReportingStatus) const>
424 bool isAllowedByAll(const CSPDirectiveListVector& policies, 425 bool isAllowedByAll(const CSPDirectiveListVector& policies,
425 Element* element, 426 Element* element,
427 const String& source,
426 const String& contextURL, 428 const String& contextURL,
427 const WTF::OrdinalNumber& contextLine, 429 const WTF::OrdinalNumber& contextLine,
428 ContentSecurityPolicy::ReportingStatus reportingStatus) { 430 ContentSecurityPolicy::ReportingStatus reportingStatus) {
429 bool isAllowed = true; 431 bool isAllowed = true;
430 for (const auto& policy : policies) { 432 for (const auto& policy : policies) {
431 isAllowed &= (policy.get()->*allowed)(element, contextURL, contextLine, 433 isAllowed &= (policy.get()->*allowed)(element, source, contextURL,
432 reportingStatus); 434 contextLine, reportingStatus);
433 } 435 }
434 return isAllowed; 436 return isAllowed;
435 } 437 }
436 438
437 template < 439 template <
438 bool (CSPDirectiveList::*allowed)(Element*, 440 bool (CSPDirectiveList::*allowed)(Element*,
439 const String&, 441 const String&,
440 const String&, 442 const String&,
441 const WTF::OrdinalNumber&, 443 const WTF::OrdinalNumber&,
442 ContentSecurityPolicy::ReportingStatus, 444 ContentSecurityPolicy::ReportingStatus,
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 type)) 617 type))
616 return true; 618 return true;
617 } 619 }
618 } 620 }
619 621
620 return false; 622 return false;
621 } 623 }
622 624
623 bool ContentSecurityPolicy::allowJavaScriptURLs( 625 bool ContentSecurityPolicy::allowJavaScriptURLs(
624 Element* element, 626 Element* element,
627 const String& source,
625 const String& contextURL, 628 const String& contextURL,
626 const WTF::OrdinalNumber& contextLine, 629 const WTF::OrdinalNumber& contextLine,
627 ContentSecurityPolicy::ReportingStatus reportingStatus) const { 630 ContentSecurityPolicy::ReportingStatus reportingStatus) const {
628 return isAllowedByAll<&CSPDirectiveList::allowJavaScriptURLs>( 631 return isAllowedByAll<&CSPDirectiveList::allowJavaScriptURLs>(
629 m_policies, element, contextURL, contextLine, reportingStatus); 632 m_policies, element, source, contextURL, contextLine, reportingStatus);
630 } 633 }
631 634
632 bool ContentSecurityPolicy::allowInlineEventHandler( 635 bool ContentSecurityPolicy::allowInlineEventHandler(
633 Element* element, 636 Element* element,
634 const String& source, 637 const String& source,
635 const String& contextURL, 638 const String& contextURL,
636 const WTF::OrdinalNumber& contextLine, 639 const WTF::OrdinalNumber& contextLine,
637 ContentSecurityPolicy::ReportingStatus reportingStatus) const { 640 ContentSecurityPolicy::ReportingStatus reportingStatus) const {
638 // Inline event handlers may be whitelisted by hash, if 641 // Inline event handlers may be whitelisted by hash, if
639 // 'unsafe-hash-attributes' is present in a policy. Check against the digest 642 // 'unsafe-hash-attributes' is present in a policy. Check against the digest
640 // of the |source| first before proceeding on to checking whether inline 643 // of the |source| first before proceeding on to checking whether inline
641 // script is allowed. 644 // script is allowed.
642 if (checkDigest<&CSPDirectiveList::allowScriptHash>( 645 if (checkDigest<&CSPDirectiveList::allowScriptHash>(
643 source, InlineType::Attribute, m_scriptHashAlgorithmsUsed, 646 source, InlineType::Attribute, m_scriptHashAlgorithmsUsed,
644 m_policies)) 647 m_policies))
645 return true; 648 return true;
646 return isAllowedByAll<&CSPDirectiveList::allowInlineEventHandlers>( 649 return isAllowedByAll<&CSPDirectiveList::allowInlineEventHandlers>(
647 m_policies, element, contextURL, contextLine, reportingStatus); 650 m_policies, element, source, contextURL, contextLine, reportingStatus);
648 } 651 }
649 652
650 bool ContentSecurityPolicy::allowInlineScript( 653 bool ContentSecurityPolicy::allowInlineScript(
651 Element* element, 654 Element* element,
652 const String& contextURL, 655 const String& contextURL,
653 const String& nonce, 656 const String& nonce,
654 const WTF::OrdinalNumber& contextLine, 657 const WTF::OrdinalNumber& contextLine,
655 const String& scriptContent, 658 const String& scriptContent,
656 ContentSecurityPolicy::ReportingStatus reportingStatus) const { 659 ContentSecurityPolicy::ReportingStatus reportingStatus) const {
657 DCHECK(element); 660 DCHECK(element);
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 static void gatherSecurityPolicyViolationEventData( 1039 static void gatherSecurityPolicyViolationEventData(
1037 SecurityPolicyViolationEventInit& init, 1040 SecurityPolicyViolationEventInit& init,
1038 ExecutionContext* context, 1041 ExecutionContext* context,
1039 const String& directiveText, 1042 const String& directiveText,
1040 const ContentSecurityPolicy::DirectiveType& effectiveType, 1043 const ContentSecurityPolicy::DirectiveType& effectiveType,
1041 const KURL& blockedURL, 1044 const KURL& blockedURL,
1042 const String& header, 1045 const String& header,
1043 RedirectStatus redirectStatus, 1046 RedirectStatus redirectStatus,
1044 ContentSecurityPolicyHeaderType headerType, 1047 ContentSecurityPolicyHeaderType headerType,
1045 ContentSecurityPolicy::ViolationType violationType, 1048 ContentSecurityPolicy::ViolationType violationType,
1046 int contextLine) { 1049 int contextLine,
1050 const String& scriptSource) {
1047 if (effectiveType == ContentSecurityPolicy::DirectiveType::FrameAncestors) { 1051 if (effectiveType == ContentSecurityPolicy::DirectiveType::FrameAncestors) {
1048 // If this load was blocked via 'frame-ancestors', then the URL of 1052 // If this load was blocked via 'frame-ancestors', then the URL of
1049 // |document| has not yet been initialized. In this case, we'll set both 1053 // |document| has not yet been initialized. In this case, we'll set both
1050 // 'documentURI' and 'blockedURI' to the blocked document's URL. 1054 // 'documentURI' and 'blockedURI' to the blocked document's URL.
1051 init.setDocumentURI(blockedURL.getString()); 1055 init.setDocumentURI(blockedURL.getString());
1052 init.setBlockedURI(blockedURL.getString()); 1056 init.setBlockedURI(blockedURL.getString());
1053 } else { 1057 } else {
1054 init.setDocumentURI(context->url().getString()); 1058 init.setDocumentURI(context->url().getString());
1055 switch (violationType) { 1059 switch (violationType) {
1056 case ContentSecurityPolicy::InlineViolation: 1060 case ContentSecurityPolicy::InlineViolation:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 } 1094 }
1091 1095
1092 std::unique_ptr<SourceLocation> location = SourceLocation::capture(context); 1096 std::unique_ptr<SourceLocation> location = SourceLocation::capture(context);
1093 if (location->lineNumber()) { 1097 if (location->lineNumber()) {
1094 KURL source = KURL(ParsedURLString, location->url()); 1098 KURL source = KURL(ParsedURLString, location->url());
1095 init.setSourceFile( 1099 init.setSourceFile(
1096 stripURLForUseInReport(context, source, redirectStatus, effectiveType)); 1100 stripURLForUseInReport(context, source, redirectStatus, effectiveType));
1097 init.setLineNumber(location->lineNumber()); 1101 init.setLineNumber(location->lineNumber());
1098 init.setColumnNumber(location->columnNumber()); 1102 init.setColumnNumber(location->columnNumber());
1099 } 1103 }
1104
1105 if (!scriptSource.isEmpty())
1106 init.setScriptSample(scriptSource.stripWhiteSpace().left(40));
1100 } 1107 }
1101 1108
1102 void ContentSecurityPolicy::reportViolation( 1109 void ContentSecurityPolicy::reportViolation(
1103 const String& directiveText, 1110 const String& directiveText,
1104 const DirectiveType& effectiveType, 1111 const DirectiveType& effectiveType,
1105 const String& consoleMessage, 1112 const String& consoleMessage,
1106 const KURL& blockedURL, 1113 const KURL& blockedURL,
1107 const Vector<String>& reportEndpoints, 1114 const Vector<String>& reportEndpoints,
1108 const String& header, 1115 const String& header,
1109 ContentSecurityPolicyHeaderType headerType, 1116 ContentSecurityPolicyHeaderType headerType,
1110 ViolationType violationType, 1117 ViolationType violationType,
1111 LocalFrame* contextFrame, 1118 LocalFrame* contextFrame,
1112 RedirectStatus redirectStatus, 1119 RedirectStatus redirectStatus,
1113 int contextLine, 1120 int contextLine,
1114 Element* element) { 1121 Element* element,
1122 const String& source) {
1115 ASSERT(violationType == URLViolation || blockedURL.isEmpty()); 1123 ASSERT(violationType == URLViolation || blockedURL.isEmpty());
1116 1124
1117 // TODO(lukasza): Support sending reports from OOPIFs - 1125 // TODO(lukasza): Support sending reports from OOPIFs -
1118 // https://crbug.com/611232 (or move CSP child-src and frame-src checks to the 1126 // https://crbug.com/611232 (or move CSP child-src and frame-src checks to the
1119 // browser process - see https://crbug.com/376522). 1127 // browser process - see https://crbug.com/376522).
1120 if (!m_executionContext && !contextFrame) { 1128 if (!m_executionContext && !contextFrame) {
1121 DCHECK(effectiveType == DirectiveType::ChildSrc || 1129 DCHECK(effectiveType == DirectiveType::ChildSrc ||
1122 effectiveType == DirectiveType::FrameSrc || 1130 effectiveType == DirectiveType::FrameSrc ||
1123 effectiveType == DirectiveType::PluginTypes); 1131 effectiveType == DirectiveType::PluginTypes);
1124 return; 1132 return;
1125 } 1133 }
1126 1134
1127 DCHECK((m_executionContext && !contextFrame) || 1135 DCHECK((m_executionContext && !contextFrame) ||
1128 ((effectiveType == DirectiveType::FrameAncestors) && contextFrame)); 1136 ((effectiveType == DirectiveType::FrameAncestors) && contextFrame));
1129 1137
1130 SecurityPolicyViolationEventInit violationData; 1138 SecurityPolicyViolationEventInit violationData;
1131 1139
1132 // If we're processing 'frame-ancestors', use |contextFrame|'s execution 1140 // If we're processing 'frame-ancestors', use |contextFrame|'s execution
1133 // context to gather data. Otherwise, use the policy's execution context. 1141 // context to gather data. Otherwise, use the policy's execution context.
1134 ExecutionContext* relevantContext = 1142 ExecutionContext* relevantContext =
1135 contextFrame ? contextFrame->document() : m_executionContext; 1143 contextFrame ? contextFrame->document() : m_executionContext;
1136 DCHECK(relevantContext); 1144 DCHECK(relevantContext);
1137 gatherSecurityPolicyViolationEventData( 1145 gatherSecurityPolicyViolationEventData(
1138 violationData, relevantContext, directiveText, effectiveType, blockedURL, 1146 violationData, relevantContext, directiveText, effectiveType, blockedURL,
1139 header, redirectStatus, headerType, violationType, contextLine); 1147 header, redirectStatus, headerType, violationType, contextLine, source);
1140 1148
1141 // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded 1149 // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded
1142 // resources should be allowed regardless. We apparently do, however, so 1150 // resources should be allowed regardless. We apparently do, however, so
1143 // we should at least stop spamming reporting endpoints. See 1151 // we should at least stop spamming reporting endpoints. See
1144 // https://crbug.com/524356 for detail. 1152 // https://crbug.com/524356 for detail.
1145 if (!violationData.sourceFile().isEmpty() && 1153 if (!violationData.sourceFile().isEmpty() &&
1146 SchemeRegistry::schemeShouldBypassContentSecurityPolicy( 1154 SchemeRegistry::schemeShouldBypassContentSecurityPolicy(
1147 KURL(ParsedURLString, violationData.sourceFile()).protocol())) { 1155 KURL(ParsedURLString, violationData.sourceFile()).protocol())) {
1148 return; 1156 return;
1149 } 1157 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1191 cspReport->setString("disposition", violationData.disposition()); 1199 cspReport->setString("disposition", violationData.disposition());
1192 cspReport->setString("blocked-uri", violationData.blockedURI()); 1200 cspReport->setString("blocked-uri", violationData.blockedURI());
1193 if (violationData.lineNumber()) 1201 if (violationData.lineNumber())
1194 cspReport->setInteger("line-number", violationData.lineNumber()); 1202 cspReport->setInteger("line-number", violationData.lineNumber());
1195 if (violationData.columnNumber()) 1203 if (violationData.columnNumber())
1196 cspReport->setInteger("column-number", violationData.columnNumber()); 1204 cspReport->setInteger("column-number", violationData.columnNumber());
1197 if (!violationData.sourceFile().isEmpty()) 1205 if (!violationData.sourceFile().isEmpty())
1198 cspReport->setString("source-file", violationData.sourceFile()); 1206 cspReport->setString("source-file", violationData.sourceFile());
1199 cspReport->setInteger("status-code", violationData.statusCode()); 1207 cspReport->setInteger("status-code", violationData.statusCode());
1200 1208
1209 if (experimentalFeaturesEnabled())
1210 cspReport->setString("script-sample", violationData.scriptSample());
1211
1201 std::unique_ptr<JSONObject> reportObject = JSONObject::create(); 1212 std::unique_ptr<JSONObject> reportObject = JSONObject::create();
1202 reportObject->setObject("csp-report", std::move(cspReport)); 1213 reportObject->setObject("csp-report", std::move(cspReport));
1203 String stringifiedReport = reportObject->toJSONString(); 1214 String stringifiedReport = reportObject->toJSONString();
1204 1215
1205 // Only POST unique reports to the external endpoint; repeated reports add no 1216 // Only POST unique reports to the external endpoint; repeated reports add no
1206 // value on the server side, as they're indistinguishable. Note that we'll 1217 // value on the server side, as they're indistinguishable. Note that we'll
1207 // fire the DOM event for every violation, as the page has enough context to 1218 // fire the DOM event for every violation, as the page has enough context to
1208 // react in some reasonable way to each violation as it occurs. 1219 // react in some reasonable way to each violation as it occurs.
1209 if (shouldSendViolationReport(stringifiedReport)) { 1220 if (shouldSendViolationReport(stringifiedReport)) {
1210 didSendViolationReport(stringifiedReport); 1221 didSendViolationReport(stringifiedReport);
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 CSPDirectiveListVector otherVector; 1639 CSPDirectiveListVector otherVector;
1629 for (const auto& policy : other.m_policies) { 1640 for (const auto& policy : other.m_policies) {
1630 if (!policy->isReportOnly()) 1641 if (!policy->isReportOnly())
1631 otherVector.push_back(policy); 1642 otherVector.push_back(policy);
1632 } 1643 }
1633 1644
1634 return m_policies[0]->subsumes(otherVector); 1645 return m_policies[0]->subsumes(otherVector);
1635 } 1646 }
1636 1647
1637 } // namespace blink 1648 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698