| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 // https://w3c.github.io/webappsec/specs/content-security-policy | 91 // https://w3c.github.io/webappsec/specs/content-security-policy |
| 92 const char ContentSecurityPolicy::ManifestSrc[] = "manifest-src"; | 92 const char ContentSecurityPolicy::ManifestSrc[] = "manifest-src"; |
| 93 | 93 |
| 94 // Mixed Content Directive | 94 // Mixed Content Directive |
| 95 // https://w3c.github.io/webappsec/specs/mixedcontent/#strict-mode | 95 // https://w3c.github.io/webappsec/specs/mixedcontent/#strict-mode |
| 96 const char ContentSecurityPolicy::BlockAllMixedContent[] = "block-all-mixed-cont
ent"; | 96 const char ContentSecurityPolicy::BlockAllMixedContent[] = "block-all-mixed-cont
ent"; |
| 97 | 97 |
| 98 // https://w3c.github.io/webappsec/specs/upgrade/ | 98 // https://w3c.github.io/webappsec/specs/upgrade/ |
| 99 const char ContentSecurityPolicy::UpgradeInsecureRequests[] = "upgrade-insecure-
requests"; | 99 const char ContentSecurityPolicy::UpgradeInsecureRequests[] = "upgrade-insecure-
requests"; |
| 100 | 100 |
| 101 // Suborigin Directive |
| 102 // https://metromoxie.github.io/webappsec/specs/suborigins/index.html |
| 103 const char ContentSecurityPolicy::Suborigin[] = "suborigin"; |
| 104 |
| 101 bool ContentSecurityPolicy::isDirectiveName(const String& name) | 105 bool ContentSecurityPolicy::isDirectiveName(const String& name) |
| 102 { | 106 { |
| 103 return (equalIgnoringCase(name, ConnectSrc) | 107 return (equalIgnoringCase(name, ConnectSrc) |
| 104 || equalIgnoringCase(name, DefaultSrc) | 108 || equalIgnoringCase(name, DefaultSrc) |
| 105 || equalIgnoringCase(name, FontSrc) | 109 || equalIgnoringCase(name, FontSrc) |
| 106 || equalIgnoringCase(name, FrameSrc) | 110 || equalIgnoringCase(name, FrameSrc) |
| 107 || equalIgnoringCase(name, ImgSrc) | 111 || equalIgnoringCase(name, ImgSrc) |
| 108 || equalIgnoringCase(name, MediaSrc) | 112 || equalIgnoringCase(name, MediaSrc) |
| 109 || equalIgnoringCase(name, ObjectSrc) | 113 || equalIgnoringCase(name, ObjectSrc) |
| 110 || equalIgnoringCase(name, ReportURI) | 114 || equalIgnoringCase(name, ReportURI) |
| 111 || equalIgnoringCase(name, Sandbox) | 115 || equalIgnoringCase(name, Sandbox) |
| 116 || equalIgnoringCase(name, Suborigin) |
| 112 || equalIgnoringCase(name, ScriptSrc) | 117 || equalIgnoringCase(name, ScriptSrc) |
| 113 || equalIgnoringCase(name, StyleSrc) | 118 || equalIgnoringCase(name, StyleSrc) |
| 114 || equalIgnoringCase(name, BaseURI) | 119 || equalIgnoringCase(name, BaseURI) |
| 115 || equalIgnoringCase(name, ChildSrc) | 120 || equalIgnoringCase(name, ChildSrc) |
| 116 || equalIgnoringCase(name, FormAction) | 121 || equalIgnoringCase(name, FormAction) |
| 117 || equalIgnoringCase(name, FrameAncestors) | 122 || equalIgnoringCase(name, FrameAncestors) |
| 118 || equalIgnoringCase(name, PluginTypes) | 123 || equalIgnoringCase(name, PluginTypes) |
| 119 || equalIgnoringCase(name, ReflectedXSS) | 124 || equalIgnoringCase(name, ReflectedXSS) |
| 120 || equalIgnoringCase(name, Referrer) | 125 || equalIgnoringCase(name, Referrer) |
| 121 || equalIgnoringCase(name, ManifestSrc) | 126 || equalIgnoringCase(name, ManifestSrc) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 141 return ReferrerPolicyNever; | 146 return ReferrerPolicyNever; |
| 142 return a; | 147 return a; |
| 143 } | 148 } |
| 144 | 149 |
| 145 ContentSecurityPolicy::ContentSecurityPolicy() | 150 ContentSecurityPolicy::ContentSecurityPolicy() |
| 146 : m_executionContext(nullptr) | 151 : m_executionContext(nullptr) |
| 147 , m_overrideInlineStyleAllowed(false) | 152 , m_overrideInlineStyleAllowed(false) |
| 148 , m_scriptHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) | 153 , m_scriptHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) |
| 149 , m_styleHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) | 154 , m_styleHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) |
| 150 , m_sandboxMask(0) | 155 , m_sandboxMask(0) |
| 156 , m_suboriginName(String()) |
| 151 , m_enforceStrictMixedContentChecking(false) | 157 , m_enforceStrictMixedContentChecking(false) |
| 152 , m_referrerPolicy(ReferrerPolicyDefault) | 158 , m_referrerPolicy(ReferrerPolicyDefault) |
| 153 , m_insecureRequestsPolicy(SecurityContext::InsecureRequestsDoNotUpgrade) | 159 , m_insecureRequestsPolicy(SecurityContext::InsecureRequestsDoNotUpgrade) |
| 154 { | 160 { |
| 155 } | 161 } |
| 156 | 162 |
| 157 void ContentSecurityPolicy::bindToExecutionContext(ExecutionContext* executionCo
ntext) | 163 void ContentSecurityPolicy::bindToExecutionContext(ExecutionContext* executionCo
ntext) |
| 158 { | 164 { |
| 159 m_executionContext = executionContext; | 165 m_executionContext = executionContext; |
| 160 applyPolicySideEffectsToExecutionContext(); | 166 applyPolicySideEffectsToExecutionContext(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 173 | 179 |
| 174 // If we're in a Document, set mixed content checking and sandbox | 180 // If we're in a Document, set mixed content checking and sandbox |
| 175 // flags, then dump all the parsing error messages, then poke at histograms. | 181 // flags, then dump all the parsing error messages, then poke at histograms. |
| 176 if (Document* document = this->document()) { | 182 if (Document* document = this->document()) { |
| 177 if (m_sandboxMask != SandboxNone) { | 183 if (m_sandboxMask != SandboxNone) { |
| 178 UseCounter::count(document, UseCounter::SandboxViaCSP); | 184 UseCounter::count(document, UseCounter::SandboxViaCSP); |
| 179 document->enforceSandboxFlags(m_sandboxMask); | 185 document->enforceSandboxFlags(m_sandboxMask); |
| 180 } | 186 } |
| 181 if (m_enforceStrictMixedContentChecking) | 187 if (m_enforceStrictMixedContentChecking) |
| 182 document->enforceStrictMixedContentChecking(); | 188 document->enforceStrictMixedContentChecking(); |
| 189 if (RuntimeEnabledFeatures::suboriginsEnabled()) { |
| 190 document->enforceSuborigin(m_suboriginName); |
| 191 } |
| 183 if (m_insecureRequestsPolicy == SecurityContext::InsecureRequestsUpgrade
) { | 192 if (m_insecureRequestsPolicy == SecurityContext::InsecureRequestsUpgrade
) { |
| 184 UseCounter::count(document, UseCounter::UpgradeInsecureRequestsEnabl
ed); | 193 UseCounter::count(document, UseCounter::UpgradeInsecureRequestsEnabl
ed); |
| 185 document->setInsecureRequestsPolicy(m_insecureRequestsPolicy); | 194 document->setInsecureRequestsPolicy(m_insecureRequestsPolicy); |
| 186 if (!securityOrigin()->host().isNull()) | 195 if (!securityOrigin()->host().isNull()) |
| 187 document->addInsecureNavigationUpgrade(securityOrigin()->host().
impl()->hash()); | 196 document->addInsecureNavigationUpgrade(securityOrigin()->host().
impl()->hash()); |
| 188 } | 197 } |
| 189 | 198 |
| 190 for (const auto& consoleMessage : m_consoleMessages) | 199 for (const auto& consoleMessage : m_consoleMessages) |
| 191 m_executionContext->addConsoleMessage(consoleMessage); | 200 m_executionContext->addConsoleMessage(consoleMessage); |
| 192 m_consoleMessages.clear(); | 201 m_consoleMessages.clear(); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 { | 657 { |
| 649 m_enforceStrictMixedContentChecking = true; | 658 m_enforceStrictMixedContentChecking = true; |
| 650 } | 659 } |
| 651 | 660 |
| 652 void ContentSecurityPolicy::setInsecureRequestsPolicy(SecurityContext::InsecureR
equestsPolicy policy) | 661 void ContentSecurityPolicy::setInsecureRequestsPolicy(SecurityContext::InsecureR
equestsPolicy policy) |
| 653 { | 662 { |
| 654 if (policy > m_insecureRequestsPolicy) | 663 if (policy > m_insecureRequestsPolicy) |
| 655 m_insecureRequestsPolicy = policy; | 664 m_insecureRequestsPolicy = policy; |
| 656 } | 665 } |
| 657 | 666 |
| 667 void ContentSecurityPolicy::enforceSuborigin(const String& name) |
| 668 { |
| 669 m_suboriginName = name; |
| 670 } |
| 671 |
| 658 static String stripURLForUseInReport(Document* document, const KURL& url) | 672 static String stripURLForUseInReport(Document* document, const KURL& url) |
| 659 { | 673 { |
| 660 if (!url.isValid()) | 674 if (!url.isValid()) |
| 661 return String(); | 675 return String(); |
| 662 if (!url.isHierarchical() || url.protocolIs("file")) | 676 if (!url.isHierarchical() || url.protocolIs("file")) |
| 663 return url.protocol(); | 677 return url.protocol(); |
| 664 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); | 678 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); |
| 665 } | 679 } |
| 666 | 680 |
| 667 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) | 681 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) | 791 void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) |
| 778 { | 792 { |
| 779 logToConsole("The report-only Content Security Policy '" + header + "' was d
elivered via a <meta> element, which is disallowed. The policy has been ignored.
"); | 793 logToConsole("The report-only Content Security Policy '" + header + "' was d
elivered via a <meta> element, which is disallowed. The policy has been ignored.
"); |
| 780 } | 794 } |
| 781 | 795 |
| 782 void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) | 796 void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) |
| 783 { | 797 { |
| 784 logToConsole("The Content Security Policy '" + header + "' was delivered via
a <meta> element outside the document's <head>, which is disallowed. The policy
has been ignored."); | 798 logToConsole("The Content Security Policy '" + header + "' was delivered via
a <meta> element outside the document's <head>, which is disallowed. The policy
has been ignored."); |
| 785 } | 799 } |
| 786 | 800 |
| 801 void ContentSecurityPolicy::reportSuboriginInMeta(const String& suboriginName) |
| 802 { |
| 803 logToConsole("The Suborigin name '" + suboriginName + "' was delivered via a
Content Security Policy in a <meta> element and not an HTTP header, which is di
sallowed. The Suborigin has been ignored."); |
| 804 } |
| 805 |
| 787 void ContentSecurityPolicy::reportValueForEmptyDirective(const String& name, con
st String& value) | 806 void ContentSecurityPolicy::reportValueForEmptyDirective(const String& name, con
st String& value) |
| 788 { | 807 { |
| 789 logToConsole("The Content Security Policy directive '" + name + "' should be
empty, but was delivered with a value of '" + value + "'. The directive has bee
n applied, and the value ignored."); | 808 logToConsole("The Content Security Policy directive '" + name + "' should be
empty, but was delivered with a value of '" + value + "'. The directive has bee
n applied, and the value ignored."); |
| 790 } | 809 } |
| 791 | 810 |
| 792 void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) | 811 void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) |
| 793 { | 812 { |
| 794 logToConsole("The Content Security Policy directive '" + name + "' is ignore
d when delivered in a report-only policy."); | 813 logToConsole("The Content Security Policy directive '" + name + "' is ignore
d when delivered in a report-only policy."); |
| 795 } | 814 } |
| 796 | 815 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 else | 860 else |
| 842 message = "Invalid plugin type in 'plugin-types' Content Security Policy
directive: '" + pluginType + "'.\n"; | 861 message = "Invalid plugin type in 'plugin-types' Content Security Policy
directive: '" + pluginType + "'.\n"; |
| 843 logToConsole(message); | 862 logToConsole(message); |
| 844 } | 863 } |
| 845 | 864 |
| 846 void ContentSecurityPolicy::reportInvalidSandboxFlags(const String& invalidFlags
) | 865 void ContentSecurityPolicy::reportInvalidSandboxFlags(const String& invalidFlags
) |
| 847 { | 866 { |
| 848 logToConsole("Error while parsing the 'sandbox' Content Security Policy dire
ctive: " + invalidFlags); | 867 logToConsole("Error while parsing the 'sandbox' Content Security Policy dire
ctive: " + invalidFlags); |
| 849 } | 868 } |
| 850 | 869 |
| 870 void ContentSecurityPolicy::reportInvalidSuboriginFlags(const String& invalidFla
gs) |
| 871 { |
| 872 logToConsole("Error while parsing the 'suborigin' Content Security Policy di
rective: " + invalidFlags); |
| 873 } |
| 874 |
| 851 void ContentSecurityPolicy::reportInvalidReflectedXSS(const String& invalidValue
) | 875 void ContentSecurityPolicy::reportInvalidReflectedXSS(const String& invalidValue
) |
| 852 { | 876 { |
| 853 logToConsole("The 'reflected-xss' Content Security Policy directive has the
invalid value \"" + invalidValue + "\". Valid values are \"allow\", \"filter\",
and \"block\"."); | 877 logToConsole("The 'reflected-xss' Content Security Policy directive has the
invalid value \"" + invalidValue + "\". Valid values are \"allow\", \"filter\",
and \"block\"."); |
| 854 } | 878 } |
| 855 | 879 |
| 856 void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter(const String& d
irectiveName, const String& value) | 880 void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter(const String& d
irectiveName, const String& value) |
| 857 { | 881 { |
| 858 String message = "The value for Content Security Policy directive '" + direc
tiveName + "' contains an invalid character: '" + value + "'. Non-whitespace cha
racters outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC 398
6, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1."; | 882 String message = "The value for Content Security Policy directive '" + direc
tiveName + "' contains an invalid character: '" + value + "'. Non-whitespace cha
racters outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC 398
6, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1."; |
| 859 logToConsole(message); | 883 logToConsole(message); |
| 860 } | 884 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. | 993 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. |
| 970 return !m_violationReportsSent.contains(report.impl()->hash()); | 994 return !m_violationReportsSent.contains(report.impl()->hash()); |
| 971 } | 995 } |
| 972 | 996 |
| 973 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 997 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
| 974 { | 998 { |
| 975 m_violationReportsSent.add(report.impl()->hash()); | 999 m_violationReportsSent.add(report.impl()->hash()); |
| 976 } | 1000 } |
| 977 | 1001 |
| 978 } // namespace blink | 1002 } // namespace blink |
| OLD | NEW |