/* * Copyright (C) 2011 Google, Inc. All rights reserved. * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "ContentSecurityPolicyDirectiveList.h" #include "ParsingUtilities.h" #include "SecurityContext.h" #include namespace WebCore { // CSP 1.0 Directives static const char connectSrc[] = "connect-src"; static const char defaultSrc[] = "default-src"; static const char fontSrc[] = "font-src"; static const char frameSrc[] = "frame-src"; static const char imgSrc[] = "img-src"; static const char mediaSrc[] = "media-src"; static const char objectSrc[] = "object-src"; static const char reportURI[] = "report-uri"; static const char sandbox[] = "sandbox"; static const char scriptSrc[] = "script-src"; static const char styleSrc[] = "style-src"; // CSP 1.1 Directives static const char baseURI[] = "base-uri"; static const char childSrc[] = "child-src"; static const char formAction[] = "form-action"; static const char pluginTypes[] = "plugin-types"; #if ENABLE(CSP_NEXT) static const char reflectedXSS[] = "reflected-xss"; #endif #if ENABLE(CSP_NEXT) static inline bool isExperimentalDirectiveName(const String& name) { return equalLettersIgnoringASCIICase(name, reflectedXSS); } #else static inline bool isExperimentalDirectiveName(const String&) { return false; } #endif bool isCSPDirectiveName(const String& name) { return equalLettersIgnoringASCIICase(name, baseURI) || equalLettersIgnoringASCIICase(name, connectSrc) || equalLettersIgnoringASCIICase(name, defaultSrc) || equalLettersIgnoringASCIICase(name, fontSrc) || equalLettersIgnoringASCIICase(name, formAction) || equalLettersIgnoringASCIICase(name, frameSrc) || equalLettersIgnoringASCIICase(name, imgSrc) || equalLettersIgnoringASCIICase(name, mediaSrc) || equalLettersIgnoringASCIICase(name, objectSrc) || equalLettersIgnoringASCIICase(name, pluginTypes) || equalLettersIgnoringASCIICase(name, reportURI) || equalLettersIgnoringASCIICase(name, sandbox) || equalLettersIgnoringASCIICase(name, scriptSrc) || equalLettersIgnoringASCIICase(name, styleSrc) || isExperimentalDirectiveName(name); } static bool isDirectiveNameCharacter(UChar c) { return isASCIIAlphanumeric(c) || c == '-'; } static bool isDirectiveValueCharacter(UChar c) { return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR } static bool isNotASCIISpace(UChar c) { return !isASCIISpace(c); } static inline bool checkEval(ContentSecurityPolicySourceListDirective* directive) { return !directive || directive->allowEval(); } static inline bool checkInline(ContentSecurityPolicySourceListDirective* directive) { return !directive || directive->allowInline(); } static inline bool checkSource(ContentSecurityPolicySourceListDirective* directive, const URL& url) { return !directive || directive->allows(url); } static inline bool checkHash(ContentSecurityPolicySourceListDirective* directive, const ContentSecurityPolicyHash& hash) { return !directive || directive->allows(hash); } static inline bool checkNonce(ContentSecurityPolicySourceListDirective* directive, const String& nonce) { return !directive || directive->allows(nonce); } static inline bool checkMediaType(ContentSecurityPolicyMediaListDirective* directive, const String& type, const String& typeAttribute) { if (!directive) return true; if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) return false; return directive->allows(type); } ContentSecurityPolicyDirectiveList::ContentSecurityPolicyDirectiveList(ContentSecurityPolicy& policy, ContentSecurityPolicyHeaderType type) : m_policy(policy) , m_headerType(type) , m_reportOnly(false) , m_haveSandboxPolicy(false) , m_reflectedXSSDisposition(ContentSecurityPolicy::ReflectedXSSUnset) { m_reportOnly = (type == ContentSecurityPolicyHeaderType::Report || type == ContentSecurityPolicyHeaderType::PrefixedReport); } std::unique_ptr ContentSecurityPolicyDirectiveList::create(ContentSecurityPolicy& policy, const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicy::PolicyFrom from) { auto directives = std::make_unique(policy, type); directives->parse(header, from); if (!checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) { String message = makeString("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->isReportOnly() && directives->reportURIs().isEmpty()) policy.reportMissingReportURI(header); return directives; } void ContentSecurityPolicyDirectiveList::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const URL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine, JSC::ExecState* state) const { String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage; m_policy.reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header, contextURL, contextLine, state); } ContentSecurityPolicySourceListDirective* ContentSecurityPolicyDirectiveList::operativeDirective(ContentSecurityPolicySourceListDirective* directive) const { return directive ? directive : m_defaultSrc.get(); } bool ContentSecurityPolicyDirectiveList::checkEvalAndReportViolation(ContentSecurityPolicySourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, JSC::ExecState* state) const { if (checkEval(directive)) return true; String suffix = String(); if (directive == m_defaultSrc.get()) suffix = " Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback."; reportViolation(directive->text(), scriptSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", URL(), contextURL, contextLine, state); if (!m_reportOnly) { m_policy.reportBlockedScriptExecutionToInspector(directive->text()); return false; } return true; } bool ContentSecurityPolicyDirectiveList::checkMediaTypeAndReportViolation(ContentSecurityPolicyMediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const { if (checkMediaType(directive, type, typeAttribute)) return true; String message = makeString(consoleMessage, '\'', directive->text(), "\'."); if (typeAttribute.isEmpty()) message = message + " When enforcing the 'plugin-types' directive, the plugin's media type must be explicitly declared with a 'type' attribute on the containing element (e.g. '')."; reportViolation(directive->text(), pluginTypes, message + "\n", URL()); return denyIfEnforcingPolicy(); } bool ContentSecurityPolicyDirectiveList::checkInlineAndReportViolation(ContentSecurityPolicySourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const { if (checkInline(directive)) return true; String suffix = String(); if (directive == m_defaultSrc.get()) suffix = makeString(" Note that '", (isScript ? "script" : "style"), "-src' was not explicitly set, so 'default-src' is used as a fallback."); reportViolation(directive->text(), isScript ? scriptSrc : styleSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", URL(), contextURL, contextLine); if (!m_reportOnly) { if (isScript) m_policy.reportBlockedScriptExecutionToInspector(directive->text()); return false; } return true; } bool ContentSecurityPolicyDirectiveList::checkSourceAndReportViolation(ContentSecurityPolicySourceListDirective* directive, const URL& url, const String& effectiveDirective) const { if (checkSource(directive, url)) return true; const char* prefix; if (baseURI == effectiveDirective) prefix = "Refused to set the document's base URI to '"; else if (childSrc == effectiveDirective) prefix = "Refused to create a child context containing '"; else if (connectSrc == effectiveDirective) prefix = "Refused to connect to '"; else if (fontSrc == effectiveDirective) prefix = "Refused to load the font '"; else if (formAction == effectiveDirective) prefix = "Refused to send form data to '"; else if (frameSrc == effectiveDirective) prefix = "Refused to load frame '"; else if (imgSrc == effectiveDirective) prefix = "Refused to load the image '"; else if (mediaSrc == effectiveDirective) prefix = "Refused to load media from '"; else if (objectSrc == effectiveDirective) prefix = "Refused to load plugin data from '"; else if (scriptSrc == effectiveDirective) prefix = "Refused to load the script '"; else if (styleSrc == effectiveDirective) prefix = "Refused to load the stylesheet '"; else prefix = ""; String suffix; if (directive == m_defaultSrc.get()) suffix = " Note that '" + effectiveDirective + "' was not explicitly set, so 'default-src' is used as a fallback."; reportViolation(directive->text(), effectiveDirective, makeString(prefix, url.stringCenterEllipsizedToLength(), "' because it violates the following Content Security Policy directive: \"", directive->text(), "\".", suffix, '\n'), url); return denyIfEnforcingPolicy(); } bool ContentSecurityPolicyDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const { static NeverDestroyed consoleMessage(ASCIILiteral("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: ")); if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true); return m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get())); } bool ContentSecurityPolicyDirectiveList::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const { static NeverDestroyed consoleMessage(ASCIILiteral("Refused to execute inline event handler because it violates the following Content Security Policy directive: ")); if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true); return m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get())); } bool ContentSecurityPolicyDirectiveList::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const { static NeverDestroyed consoleMessage(ASCIILiteral("Refused to execute inline script because it violates the following Content Security Policy directive: ")); if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true); return m_reportOnly || checkInline(operativeDirective(m_scriptSrc.get())); } bool ContentSecurityPolicyDirectiveList::allowInlineScriptWithHash(const ContentSecurityPolicyHash& hash) const { return checkHash(operativeDirective(m_scriptSrc.get()), hash); } bool ContentSecurityPolicyDirectiveList::allowScriptWithNonce(const String& nonce) const { return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); } bool ContentSecurityPolicyDirectiveList::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const { static NeverDestroyed consoleMessage(ASCIILiteral("Refused to apply inline style because it violates the following Content Security Policy directive: ")); if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkInlineAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, contextURL, contextLine, false); return m_reportOnly || checkInline(operativeDirective(m_styleSrc.get())); } bool ContentSecurityPolicyDirectiveList::allowInlineStyleWithHash(const ContentSecurityPolicyHash& hash) const { return checkHash(operativeDirective(m_styleSrc.get()), hash); } bool ContentSecurityPolicyDirectiveList::allowStyleWithNonce(const String& nonce) const { return checkNonce(operativeDirective(m_styleSrc.get()), nonce); } bool ContentSecurityPolicyDirectiveList::allowEval(JSC::ExecState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const { static NeverDestroyed consoleMessage(ASCIILiteral("Refused to evaluate script because it violates the following Content Security Policy directive: ")); if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, String(), WTF::OrdinalNumber::beforeFirst(), state); return m_reportOnly || checkEval(operativeDirective(m_scriptSrc.get())); } bool ContentSecurityPolicyDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.stringCenterEllipsizedToLength() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: "); return m_reportOnly || checkMediaType(m_pluginTypes.get(), type, typeAttribute); } bool ContentSecurityPolicyDirectiveList::allowScriptFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_scriptSrc.get()), url, scriptSrc); return m_reportOnly || checkSource(operativeDirective(m_scriptSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowObjectFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (url.isBlankURL()) return true; if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_objectSrc.get()), url, objectSrc); return m_reportOnly || checkSource(operativeDirective(m_objectSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowChildContextFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_childSrc.get()), url, childSrc); return m_reportOnly || checkSource(operativeDirective(m_childSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowChildFrameFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (url.isBlankURL()) return true; // We must enforce the frame-src directive (if specified) before enforcing the child-src directive for a nested browsing // context by (29 August 2015). ContentSecurityPolicySourceListDirective* directiveToEnforce = operativeDirective(m_frameSrc ? m_frameSrc.get() : m_childSrc.get()); if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(directiveToEnforce, url, frameSrc); return m_reportOnly || checkSource(directiveToEnforce, url); } bool ContentSecurityPolicyDirectiveList::allowImageFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_imgSrc.get()), url, imgSrc); return m_reportOnly || checkSource(operativeDirective(m_imgSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowStyleFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_styleSrc.get()), url, styleSrc); return m_reportOnly || checkSource(operativeDirective(m_styleSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowFontFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_fontSrc.get()), url, fontSrc); return m_reportOnly || checkSource(operativeDirective(m_fontSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowMediaFromSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_mediaSrc.get()), url, mediaSrc); return m_reportOnly || checkSource(operativeDirective(m_mediaSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowConnectToSource(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(operativeDirective(m_connectSrc.get()), url, connectSrc); return m_reportOnly || checkSource(operativeDirective(m_connectSrc.get()), url); } bool ContentSecurityPolicyDirectiveList::allowFormAction(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(m_formAction.get(), url, formAction); return m_reportOnly || checkSource(m_formAction.get(), url); } bool ContentSecurityPolicyDirectiveList::allowBaseURI(const URL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (reportingStatus == ContentSecurityPolicy::ReportingStatus::SendReport) return checkSourceAndReportViolation(m_baseURI.get(), url, baseURI); return m_reportOnly || checkSource(m_baseURI.get(), url); } // policy = directive-list // directive-list = [ directive *( ";" [ directive ] ) ] // void ContentSecurityPolicyDirectiveList::parse(const String& policy, ContentSecurityPolicy::PolicyFrom policyFrom) { m_header = policy; if (policy.isEmpty()) return; auto characters = StringView(policy).upconvertedCharacters(); const UChar* position = characters; const UChar* end = position + policy.length(); while (position < end) { const UChar* directiveBegin = position; skipUntil(position, end, ';'); String name, value; if (parseDirective(directiveBegin, position, name, value)) { ASSERT(!name.isEmpty()); switch (policyFrom) { case ContentSecurityPolicy::PolicyFrom::HTTPEquivMeta: if (equalLettersIgnoringASCIICase(name, sandbox) || equalLettersIgnoringASCIICase(name, reportURI)) { m_policy.reportInvalidDirectiveInHTTPEquivMeta(name); break; } FALLTHROUGH; default: addDirective(name, value); break; } } ASSERT(position == end || *position == ';'); skipExactly(position, end, ';'); } } // directive = *WSP [ directive-name [ WSP directive-value ] ] // directive-name = 1*( ALPHA / DIGIT / "-" ) // directive-value = *( WSP / ) // bool ContentSecurityPolicyDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value) { ASSERT(name.isEmpty()); ASSERT(value.isEmpty()); const UChar* position = begin; skipWhile(position, end); // Empty directive (e.g. ";;;"). Exit early. if (position == end) return false; const UChar* nameBegin = position; skipWhile(position, end); // The directive-name must be non-empty. if (nameBegin == position) { skipWhile(position, end); m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin)); return false; } name = String(nameBegin, position - nameBegin); if (position == end) return true; if (!skipExactly(position, end)) { skipWhile(position, end); m_policy.reportUnsupportedDirective(String(nameBegin, position - nameBegin)); return false; } skipWhile(position, end); const UChar* valueBegin = position; skipWhile(position, end); if (position != end) { m_policy.reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin)); return false; } // The directive-value may be empty. if (valueBegin == position) return true; value = String(valueBegin, position - valueBegin); return true; } void ContentSecurityPolicyDirectiveList::parseReportURI(const String& name, const String& value) { if (!m_reportURIs.isEmpty()) { m_policy.reportDuplicateDirective(name); return; } auto characters = StringView(value).upconvertedCharacters(); const UChar* position = characters; const UChar* end = position + value.length(); while (position < end) { skipWhile(position, end); const UChar* urlBegin = position; skipWhile(position, end); if (urlBegin < position) m_reportURIs.append(value.substring(urlBegin - characters, position - urlBegin)); } } template void ContentSecurityPolicyDirectiveList::setCSPDirective(const String& name, const String& value, std::unique_ptr& directive) { if (directive) { m_policy.reportDuplicateDirective(name); return; } directive = std::make_unique(name, value, m_policy); } void ContentSecurityPolicyDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy) { if (m_reportOnly) { m_policy.reportInvalidDirectiveInReportOnlyMode(name); return; } if (m_haveSandboxPolicy) { m_policy.reportDuplicateDirective(name); return; } m_haveSandboxPolicy = true; String invalidTokens; m_policy.enforceSandboxFlags(SecurityContext::parseSandboxPolicy(sandboxPolicy, invalidTokens)); if (!invalidTokens.isNull()) m_policy.reportInvalidSandboxFlags(invalidTokens); } void ContentSecurityPolicyDirectiveList::parseReflectedXSS(const String& name, const String& value) { if (m_reflectedXSSDisposition != ContentSecurityPolicy::ReflectedXSSUnset) { m_policy.reportDuplicateDirective(name); m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; return; } if (value.isEmpty()) { m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; m_policy.reportInvalidReflectedXSS(value); return; } auto characters = StringView(value).upconvertedCharacters(); const UChar* position = characters; const UChar* end = position + value.length(); skipWhile(position, end); const UChar* begin = position; skipWhile(position, end); // value1 // ^ if (equalLettersIgnoringASCIICase(begin, position - begin, "allow")) m_reflectedXSSDisposition = ContentSecurityPolicy::AllowReflectedXSS; else if (equalLettersIgnoringASCIICase(begin, position - begin, "filter")) m_reflectedXSSDisposition = ContentSecurityPolicy::FilterReflectedXSS; else if (equalLettersIgnoringASCIICase(begin, position - begin, "block")) m_reflectedXSSDisposition = ContentSecurityPolicy::BlockReflectedXSS; else { m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; m_policy.reportInvalidReflectedXSS(value); return; } skipWhile(position, end); if (position == end && m_reflectedXSSDisposition != ContentSecurityPolicy::ReflectedXSSUnset) return; // value1 value2 // ^ m_reflectedXSSDisposition = ContentSecurityPolicy::ReflectedXSSInvalid; m_policy.reportInvalidReflectedXSS(value); } void ContentSecurityPolicyDirectiveList::addDirective(const String& name, const String& value) { ASSERT(!name.isEmpty()); if (equalLettersIgnoringASCIICase(name, defaultSrc)) { setCSPDirective(name, value, m_defaultSrc); m_policy.addHashAlgorithmsForInlineScripts(m_defaultSrc->hashAlgorithmsUsed()); m_policy.addHashAlgorithmsForInlineStylesheets(m_defaultSrc->hashAlgorithmsUsed()); } else if (equalLettersIgnoringASCIICase(name, scriptSrc)) { setCSPDirective(name, value, m_scriptSrc); m_policy.addHashAlgorithmsForInlineScripts(m_scriptSrc->hashAlgorithmsUsed()); } else if (equalLettersIgnoringASCIICase(name, styleSrc)) { setCSPDirective(name, value, m_styleSrc); m_policy.addHashAlgorithmsForInlineStylesheets(m_styleSrc->hashAlgorithmsUsed()); } else if (equalLettersIgnoringASCIICase(name, objectSrc)) setCSPDirective(name, value, m_objectSrc); else if (equalLettersIgnoringASCIICase(name, frameSrc)) setCSPDirective(name, value, m_frameSrc); else if (equalLettersIgnoringASCIICase(name, imgSrc)) setCSPDirective(name, value, m_imgSrc); else if (equalLettersIgnoringASCIICase(name, fontSrc)) setCSPDirective(name, value, m_fontSrc); else if (equalLettersIgnoringASCIICase(name, mediaSrc)) setCSPDirective(name, value, m_mediaSrc); else if (equalLettersIgnoringASCIICase(name, connectSrc)) setCSPDirective(name, value, m_connectSrc); else if (equalLettersIgnoringASCIICase(name, childSrc)) setCSPDirective(name, value, m_childSrc); else if (equalLettersIgnoringASCIICase(name, formAction)) setCSPDirective(name, value, m_formAction); else if (equalLettersIgnoringASCIICase(name, baseURI)) setCSPDirective(name, value, m_baseURI); else if (equalLettersIgnoringASCIICase(name, pluginTypes)) setCSPDirective(name, value, m_pluginTypes); else if (equalLettersIgnoringASCIICase(name, sandbox)) applySandboxPolicy(name, value); else if (equalLettersIgnoringASCIICase(name, reportURI)) parseReportURI(name, value); #if ENABLE(CSP_NEXT) else if (m_policy.experimentalFeaturesEnabled()) { if (equalLettersIgnoringASCIICase(name, reflectedXSS)) parseReflectedXSS(name, value); else m_policy.reportUnsupportedDirective(name); } #endif else m_policy.reportUnsupportedDirective(name); } } // namespace WebCore