bool matches(const KURL&);
bool allowInline() const { return m_allowInline; }
- bool allowEval() const { return m_allowEval; }
+ bool allowScriptEval() const { return m_allowScriptEval; }
bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_nonces.contains(nonce); }
bool allowHash(const SourceHashValue& hashValue) const { return m_hashes.contains(hashValue); }
uint8_t hashAlgorithmsUsed() const { return m_hashAlgorithmsUsed; }
String m_directiveName;
bool m_allowStar;
bool m_allowInline;
- bool m_allowEval;
+ bool m_allowScriptEval;
HashSet<String> m_nonces;
HashSet<SourceHashValue> m_hashes;
uint8_t m_hashAlgorithmsUsed;
, m_directiveName(directiveName)
, m_allowStar(false)
, m_allowInline(false)
- , m_allowEval(false)
+ , m_allowScriptEval(false)
, m_hashAlgorithmsUsed(0)
{
}
void CSPSourceList::addSourceUnsafeEval()
{
- m_allowEval = true;
+ m_allowScriptEval = true;
}
void CSPSourceList::addSourceNonce(const String& nonce)
}
bool allowInline() const { return m_sourceList.allowInline(); }
- bool allowEval() const { return m_sourceList.allowEval(); }
+ bool allowScriptEval() const { return m_sourceList.allowScriptEval(); }
bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce(nonce.stripWhiteSpace()); }
bool allowHash(const SourceHashValue& hashValue) const { return m_sourceList.allowHash(hashValue); }
bool isHashOrNoncePresent() const { return m_sourceList.isHashOrNoncePresent(); }
bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const;
- bool allowEval(ScriptState*, ContentSecurityPolicy::ReportingStatus) const;
+ bool allowScriptEval(ScriptState*, ContentSecurityPolicy::ReportingStatus) const;
+ bool allowStyleEval(ScriptState*, ContentSecurityPolicy::ReportingStatus) const;
bool allowPluginType(const String& type, const String& typeAttribute, const KURL&, ContentSecurityPolicy::ReportingStatus) const;
bool allowScriptFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const;
bool allowStyleHash(const SourceHashValue&) const;
const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
+ const String& styleEvalDisabledErrorMessage() const { return m_styleEvalDisabledErrorMessage; }
ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflectedXSSDisposition; }
ReferrerPolicy referrerPolicy() const { return m_referrerPolicy; }
bool didSetReferrerPolicy() const { return m_didSetReferrerPolicy; }
bool checkAncestors(SourceListDirective*, Frame*) const;
void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisabledErrorMessage = errorMessage; }
+ void setStyleEvalDisabledErrorMessage(const String& errorMessage) { m_styleEvalDisabledErrorMessage = errorMessage; }
bool checkEvalAndReportViolation(SourceListDirective*, const String& consoleMessage, ScriptState*) const;
bool checkInlineAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
Vector<KURL> m_reportURIs;
String m_evalDisabledErrorMessage;
+ String m_styleEvalDisabledErrorMessage;
};
CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurityPolicy::HeaderType type, ContentSecurityPolicy::HeaderSource source)
OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy, type, source));
directives->parse(begin, end);
- if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
- String message = "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_scriptSrc.get())->text() + "\".\n";
- directives->setEvalDisabledErrorMessage(message);
- }
+ if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get())))
+ directives->setEvalDisabledErrorMessage("Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_scriptSrc.get())->text() + "\".\n");
+ if (!directives->checkEval(directives->operativeDirective(directives->m_styleSrc.get())))
+ directives->setStyleEvalDisabledErrorMessage("Refused to evaluate a string as CSS because 'unsafe-eval' is not an allowed source of style in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_styleSrc.get())->text() + "\".\n");
if (directives->isReportOnly() && directives->reportURIs().isEmpty())
policy->reportMissingReportURI(String(begin, end - begin));
bool CSPDirectiveList::checkEval(SourceListDirective* directive) const
{
- return !directive || directive->allowEval();
+ return !directive || directive->allowScriptEval();
}
bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
checkInline(operativeDirective(m_styleSrc.get()));
}
-bool CSPDirectiveList::allowEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+bool CSPDirectiveList::allowScriptEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
{
DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "));
checkEval(operativeDirective(m_scriptSrc.get()));
}
+bool CSPDirectiveList::allowStyleEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate a string as CSS because 'unsafe-eval' is not an allowed source of style in the following Content Security Policy directive: "));
+
+ return reportingStatus == ContentSecurityPolicy::SendReport ?
+ checkEvalAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, state) :
+ checkEval(operativeDirective(m_styleSrc.get()));
+}
+
bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
{
return reportingStatus == ContentSecurityPolicy::SendReport ?
didReceiveHeader(headers.contentSecurityPolicy(), ContentSecurityPolicy::Enforce, ContentSecurityPolicy::HeaderSourceHTTP);
if (!headers.contentSecurityPolicyReportOnly().isEmpty())
didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecurityPolicy::Report, ContentSecurityPolicy::HeaderSourceHTTP);
-
- // FIXME: Remove this reporting (and the 'xWebKitCSP*' methods) after the next release branch.
- if (m_client->isDocument()) {
- Document* document = static_cast<Document*>(m_client);
- if (!headers.xWebKitCSP().isEmpty())
- UseCounter::countDeprecation(*document, UseCounter::PrefixedContentSecurityPolicy);
- if (!headers.xWebKitCSPReportOnly().isEmpty())
- UseCounter::countDeprecation(*document, UseCounter::PrefixedContentSecurityPolicyReportOnly);
- }
}
void ContentSecurityPolicy::didReceiveHeader(const String& header, HeaderType type, HeaderSource source)
void ContentSecurityPolicy::addPolicyFromHeaderValue(const String& header, HeaderType type, HeaderSource source)
{
- Document* document = 0;
- if (m_client->isDocument()) {
- document = static_cast<Document*>(m_client);
+ Document* document = this->document();
+ if (document) {
UseCounter::count(*document, getUseCounterType(type));
// CSP 1.1 defines report-only in a <meta> element as invalid. Measure for now, disable in experimental mode.
OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin, position, type, source);
// We disable 'eval()' even in the case of report-only policies, and rely on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread callback to determine whether the call should execute or not.
- if (!policy->allowEval(0, SuppressReport))
+ if (!policy->allowScriptEval(0, SuppressReport))
m_client->disableEval(policy->evalDisabledErrorMessage());
m_policies.append(policy.release());
return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus);
}
-bool ContentSecurityPolicy::allowEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+bool ContentSecurityPolicy::allowScriptEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+ return isAllowedByAllWithState<&CSPDirectiveList::allowScriptEval>(m_policies, state, reportingStatus);
+}
+
+bool ContentSecurityPolicy::allowStyleEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const
{
- return isAllowedByAllWithState<&CSPDirectiveList::allowEval>(m_policies, state, reportingStatus);
+ if (!experimentalFeaturesEnabled()) {
+ if (Document* document = this->document())
+ UseCounter::count(*document, UseCounter::UnsafeEvalBlocksCSSOM);
+ return true;
+ }
+ return isAllowedByAllWithState<&CSPDirectiveList::allowStyleEval>(m_policies, state, reportingStatus);
}
String ContentSecurityPolicy::evalDisabledErrorMessage() const
{
for (size_t i = 0; i < m_policies.size(); ++i) {
- if (!m_policies[i]->allowEval(0, SuppressReport))
+ if (!m_policies[i]->allowScriptEval(0, SuppressReport))
return m_policies[i]->evalDisabledErrorMessage();
}
return String();
}
+String ContentSecurityPolicy::styleEvalDisabledErrorMessage() const
+{
+ for (size_t i = 0; i < m_policies.size(); ++i) {
+ if (!m_policies[i]->allowStyleEval(0, SuppressReport))
+ return m_policies[i]->styleEvalDisabledErrorMessage();
+ }
+ return String();
+}
+
bool ContentSecurityPolicy::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
{
for (size_t i = 0; i < m_policies.size(); ++i) {
return isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, reportingStatus);
}
+bool ContentSecurityPolicy::allowWorkerContextFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
+{
+ // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure the impact of this backwards-incompatible change.
+ if (m_client->isDocument()) {
+ Document* document = static_cast<Document*>(m_client);
+ UseCounter::count(*document, UseCounter::WorkerSubjectToCSP);
+ if (isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, SuppressReport) && !isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, SuppressReport))
+ UseCounter::count(*document, UseCounter::WorkerAllowedByChildBlockedByScript);
+ }
+
+ return experimentalFeaturesEnabled() ?
+ isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, reportingStatus) :
+ isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, reportingStatus);
+}
+
bool ContentSecurityPolicy::isActive() const
{
return !m_policies.isEmpty();
void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const
{
- if (m_client->isDocument())
- static_cast<Document*>(m_client)->enforceSandboxFlags(mask);
+ if (Document* document = this->document())
+ document->enforceSandboxFlags(mask);
}
static String stripURLForUseInReport(Document* document, const KURL& url)
if (!m_client->isDocument())
return;
- Document* document = static_cast<Document*>(m_client);
+ Document* document = this->document();
Frame* frame = document->frame();
if (!frame)
return;
logToConsole("The report-only Content Security Policy '" + header + "' was delivered via a <meta> element, which is disallowed. The policy has been ignored.");
}
+void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) const
+{
+ 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.");
+}
+
void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) const
{
logToConsole("The Content Security Policy directive '" + name + "' is ignored when delivered in a report-only policy.");