1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/frame/csp/CSPDirectiveList.h"
8 #include "core/dom/Document.h"
9 #include "core/frame/LocalFrame.h"
10 #include "core/inspector/ConsoleMessage.h"
11 #include "platform/ParsingUtilities.h"
12 #include "platform/RuntimeEnabledFeatures.h"
13 #include "platform/weborigin/KURL.h"
14 #include "wtf/text/WTFString.h"
18 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source)
21 , m_headerSource(source)
23 , m_haveSandboxPolicy(false)
24 , m_reflectedXSSDisposition(ReflectedXSSUnset)
25 , m_didSetReferrerPolicy(false)
26 , m_referrerPolicy(ReferrerPolicyDefault)
28 m_reportOnly = type == ContentSecurityPolicyHeaderTypeReport;
31 PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* policy, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source)
33 OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy, type, source));
34 directives->parse(begin, end);
36 if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) {
37 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";
38 directives->setEvalDisabledErrorMessage(message);
41 if (directives->isReportOnly() && directives->reportEndpoints().isEmpty())
42 policy->reportMissingReportURI(String(begin, end - begin));
44 return directives.release();
47 void CSPDirectiveList::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL) const
49 String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
50 m_policy->logToConsole(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, message));
51 m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportEndpoints, m_header);
54 void CSPDirectiveList::reportViolationWithFrame(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, LocalFrame* frame) const
56 String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
57 m_policy->logToConsole(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, message), frame);
58 m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportEndpoints, m_header, frame);
61 void CSPDirectiveList::reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const
63 String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage;
64 m_policy->logToConsole(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, message, contextURL, contextLine.oneBasedInt()));
65 m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportEndpoints, m_header);
68 void CSPDirectiveList::reportViolationWithState(const String& directiveText, const String& effectiveDirective, const String& message, const KURL& blockedURL, ScriptState* scriptState) const
70 String reportMessage = m_reportOnly ? "[Report Only] " + message : message;
71 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, reportMessage);
72 consoleMessage->setScriptState(scriptState);
73 m_policy->logToConsole(consoleMessage.release());
74 m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportEndpoints, m_header);
77 bool CSPDirectiveList::checkEval(SourceListDirective* directive) const
79 return !directive || directive->allowEval();
82 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
84 return !directive || (directive->allowInline() && !directive->isHashOrNoncePresent());
87 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const
89 return !directive || directive->allowNonce(nonce);
92 bool CSPDirectiveList::checkHash(SourceListDirective* directive, const CSPHashValue& hashValue) const
94 return !directive || directive->allowHash(hashValue);
97 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& url) const
99 return !directive || directive->allows(url);
102 bool CSPDirectiveList::checkAncestors(SourceListDirective* directive, LocalFrame* frame) const
104 if (!frame || !directive)
107 for (Frame* current = frame->tree().parent(); current; current = current->tree().parent()) {
108 // FIXME: To make this work for out-of-process iframes, we need to propagate URL information of ancestor frames across processes.
109 if (!current->isLocalFrame() || !directive->allows(toLocalFrame(current)->document()->url()))
115 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const
119 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
121 return directive->allows(type);
124 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive) const
126 return directive ? directive : m_defaultSrc.get();
129 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive, SourceListDirective* override) const
131 return directive ? directive : override;
134 bool CSPDirectiveList::checkEvalAndReportViolation(SourceListDirective* directive, const String& consoleMessage, ScriptState* scriptState) const
136 if (checkEval(directive))
139 String suffix = String();
140 if (directive == m_defaultSrc)
141 suffix = " Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.";
143 reportViolationWithState(directive->text(), ContentSecurityPolicy::ScriptSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), scriptState);
145 m_policy->reportBlockedScriptExecutionToInspector(directive->text());
151 bool CSPDirectiveList::checkMediaTypeAndReportViolation(MediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const
153 if (checkMediaType(directive, type, typeAttribute))
156 String message = consoleMessage + "\'" + directive->text() + "\'.";
157 if (typeAttribute.isEmpty())
158 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. '<object type=\"[TYPE GOES HERE]\" ...>').";
160 reportViolation(directive->text(), ContentSecurityPolicy::PluginTypes, message + "\n", KURL());
161 return denyIfEnforcingPolicy();
164 bool CSPDirectiveList::checkInlineAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const
166 if (checkInline(directive))
169 String suffix = String();
170 if (directive->allowInline() && directive->isHashOrNoncePresent()) {
171 // If inline is allowed, but a hash or nonce is present, we ignore 'unsafe-inline'. Throw a reasonable error.
172 suffix = " Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.";
174 suffix = " Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.";
175 if (directive == m_defaultSrc)
176 suffix = suffix + " Note also that '" + String(isScript ? "script" : "style") + "-src' was not explicitly set, so 'default-src' is used as a fallback.";
179 reportViolationWithLocation(directive->text(), isScript ? ContentSecurityPolicy::ScriptSrc : ContentSecurityPolicy::StyleSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), contextURL, contextLine);
183 m_policy->reportBlockedScriptExecutionToInspector(directive->text());
189 bool CSPDirectiveList::checkSourceAndReportViolation(SourceListDirective* directive, const KURL& url, const String& effectiveDirective) const
191 if (checkSource(directive, url))
195 if (ContentSecurityPolicy::BaseURI == effectiveDirective)
196 prefix = "Refused to set the document's base URI to '";
197 else if (ContentSecurityPolicy::ChildSrc == effectiveDirective)
198 prefix = "Refused to create a child context containing '";
199 else if (ContentSecurityPolicy::ConnectSrc == effectiveDirective)
200 prefix = "Refused to connect to '";
201 else if (ContentSecurityPolicy::FontSrc == effectiveDirective)
202 prefix = "Refused to load the font '";
203 else if (ContentSecurityPolicy::FormAction == effectiveDirective)
204 prefix = "Refused to send form data to '";
205 else if (ContentSecurityPolicy::FrameSrc == effectiveDirective)
206 prefix = "Refused to frame '";
207 else if (ContentSecurityPolicy::ImgSrc == effectiveDirective)
208 prefix = "Refused to load the image '";
209 else if (ContentSecurityPolicy::MediaSrc == effectiveDirective)
210 prefix = "Refused to load media from '";
211 else if (ContentSecurityPolicy::ManifestSrc == effectiveDirective)
212 prefix = "Refused to load manifest from '";
213 else if (ContentSecurityPolicy::ObjectSrc == effectiveDirective)
214 prefix = "Refused to load plugin data from '";
215 else if (ContentSecurityPolicy::ScriptSrc == effectiveDirective)
216 prefix = "Refused to load the script '";
217 else if (ContentSecurityPolicy::StyleSrc == effectiveDirective)
218 prefix = "Refused to load the stylesheet '";
220 String suffix = String();
221 if (directive == m_defaultSrc)
222 suffix = " Note that '" + effectiveDirective + "' was not explicitly set, so 'default-src' is used as a fallback.";
224 reportViolation(directive->text(), effectiveDirective, prefix + url.elidedString() + "' because it violates the following Content Security Policy directive: \"" + directive->text() + "\"." + suffix + "\n", url);
225 return denyIfEnforcingPolicy();
228 bool CSPDirectiveList::checkAncestorsAndReportViolation(SourceListDirective* directive, LocalFrame* frame, const KURL& url) const
230 if (checkAncestors(directive, frame))
233 reportViolationWithFrame(directive->text(), "frame-ancestors", "Refused to display '" + url.elidedString() + "' in a frame because an ancestor violates the following Content Security Policy directive: \"" + directive->text() + "\".", url, frame);
234 return denyIfEnforcingPolicy();
237 bool CSPDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
239 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: "));
240 if (reportingStatus == ContentSecurityPolicy::SendReport)
241 return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true);
243 return checkInline(operativeDirective(m_scriptSrc.get()));
246 bool CSPDirectiveList::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
248 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline event handler because it violates the following Content Security Policy directive: "));
249 if (reportingStatus == ContentSecurityPolicy::SendReport)
250 return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true);
251 return checkInline(operativeDirective(m_scriptSrc.get()));
254 bool CSPDirectiveList::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
256 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline script because it violates the following Content Security Policy directive: "));
257 return reportingStatus == ContentSecurityPolicy::SendReport ?
258 checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true) :
259 checkInline(operativeDirective(m_scriptSrc.get()));
262 bool CSPDirectiveList::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
264 DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to apply inline style because it violates the following Content Security Policy directive: "));
265 return reportingStatus == ContentSecurityPolicy::SendReport ?
266 checkInlineAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, contextURL, contextLine, false) :
267 checkInline(operativeDirective(m_styleSrc.get()));
270 bool CSPDirectiveList::allowEval(ScriptState* scriptState, ContentSecurityPolicy::ReportingStatus reportingStatus) const
272 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: "));
274 return reportingStatus == ContentSecurityPolicy::SendReport ?
275 checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, scriptState) :
276 checkEval(operativeDirective(m_scriptSrc.get()));
279 bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
281 return reportingStatus == ContentSecurityPolicy::SendReport ?
282 checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.elidedString() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ") :
283 checkMediaType(m_pluginTypes.get(), type, typeAttribute);
286 bool CSPDirectiveList::allowScriptFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
288 return reportingStatus == ContentSecurityPolicy::SendReport ?
289 checkSourceAndReportViolation(operativeDirective(m_scriptSrc.get()), url, ContentSecurityPolicy::ScriptSrc) :
290 checkSource(operativeDirective(m_scriptSrc.get()), url);
293 bool CSPDirectiveList::allowObjectFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
295 if (url.protocolIsAbout())
297 return reportingStatus == ContentSecurityPolicy::SendReport ?
298 checkSourceAndReportViolation(operativeDirective(m_objectSrc.get()), url, ContentSecurityPolicy::ObjectSrc) :
299 checkSource(operativeDirective(m_objectSrc.get()), url);
302 bool CSPDirectiveList::allowChildFrameFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
304 if (url.protocolIsAbout())
307 // 'frame-src' is the only directive which overrides something other than the default sources.
308 // It overrides 'child-src', which overrides the default sources. So, we do this nested set
309 // of calls to 'operativeDirective()' to grab 'frame-src' if it exists, 'child-src' if it
310 // doesn't, and 'defaut-src' if neither are available.
311 SourceListDirective* whichDirective = operativeDirective(m_frameSrc.get(), operativeDirective(m_childSrc.get()));
313 return reportingStatus == ContentSecurityPolicy::SendReport ?
314 checkSourceAndReportViolation(whichDirective, url, ContentSecurityPolicy::FrameSrc) :
315 checkSource(whichDirective, url);
318 bool CSPDirectiveList::allowImageFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
320 return reportingStatus == ContentSecurityPolicy::SendReport ?
321 checkSourceAndReportViolation(operativeDirective(m_imgSrc.get()), url, ContentSecurityPolicy::ImgSrc) :
322 checkSource(operativeDirective(m_imgSrc.get()), url);
325 bool CSPDirectiveList::allowStyleFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
327 return reportingStatus == ContentSecurityPolicy::SendReport ?
328 checkSourceAndReportViolation(operativeDirective(m_styleSrc.get()), url, ContentSecurityPolicy::StyleSrc) :
329 checkSource(operativeDirective(m_styleSrc.get()), url);
332 bool CSPDirectiveList::allowFontFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
334 return reportingStatus == ContentSecurityPolicy::SendReport ?
335 checkSourceAndReportViolation(operativeDirective(m_fontSrc.get()), url, ContentSecurityPolicy::FontSrc) :
336 checkSource(operativeDirective(m_fontSrc.get()), url);
339 bool CSPDirectiveList::allowMediaFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
341 return reportingStatus == ContentSecurityPolicy::SendReport ?
342 checkSourceAndReportViolation(operativeDirective(m_mediaSrc.get()), url, ContentSecurityPolicy::MediaSrc) :
343 checkSource(operativeDirective(m_mediaSrc.get()), url);
346 bool CSPDirectiveList::allowManifestFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
348 return reportingStatus == ContentSecurityPolicy::SendReport ?
349 checkSourceAndReportViolation(operativeDirective(m_manifestSrc.get()), url, ContentSecurityPolicy::ManifestSrc) :
350 checkSource(operativeDirective(m_manifestSrc.get()), url);
353 bool CSPDirectiveList::allowConnectToSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
355 return reportingStatus == ContentSecurityPolicy::SendReport ?
356 checkSourceAndReportViolation(operativeDirective(m_connectSrc.get()), url, ContentSecurityPolicy::ConnectSrc) :
357 checkSource(operativeDirective(m_connectSrc.get()), url);
360 bool CSPDirectiveList::allowFormAction(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
362 return reportingStatus == ContentSecurityPolicy::SendReport ?
363 checkSourceAndReportViolation(m_formAction.get(), url, ContentSecurityPolicy::FormAction) :
364 checkSource(m_formAction.get(), url);
367 bool CSPDirectiveList::allowBaseURI(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
369 return reportingStatus == ContentSecurityPolicy::SendReport ?
370 checkSourceAndReportViolation(m_baseURI.get(), url, ContentSecurityPolicy::BaseURI) :
371 checkSource(m_baseURI.get(), url);
374 bool CSPDirectiveList::allowAncestors(LocalFrame* frame, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
376 return reportingStatus == ContentSecurityPolicy::SendReport ?
377 checkAncestorsAndReportViolation(m_frameAncestors.get(), frame, url) :
378 checkAncestors(m_frameAncestors.get(), frame);
381 bool CSPDirectiveList::allowChildContextFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const
383 return reportingStatus == ContentSecurityPolicy::SendReport ?
384 checkSourceAndReportViolation(operativeDirective(m_childSrc.get()), url, ContentSecurityPolicy::ChildSrc) :
385 checkSource(operativeDirective(m_childSrc.get()), url);
388 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const
390 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
393 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const
395 return checkNonce(operativeDirective(m_styleSrc.get()), nonce);
398 bool CSPDirectiveList::allowScriptHash(const CSPHashValue& hashValue) const
400 return checkHash(operativeDirective(m_scriptSrc.get()), hashValue);
403 bool CSPDirectiveList::allowStyleHash(const CSPHashValue& hashValue) const
405 return checkHash(operativeDirective(m_styleSrc.get()), hashValue);
408 // policy = directive-list
409 // directive-list = [ directive *( ";" [ directive ] ) ]
411 void CSPDirectiveList::parse(const UChar* begin, const UChar* end)
413 m_header = String(begin, end - begin);
418 const UChar* position = begin;
419 while (position < end) {
420 const UChar* directiveBegin = position;
421 skipUntil<UChar>(position, end, ';');
424 if (parseDirective(directiveBegin, position, name, value)) {
425 ASSERT(!name.isEmpty());
426 addDirective(name, value);
429 ASSERT(position == end || *position == ';');
430 skipExactly<UChar>(position, end, ';');
434 // directive = *WSP [ directive-name [ WSP directive-value ] ]
435 // directive-name = 1*( ALPHA / DIGIT / "-" )
436 // directive-value = *( WSP / <VCHAR except ";"> )
438 bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value)
440 ASSERT(name.isEmpty());
441 ASSERT(value.isEmpty());
443 const UChar* position = begin;
444 skipWhile<UChar, isASCIISpace>(position, end);
446 // Empty directive (e.g. ";;;"). Exit early.
450 const UChar* nameBegin = position;
451 skipWhile<UChar, isCSPDirectiveNameCharacter>(position, end);
453 // The directive-name must be non-empty.
454 if (nameBegin == position) {
455 skipWhile<UChar, isNotASCIISpace>(position, end);
456 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin));
460 name = String(nameBegin, position - nameBegin);
465 if (!skipExactly<UChar, isASCIISpace>(position, end)) {
466 skipWhile<UChar, isNotASCIISpace>(position, end);
467 m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin));
471 skipWhile<UChar, isASCIISpace>(position, end);
473 const UChar* valueBegin = position;
474 skipWhile<UChar, isCSPDirectiveValueCharacter>(position, end);
476 if (position != end) {
477 m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin));
481 // The directive-value may be empty.
482 if (valueBegin == position)
485 value = String(valueBegin, position - valueBegin);
489 void CSPDirectiveList::parseReportURI(const String& name, const String& value)
491 if (!m_reportEndpoints.isEmpty()) {
492 m_policy->reportDuplicateDirective(name);
496 Vector<UChar> characters;
497 value.appendTo(characters);
499 const UChar* position = characters.data();
500 const UChar* end = position + characters.size();
502 while (position < end) {
503 skipWhile<UChar, isASCIISpace>(position, end);
505 const UChar* urlBegin = position;
506 skipWhile<UChar, isNotASCIISpace>(position, end);
508 if (urlBegin < position) {
509 String url = String(urlBegin, position - urlBegin);
510 m_reportEndpoints.append(url);
516 template<class CSPDirectiveType>
517 void CSPDirectiveList::setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>& directive)
520 m_policy->reportDuplicateDirective(name);
523 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy));
526 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy)
529 m_policy->reportInvalidInReportOnly(name);
532 if (m_haveSandboxPolicy) {
533 m_policy->reportDuplicateDirective(name);
536 m_haveSandboxPolicy = true;
537 String invalidTokens;
538 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidTokens));
539 if (!invalidTokens.isNull())
540 m_policy->reportInvalidSandboxFlags(invalidTokens);
543 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value)
545 if (m_reflectedXSSDisposition != ReflectedXSSUnset) {
546 m_policy->reportDuplicateDirective(name);
547 m_reflectedXSSDisposition = ReflectedXSSInvalid;
551 if (value.isEmpty()) {
552 m_reflectedXSSDisposition = ReflectedXSSInvalid;
553 m_policy->reportInvalidReflectedXSS(value);
557 Vector<UChar> characters;
558 value.appendTo(characters);
560 const UChar* position = characters.data();
561 const UChar* end = position + characters.size();
563 skipWhile<UChar, isASCIISpace>(position, end);
564 const UChar* begin = position;
565 skipWhile<UChar, isNotASCIISpace>(position, end);
569 if (equalIgnoringCase("allow", begin, position - begin)) {
570 m_reflectedXSSDisposition = AllowReflectedXSS;
571 } else if (equalIgnoringCase("filter", begin, position - begin)) {
572 m_reflectedXSSDisposition = FilterReflectedXSS;
573 } else if (equalIgnoringCase("block", begin, position - begin)) {
574 m_reflectedXSSDisposition = BlockReflectedXSS;
576 m_reflectedXSSDisposition = ReflectedXSSInvalid;
577 m_policy->reportInvalidReflectedXSS(value);
581 skipWhile<UChar, isASCIISpace>(position, end);
582 if (position == end && m_reflectedXSSDisposition != ReflectedXSSUnset)
587 m_reflectedXSSDisposition = ReflectedXSSInvalid;
588 m_policy->reportInvalidReflectedXSS(value);
591 void CSPDirectiveList::parseReferrer(const String& name, const String& value)
593 if (m_didSetReferrerPolicy) {
594 m_policy->reportDuplicateDirective(name);
595 m_referrerPolicy = ReferrerPolicyNever;
599 m_didSetReferrerPolicy = true;
601 if (value.isEmpty()) {
602 m_policy->reportInvalidReferrer(value);
603 m_referrerPolicy = ReferrerPolicyNever;
607 Vector<UChar> characters;
608 value.appendTo(characters);
610 const UChar* position = characters.data();
611 const UChar* end = position + characters.size();
613 skipWhile<UChar, isASCIISpace>(position, end);
614 const UChar* begin = position;
615 skipWhile<UChar, isNotASCIISpace>(position, end);
619 if (equalIgnoringCase("unsafe-url", begin, position - begin)) {
620 m_referrerPolicy = ReferrerPolicyAlways;
621 } else if (equalIgnoringCase("no-referrer", begin, position - begin)) {
622 m_referrerPolicy = ReferrerPolicyNever;
623 } else if (equalIgnoringCase("no-referrer-when-downgrade", begin, position - begin)) {
624 m_referrerPolicy = ReferrerPolicyDefault;
625 } else if (equalIgnoringCase("origin", begin, position - begin)) {
626 m_referrerPolicy = ReferrerPolicyOrigin;
628 m_referrerPolicy = ReferrerPolicyNever;
629 m_policy->reportInvalidReferrer(value);
633 skipWhile<UChar, isASCIISpace>(position, end);
639 m_referrerPolicy = ReferrerPolicyNever;
640 m_policy->reportInvalidReferrer(value);
644 void CSPDirectiveList::addDirective(const String& name, const String& value)
646 ASSERT(!name.isEmpty());
648 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) {
649 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc);
650 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) {
651 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc);
652 m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed());
653 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ObjectSrc)) {
654 setCSPDirective<SourceListDirective>(name, value, m_objectSrc);
655 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FrameAncestors)) {
656 setCSPDirective<SourceListDirective>(name, value, m_frameAncestors);
657 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FrameSrc)) {
658 setCSPDirective<SourceListDirective>(name, value, m_frameSrc);
659 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ImgSrc)) {
660 setCSPDirective<SourceListDirective>(name, value, m_imgSrc);
661 } else if (equalIgnoringCase(name, ContentSecurityPolicy::StyleSrc)) {
662 setCSPDirective<SourceListDirective>(name, value, m_styleSrc);
663 m_policy->usesStyleHashAlgorithms(m_styleSrc->hashAlgorithmsUsed());
664 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FontSrc)) {
665 setCSPDirective<SourceListDirective>(name, value, m_fontSrc);
666 } else if (equalIgnoringCase(name, ContentSecurityPolicy::MediaSrc)) {
667 setCSPDirective<SourceListDirective>(name, value, m_mediaSrc);
668 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ConnectSrc)) {
669 setCSPDirective<SourceListDirective>(name, value, m_connectSrc);
670 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Sandbox)) {
671 applySandboxPolicy(name, value);
672 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReportURI)) {
673 parseReportURI(name, value);
674 } else if (equalIgnoringCase(name, ContentSecurityPolicy::BaseURI)) {
675 setCSPDirective<SourceListDirective>(name, value, m_baseURI);
676 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ChildSrc)) {
677 setCSPDirective<SourceListDirective>(name, value, m_childSrc);
678 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FormAction)) {
679 setCSPDirective<SourceListDirective>(name, value, m_formAction);
680 } else if (equalIgnoringCase(name, ContentSecurityPolicy::PluginTypes)) {
681 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes);
682 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) {
683 parseReflectedXSS(name, value);
684 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) {
685 parseReferrer(name, value);
686 } else if (m_policy->experimentalFeaturesEnabled()) {
687 if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc))
688 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc);
690 m_policy->reportUnsupportedDirective(name);
692 m_policy->reportUnsupportedDirective(name);