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