Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2024-02-08 14:34:40 +08:00
commit 523b9df9db
16 changed files with 230 additions and 137 deletions

View file

@ -797,7 +797,7 @@ EventListenerManager::SetEventHandler(nsIAtom* aName,
if (csp) { if (csp) {
bool allowsInlineScript = true; bool allowsInlineScript = true;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT, rv = csp->GetAllowsInline(nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE,
EmptyString(), // aNonce EmptyString(), // aNonce
true, // aParserCreated (true because attribute event handler) true, // aParserCreated (true because attribute event handler)
aBody, aBody,

View file

@ -60,6 +60,10 @@ interface nsIContentSecurityPolicy : nsISerializable
const unsigned short REQUIRE_SRI_FOR = 20; const unsigned short REQUIRE_SRI_FOR = 20;
const unsigned short SANDBOX_DIRECTIVE = 21; const unsigned short SANDBOX_DIRECTIVE = 21;
const unsigned short WORKER_SRC_DIRECTIVE = 22; const unsigned short WORKER_SRC_DIRECTIVE = 22;
const unsigned short SCRIPT_SRC_ELEM_DIRECTIVE = 23;
const unsigned short SCRIPT_SRC_ATTR_DIRECTIVE = 24;
const unsigned short STYLE_SRC_ELEM_DIRECTIVE = 25;
const unsigned short STYLE_SRC_ATTR_DIRECTIVE = 26;
/** /**
* Accessor method for a read-only string version of the policy at a given * Accessor method for a read-only string version of the policy at a given
@ -146,7 +150,7 @@ interface nsIContentSecurityPolicy : nsISerializable
* Whether or not the effects of the inline style should be allowed * Whether or not the effects of the inline style should be allowed
* (block the rules if false). * (block the rules if false).
*/ */
boolean getAllowsInline(in nsContentPolicyType aContentPolicyType, boolean getAllowsInline(in CSPDirective aContentPolicyType,
in AString aNonce, in AString aNonce,
in boolean aParserCreated, in boolean aParserCreated,
in AString aContent, in AString aContent,

View file

@ -179,8 +179,10 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
rv = principal->GetCsp(getter_AddRefs(csp)); rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (csp) { if (csp) {
// javascript: is a "navigation" type, so script-src-elem applies.
// https://w3c.github.io/webappsec-csp/#effective-directive-for-inline-check
bool allowsInlineScript = true; bool allowsInlineScript = true;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT, rv = csp->GetAllowsInline(nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE,
EmptyString(), // aNonce EmptyString(), // aNonce
true, // aParserCreated true, // aParserCreated
EmptyString(), // aContent EmptyString(), // aContent

View file

@ -35,17 +35,22 @@ ignoringDuplicateSrc = Ignoring duplicate source %1$S
# LOCALIZATION NOTE (ignoringSrcFromMetaCSP): # LOCALIZATION NOTE (ignoringSrcFromMetaCSP):
# %1$S defines the ignored src # %1$S defines the ignored src
ignoringSrcFromMetaCSP = Ignoring source ‘%1$S’ (Not supported when delivered via meta element). ignoringSrcFromMetaCSP = Ignoring source ‘%1$S’ (Not supported when delivered via meta element).
# LOCALIZATION NOTE (ignoringSrcWithinScriptStyleSrc): # LOCALIZATION NOTE (ignoringSrcWithinNonceOrHashDirective):
# %1$S is the ignored src (e.g. "unsafe-inline")
# %2$S is the directive (e.g. "script-src-elem")
ignoringSrcWithinNonceOrHashDirective = Ignoring “%1$S” within %2$S: nonce-source or hash-source specified
# LOCALIZATION NOTE (ignoringScriptSrcForStrictDynamic):
# %1$S is the ignored src # %1$S is the ignored src
# script-src and style-src are directive names and should not be localized # %2$S is the directive src (e.g. "script-src-elem")
ignoringSrcWithinScriptStyleSrc = Ignoring “%1$S” within script-src or style-src: nonce-source or hash-source specified # 'strict-dynamic' should not be localized
# LOCALIZATION NOTE (ignoringSrcForStrictDynamic): ignoringScriptSrcForStrictDynamic = Ignoring “%1$S” within %2$S: ‘strict-dynamic’ specified
# %1$S is the ignored src
# script-src, as well as 'strict-dynamic' should not be localized
ignoringSrcForStrictDynamic = Ignoring “%1$S” within script-src: ‘strict-dynamic’ specified
# LOCALIZATION NOTE (ignoringStrictDynamic): # LOCALIZATION NOTE (ignoringStrictDynamic):
# %1$S is the ignored src # %1$S is the ignored src
ignoringStrictDynamic = Ignoring source “%1$S” (Only supported within script-src). ignoringStrictDynamic = Ignoring source “%1$S” (Only supported within script-src).
# LOCALIZATION NOTE (ignoringUnsafeEval):
# %1$S is the csp directive (e.g. script-src-elem)
# 'unsafe-eval' and 'wasm-unsafe-eval' should not be localized
ignoringUnsafeEval = Ignoring ‘unsafe-eval’ or ‘wasm-unsafe-eval’ inside “%1$S”.
# LOCALIZATION NOTE (strictDynamicButNoHashOrNonce): # LOCALIZATION NOTE (strictDynamicButNoHashOrNonce):
# %1$S is the csp directive that contains 'strict-dynamic' # %1$S is the csp directive that contains 'strict-dynamic'
# 'strict-dynamic' should not be localized # 'strict-dynamic' should not be localized

View file

@ -1471,7 +1471,7 @@ CSPAllowsInlineScript(nsIScriptElement *aElement, nsIDocument *aDocument)
aElement->GetScriptText(scriptText); aElement->GetScriptText(scriptText);
bool allowInlineScript = false; bool allowInlineScript = false;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT, rv = csp->GetAllowsInline(nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE,
nonce, parserCreated, scriptText, nonce, parserCreated, scriptText,
aElement->GetScriptLineNumber(), aElement->GetScriptLineNumber(),
aElement->GetScriptColumnNumber(), aElement->GetScriptColumnNumber(),

View file

@ -469,7 +469,7 @@ nsCSPContext::GetAllowsEval(bool* outShouldReportViolation,
*outAllowsEval = true; *outAllowsEval = true;
for (uint32_t i = 0; i < mPolicies.Length(); i++) { for (uint32_t i = 0; i < mPolicies.Length(); i++) {
if (!mPolicies[i]->allows(nsIContentPolicy::TYPE_SCRIPT, if (!mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE,
CSP_UNSAFE_EVAL, CSP_UNSAFE_EVAL,
EmptyString(), EmptyString(),
false)) { false)) {
@ -486,7 +486,7 @@ nsCSPContext::GetAllowsEval(bool* outShouldReportViolation,
// Helper function to report inline violations // Helper function to report inline violations
void void
nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType, nsCSPContext::reportInlineViolation(CSPDirective aDirective,
const nsAString& aNonce, const nsAString& aNonce,
const nsAString& aContent, const nsAString& aContent,
const nsAString& aViolatedDirective, const nsAString& aViolatedDirective,
@ -499,12 +499,14 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
// let's report the hash error; no need to report the unsafe-inline error // let's report the hash error; no need to report the unsafe-inline error
// anymore. // anymore.
if (!aNonce.IsEmpty()) { if (!aNonce.IsEmpty()) {
observerSubject = (aContentType == nsIContentPolicy::TYPE_SCRIPT) observerSubject = (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
aDirective == SCRIPT_SRC_ATTR_DIRECTIVE)
? NS_LITERAL_STRING(SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC) ? NS_LITERAL_STRING(SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC)
: NS_LITERAL_STRING(STYLE_NONCE_VIOLATION_OBSERVER_TOPIC); : NS_LITERAL_STRING(STYLE_NONCE_VIOLATION_OBSERVER_TOPIC);
} }
else { else {
observerSubject = (aContentType == nsIContentPolicy::TYPE_SCRIPT) observerSubject = (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
aDirective == SCRIPT_SRC_ATTR_DIRECTIVE)
? NS_LITERAL_STRING(SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC) ? NS_LITERAL_STRING(SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC)
: NS_LITERAL_STRING(STYLE_HASH_VIOLATION_OBSERVER_TOPIC); : NS_LITERAL_STRING(STYLE_HASH_VIOLATION_OBSERVER_TOPIC);
} }
@ -555,7 +557,7 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType, nsCSPContext::GetAllowsInline(CSPDirective aDirective,
const nsAString& aNonce, const nsAString& aNonce,
bool aParserCreated, bool aParserCreated,
const nsAString& aContent, const nsAString& aContent,
@ -565,20 +567,19 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
{ {
*outAllowsInline = true; *outAllowsInline = true;
MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), if (aDirective != SCRIPT_SRC_ELEM_DIRECTIVE &&
"We should only see external content policy types here."); aDirective != SCRIPT_SRC_ATTR_DIRECTIVE &&
aDirective != STYLE_SRC_ELEM_DIRECTIVE &&
if (aContentType != nsIContentPolicy::TYPE_SCRIPT && aDirective != STYLE_SRC_ATTR_DIRECTIVE) {
aContentType != nsIContentPolicy::TYPE_STYLESHEET) { MOZ_ASSERT(false, "can only allow inline for (script/style)-src-(attr/elem) or style");
MOZ_ASSERT(false, "can only allow inline for script or style");
return NS_OK; return NS_OK;
} }
// always iterate all policies, otherwise we might not send out all reports // always iterate all policies, otherwise we might not send out all reports
for (uint32_t i = 0; i < mPolicies.Length(); i++) { for (uint32_t i = 0; i < mPolicies.Length(); i++) {
bool allowed = bool allowed =
mPolicies[i]->allows(aContentType, CSP_UNSAFE_INLINE, EmptyString(), aParserCreated) || mPolicies[i]->allows(aDirective, CSP_UNSAFE_INLINE, EmptyString(), aParserCreated) ||
mPolicies[i]->allows(aContentType, CSP_NONCE, aNonce, aParserCreated); mPolicies[i]->allows(aDirective, CSP_NONCE, aNonce, aParserCreated);
// If the inlined script or style is allowed by either unsafe-inline or the // If the inlined script or style is allowed by either unsafe-inline or the
// nonce, go ahead and shortcut this loop. // nonce, go ahead and shortcut this loop.
@ -589,7 +590,7 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
// Check if the csp-hash matches against the hash of the script. // Check if the csp-hash matches against the hash of the script.
// If we don't have any content to check, block the script. // If we don't have any content to check, block the script.
if (!aContent.IsEmpty()) { if (!aContent.IsEmpty()) {
allowed = mPolicies[i]->allows(aContentType, CSP_HASH, aContent, aParserCreated); allowed = mPolicies[i]->allows(aDirective, CSP_HASH, aContent, aParserCreated);
} }
if (!allowed) { if (!allowed) {
@ -599,8 +600,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
*outAllowsInline = false; *outAllowsInline = false;
} }
nsAutoString violatedDirective; nsAutoString violatedDirective;
mPolicies[i]->getDirectiveStringForContentType(aContentType, violatedDirective); mPolicies[i]->getDirectiveStringForContentType(aDirective, violatedDirective);
reportInlineViolation(aContentType, reportInlineViolation(aDirective,
aNonce, aNonce,
aContent, aContent,
violatedDirective, violatedDirective,
@ -641,17 +642,17 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
* GetAllowsInline() and do not call this macro, hence we can pass 'false' * GetAllowsInline() and do not call this macro, hence we can pass 'false'
* as the argument _aParserCreated_ to allows(). * as the argument _aParserCreated_ to allows().
*/ */
#define CASE_CHECK_AND_REPORT(violationType, contentPolicyType, nonceOrHash, \ #define CASE_CHECK_AND_REPORT(violationType, directive, nonceOrHash, \
keyword, observerTopic) \ keyword, observerTopic) \
case nsIContentSecurityPolicy::VIOLATION_TYPE_ ## violationType : \ case nsIContentSecurityPolicy::VIOLATION_TYPE_ ## violationType : \
PR_BEGIN_MACRO \ PR_BEGIN_MACRO \
if (!mPolicies[p]->allows(nsIContentPolicy::TYPE_ ## contentPolicyType, \ static_assert(directive##_SRC_DIRECTIVE == SCRIPT_SRC_DIRECTIVE || \
keyword, nonceOrHash, false)) \ directive##_SRC_DIRECTIVE == STYLE_SRC_DIRECTIVE); \
{ \ if (!mPolicies[p]->allows(directive##_SRC_DIRECTIVE, keyword, nonceOrHash, \
false)) { \
nsAutoString violatedDirective; \ nsAutoString violatedDirective; \
mPolicies[p]->getDirectiveStringForContentType( \ mPolicies[p]->getDirectiveStringForContentType( \
nsIContentPolicy::TYPE_ ## contentPolicyType, \ directive##_SRC_DIRECTIVE, violatedDirective); \
violatedDirective); \
this->AsyncReportViolation(selfISupports, nullptr, violatedDirective, p, \ this->AsyncReportViolation(selfISupports, nullptr, violatedDirective, p, \
NS_LITERAL_STRING(observerTopic), aSourceFile,\ NS_LITERAL_STRING(observerTopic), aSourceFile,\
aScriptSample, aLineNum, aColumnNum); \ aScriptSample, aLineNum, aColumnNum); \
@ -711,19 +712,19 @@ nsCSPContext::LogViolationDetails(uint16_t aViolationType,
switch (aViolationType) { switch (aViolationType) {
CASE_CHECK_AND_REPORT(EVAL, SCRIPT, NS_LITERAL_STRING(""), CASE_CHECK_AND_REPORT(EVAL, SCRIPT, NS_LITERAL_STRING(""),
CSP_UNSAFE_EVAL, EVAL_VIOLATION_OBSERVER_TOPIC); CSP_UNSAFE_EVAL, EVAL_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(INLINE_STYLE, STYLESHEET, NS_LITERAL_STRING(""), CASE_CHECK_AND_REPORT(INLINE_STYLE, STYLE, NS_LITERAL_STRING(""),
CSP_UNSAFE_INLINE, INLINE_STYLE_VIOLATION_OBSERVER_TOPIC); CSP_UNSAFE_INLINE, INLINE_STYLE_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(INLINE_SCRIPT, SCRIPT, NS_LITERAL_STRING(""), CASE_CHECK_AND_REPORT(INLINE_SCRIPT, SCRIPT, NS_LITERAL_STRING(""),
CSP_UNSAFE_INLINE, INLINE_SCRIPT_VIOLATION_OBSERVER_TOPIC); CSP_UNSAFE_INLINE, INLINE_SCRIPT_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(NONCE_SCRIPT, SCRIPT, aNonce, CASE_CHECK_AND_REPORT(NONCE_SCRIPT, SCRIPT, aNonce,
CSP_UNSAFE_INLINE, SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC); CSP_UNSAFE_INLINE, SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(NONCE_STYLE, STYLESHEET, aNonce, CASE_CHECK_AND_REPORT(NONCE_STYLE, STYLE, aNonce,
CSP_UNSAFE_INLINE, STYLE_NONCE_VIOLATION_OBSERVER_TOPIC); CSP_UNSAFE_INLINE, STYLE_NONCE_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(HASH_SCRIPT, SCRIPT, aContent, CASE_CHECK_AND_REPORT(HASH_SCRIPT, SCRIPT, aContent,
CSP_UNSAFE_INLINE, SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC); CSP_UNSAFE_INLINE, SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(HASH_STYLE, STYLESHEET, aContent, CASE_CHECK_AND_REPORT(HASH_STYLE, STYLE, aContent,
CSP_UNSAFE_INLINE, STYLE_HASH_VIOLATION_OBSERVER_TOPIC); CSP_UNSAFE_INLINE, STYLE_HASH_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(REQUIRE_SRI_FOR_STYLE, STYLESHEET, NS_LITERAL_STRING(""), CASE_CHECK_AND_REPORT(REQUIRE_SRI_FOR_STYLE, STYLE, NS_LITERAL_STRING(""),
CSP_REQUIRE_SRI_FOR, REQUIRE_SRI_STYLE_VIOLATION_OBSERVER_TOPIC); CSP_REQUIRE_SRI_FOR, REQUIRE_SRI_STYLE_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(REQUIRE_SRI_FOR_SCRIPT, SCRIPT, NS_LITERAL_STRING(""), CASE_CHECK_AND_REPORT(REQUIRE_SRI_FOR_SCRIPT, SCRIPT, NS_LITERAL_STRING(""),
CSP_REQUIRE_SRI_FOR, REQUIRE_SRI_SCRIPT_VIOLATION_OBSERVER_TOPIC); CSP_REQUIRE_SRI_FOR, REQUIRE_SRI_SCRIPT_VIOLATION_OBSERVER_TOPIC);

View file

@ -133,7 +133,7 @@ class nsCSPContext : public nsIContentSecurityPolicy
bool aParserCreated); bool aParserCreated);
// helper to report inline script/style violations // helper to report inline script/style violations
void reportInlineViolation(nsContentPolicyType aContentType, void reportInlineViolation(CSPDirective aDirective,
const nsAString& aNonce, const nsAString& aNonce,
const nsAString& aContent, const nsAString& aContent,
const nsAString& aViolatedDirective, const nsAString& aViolatedDirective,

View file

@ -108,12 +108,14 @@ nsCSPParser::nsCSPParser(cspTokens& aTokens,
: mCurChar(nullptr) : mCurChar(nullptr)
, mEndChar(nullptr) , mEndChar(nullptr)
, mHasHashOrNonce(false) , mHasHashOrNonce(false)
, mHasAnyUnsafeEval(false)
, mStrictDynamic(false) , mStrictDynamic(false)
, mUnsafeInlineKeywordSrc(nullptr) , mUnsafeInlineKeywordSrc(nullptr)
, mChildSrc(nullptr) , mChildSrc(nullptr)
, mFrameSrc(nullptr) , mFrameSrc(nullptr)
, mWorkerSrc(nullptr) , mWorkerSrc(nullptr)
, mScriptSrc(nullptr) , mScriptSrc(nullptr)
, mStyleSrc(nullptr)
, mParsingFrameAncestorsDir(false) , mParsingFrameAncestorsDir(false)
, mTokens(aTokens) , mTokens(aTokens)
, mSelfURI(aSelfURI) , mSelfURI(aSelfURI)
@ -497,7 +499,9 @@ nsCSPParser::keywordSource()
if (!sStrictDynamicEnabled) { if (!sStrictDynamicEnabled) {
return nullptr; return nullptr;
} }
if (!CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE)) { if (!CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE) &&
!CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE) &&
!CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE)) {
// Todo: Enforce 'strict-dynamic' within default-src; see Bug 1313937 // Todo: Enforce 'strict-dynamic' within default-src; see Bug 1313937
const char16_t* params[] = { u"strict-dynamic" }; const char16_t* params[] = { u"strict-dynamic" };
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringStrictDynamic", logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringStrictDynamic",
@ -534,6 +538,7 @@ nsCSPParser::keywordSource()
if (doc) { if (doc) {
doc->SetHasUnsafeEvalCSP(true); doc->SetHasUnsafeEvalCSP(true);
} }
mHasAnyUnsafeEval = true;
return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken)); return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken));
} }
return nullptr; return nullptr;
@ -1077,12 +1082,20 @@ nsCSPParser::directiveName()
} }
// if we have a script-src, cache it as a fallback for worker-src // if we have a script-src, cache it as a fallback for worker-src
// in case child-src is not present // in case child-src is not present. It is also used as a fallback for
// script-src-elem and script-src-attr.
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE)) { if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE)) {
mScriptSrc = new nsCSPScriptSrcDirective(CSP_StringToCSPDirective(mCurToken)); mScriptSrc = new nsCSPScriptSrcDirective(CSP_StringToCSPDirective(mCurToken));
return mScriptSrc; return mScriptSrc;
} }
// If we have a style-src, cache it as a fallback for style-src-elem and
// style-src-attr.
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE)) {
mStyleSrc = new nsCSPStyleSrcDirective(CSP_StringToCSPDirective(mCurToken));
return mStyleSrc;
}
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::REQUIRE_SRI_FOR)) { if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::REQUIRE_SRI_FOR)) {
return new nsRequireSRIForDirective(CSP_StringToCSPDirective(mCurToken)); return new nsRequireSRIForDirective(CSP_StringToCSPDirective(mCurToken));
} }
@ -1181,6 +1194,7 @@ nsCSPParser::directive()
// make sure to reset cache variables when trying to invalidate unsafe-inline; // make sure to reset cache variables when trying to invalidate unsafe-inline;
// unsafe-inline might not only appear in script-src, but also in default-src // unsafe-inline might not only appear in script-src, but also in default-src
mHasHashOrNonce = false; mHasHashOrNonce = false;
mHasAnyUnsafeEval = false;
mStrictDynamic = false; mStrictDynamic = false;
mUnsafeInlineKeywordSrc = nullptr; mUnsafeInlineKeywordSrc = nullptr;
@ -1200,8 +1214,12 @@ nsCSPParser::directive()
// If policy contains 'strict-dynamic' invalidate all srcs within script-src. // If policy contains 'strict-dynamic' invalidate all srcs within script-src.
if (mStrictDynamic) { if (mStrictDynamic) {
MOZ_ASSERT(cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE), MOZ_ASSERT(
"strict-dynamic only allowed within script-src"); cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE) ||
cspDir->equals(
nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE) ||
cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE),
"strict-dynamic only allowed within script-src(-elem|attr)");
for (uint32_t i = 0; i < srcs.Length(); i++) { for (uint32_t i = 0; i < srcs.Length(); i++) {
// Please note that nsCSPNonceSrc as well as nsCSPHashSrc overwrite invalidate(), // Please note that nsCSPNonceSrc as well as nsCSPHashSrc overwrite invalidate(),
// so it's fine to just call invalidate() on all srcs. Please also note that // so it's fine to just call invalidate() on all srcs. Please also note that
@ -1220,8 +1238,8 @@ nsCSPParser::directive()
!StringBeginsWith(NS_ConvertUTF16toUTF8(srcStr), NS_LITERAL_CSTRING("'nonce-")) && !StringBeginsWith(NS_ConvertUTF16toUTF8(srcStr), NS_LITERAL_CSTRING("'nonce-")) &&
!StringBeginsWith(NS_ConvertUTF16toUTF8(srcStr), NS_LITERAL_CSTRING("'sha"))) !StringBeginsWith(NS_ConvertUTF16toUTF8(srcStr), NS_LITERAL_CSTRING("'sha")))
{ {
const char16_t* params[] = { srcStr.get() }; const char16_t* params[] = { srcStr.get(), mCurDir[0].get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringSrcForStrictDynamic", logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringScriptSrcForStrictDynamic",
params, ArrayLength(params)); params, ArrayLength(params));
} }
} }
@ -1235,11 +1253,22 @@ nsCSPParser::directive()
} }
else if (mHasHashOrNonce && mUnsafeInlineKeywordSrc && else if (mHasHashOrNonce && mUnsafeInlineKeywordSrc &&
(cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE) || (cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE) ||
cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE) ||
cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE) ||
cspDir->equals(nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE))) { cspDir->equals(nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE))) {
mUnsafeInlineKeywordSrc->invalidate(); mUnsafeInlineKeywordSrc->invalidate();
// log to the console that unsafe-inline will be ignored // log to the console that unsafe-inline will be ignored.
const char16_t* params[] = { u"'unsafe-inline'" }; const char16_t* params[] = { u"'unsafe-inline'", mCurDir[0].get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringSrcWithinScriptStyleSrc", logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringSrcWithinNonceOrHashDirective",
params, ArrayLength(params));
}
if (mHasAnyUnsafeEval &&
(cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE) ||
cspDir->equals(nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE))) {
// Log to the console that (wasm-)unsafe-eval will be ignored.
const char16_t* params[] = { mCurDir[0].get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringUnsafeEval",
params, ArrayLength(params)); params, ArrayLength(params));
} }
@ -1265,13 +1294,13 @@ nsCSPParser::policy()
if (mChildSrc) { if (mChildSrc) {
if (!mFrameSrc) { if (!mFrameSrc) {
// if frame-src is specified explicitly for that policy than child-src should // if frame-src is specified explicitly for that policy, then child-src should
// not restrict frames; if not, than child-src needs to restrict frames. // not restrict frames; if not, then child-src needs to restrict frames.
mChildSrc->setRestrictFrames(); mChildSrc->setRestrictFrames();
} }
if (!mWorkerSrc) { if (!mWorkerSrc) {
// if worker-src is specified explicitly for that policy than child-src should // if worker-src is specified explicitly for that policy, then child-src should
// not restrict workers; if not, than child-src needs to restrict workers. // not restrict workers; if not, then child-src needs to restrict workers.
mChildSrc->setRestrictWorkers(); mChildSrc->setRestrictWorkers();
} }
} }
@ -1281,6 +1310,30 @@ nsCSPParser::policy()
mScriptSrc->setRestrictWorkers(); mScriptSrc->setRestrictWorkers();
} }
// If script-src is specified and script-src-elem is not specified, then
// script-src has to govern script requests and script blocks.
if (mScriptSrc && !mPolicy->hasDirective(nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE)) {
mScriptSrc->setRestrictScriptElem();
}
// If script-src is specified and script-src-attr is not specified, then
// script-src has to govern script attr (event handlers).
if (mScriptSrc && !mPolicy->hasDirective(nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE)) {
mScriptSrc->setRestrictScriptAttr();
}
// If style-src is specified and style-src-elem is not specified, then
// style-src serves as a fallback.
if (mStyleSrc && !mPolicy->hasDirective(nsIContentSecurityPolicy::STYLE_SRC_ELEM_DIRECTIVE)) {
mStyleSrc->setRestrictStyleElem();
}
// If style-src is specified and style-src-attr is not specified, then
// style-src serves as a fallback.
if (mStyleSrc && !mPolicy->hasDirective(nsIContentSecurityPolicy::STYLE_SRC_ATTR_DIRECTIVE)) {
mStyleSrc->setRestrictStyleAttr();
}
return mPolicy; return mPolicy;
} }

View file

@ -240,6 +240,7 @@ class nsCSPParser {
// helpers to allow invalidation of srcs within script-src and style-src // helpers to allow invalidation of srcs within script-src and style-src
// if either 'strict-dynamic' or at least a hash or nonce is present. // if either 'strict-dynamic' or at least a hash or nonce is present.
bool mHasHashOrNonce; // false, if no hash or nonce is defined bool mHasHashOrNonce; // false, if no hash or nonce is defined
bool mHasAnyUnsafeEval; // false, if no (wasm-)unsafe-eval keyword is used.
bool mStrictDynamic; // false, if 'strict-dynamic' is not defined bool mStrictDynamic; // false, if 'strict-dynamic' is not defined
nsCSPKeywordSrc* mUnsafeInlineKeywordSrc; // null, otherwise invlidate() nsCSPKeywordSrc* mUnsafeInlineKeywordSrc; // null, otherwise invlidate()
@ -254,6 +255,7 @@ class nsCSPParser {
nsCSPDirective* mFrameSrc; nsCSPDirective* mFrameSrc;
nsCSPDirective* mWorkerSrc; nsCSPDirective* mWorkerSrc;
nsCSPScriptSrcDirective* mScriptSrc; nsCSPScriptSrcDirective* mScriptSrc;
nsCSPStyleSrcDirective* mStyleSrc;
// cache variable to let nsCSPHostSrc know that it's within // cache variable to let nsCSPHostSrc know that it's within
// the frame-ancestors directive. // the frame-ancestors directive.

View file

@ -199,6 +199,10 @@ CSP_LogLocalizedStr(const char16_t* aName,
} }
/* ===== Helpers ============================ */ /* ===== Helpers ============================ */
// This implements
// https://w3c.github.io/webappsec-csp/#effective-directive-for-a-request.
// However the spec doesn't currently cover all request destinations, which
// we roughly represent using nsContentPolicyType.
CSPDirective CSPDirective
CSP_ContentTypeToDirective(nsContentPolicyType aType) CSP_ContentTypeToDirective(nsContentPolicyType aType)
{ {
@ -213,10 +217,14 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType)
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS: case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
return nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE; // (https://github.com/w3c/webappsec-csp/issues/554)
// Some of these types are not explicitly defined in the spec.
//
// Chrome seems to use script-src-elem for worklet!
return nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE;
case nsIContentPolicy::TYPE_STYLESHEET: case nsIContentPolicy::TYPE_STYLESHEET:
return nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE; return nsIContentSecurityPolicy::STYLE_SRC_ELEM_DIRECTIVE;
case nsIContentPolicy::TYPE_FONT: case nsIContentPolicy::TYPE_FONT:
return nsIContentSecurityPolicy::FONT_SRC_DIRECTIVE; return nsIContentSecurityPolicy::FONT_SRC_DIRECTIVE;
@ -1217,6 +1225,16 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
outCSP.mWorker_src.Value() = mozilla::Move(srcs); outCSP.mWorker_src.Value() = mozilla::Move(srcs);
return; return;
case nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE:
outCSP.mScript_src_elem.Construct();
outCSP.mScript_src_elem.Value() = mozilla::Move(srcs);
return;
case nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE:
outCSP.mScript_src_attr.Construct();
outCSP.mScript_src_attr.Value() = mozilla::Move(srcs);
return;
// REFERRER_DIRECTIVE and REQUIRE_SRI_FOR are handled in nsCSPPolicy::toDomCSPStruct() // REFERRER_DIRECTIVE and REQUIRE_SRI_FOR are handled in nsCSPPolicy::toDomCSPStruct()
default: default:
@ -1225,16 +1243,6 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
} }
bool
nsCSPDirective::restrictsContentType(nsContentPolicyType aContentType) const
{
// make sure we do not check for the default src before any other sources
if (isDefaultDirective()) {
return false;
}
return mDirective == CSP_ContentTypeToDirective(aContentType);
}
void void
nsCSPDirective::getReportURIs(nsTArray<nsString> &outReportURIs) const nsCSPDirective::getReportURIs(nsTArray<nsString> &outReportURIs) const
{ {
@ -1284,19 +1292,6 @@ nsCSPChildSrcDirective::~nsCSPChildSrcDirective()
{ {
} }
bool nsCSPChildSrcDirective::restrictsContentType(nsContentPolicyType aContentType) const
{
if (aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
return mRestrictFrames;
}
if (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER) {
return mRestrictWorkers;
}
return false;
}
bool nsCSPChildSrcDirective::equals(CSPDirective aDirective) const bool nsCSPChildSrcDirective::equals(CSPDirective aDirective) const
{ {
if (aDirective == nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE) { if (aDirective == nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE) {
@ -1313,28 +1308,44 @@ bool nsCSPChildSrcDirective::equals(CSPDirective aDirective) const
nsCSPScriptSrcDirective::nsCSPScriptSrcDirective(CSPDirective aDirective) nsCSPScriptSrcDirective::nsCSPScriptSrcDirective(CSPDirective aDirective)
: nsCSPDirective(aDirective) : nsCSPDirective(aDirective)
, mRestrictWorkers(false) , mRestrictWorkers(false)
, mRestrictScriptElem(false)
, mRestrictScriptAttr(false)
{ {
} }
nsCSPScriptSrcDirective::~nsCSPScriptSrcDirective() nsCSPScriptSrcDirective::~nsCSPScriptSrcDirective() = default;
{
}
bool nsCSPScriptSrcDirective::restrictsContentType(nsContentPolicyType aContentType) const bool nsCSPScriptSrcDirective::equals(CSPDirective aDirective) const {
{
if (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER) {
return mRestrictWorkers;
}
return mDirective == CSP_ContentTypeToDirective(aContentType);
}
bool nsCSPScriptSrcDirective::equals(CSPDirective aDirective) const
{
if (aDirective == nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE) { if (aDirective == nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE) {
return mRestrictWorkers; return mRestrictWorkers;
} }
if (aDirective == nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE) {
return mRestrictScriptElem;
}
if (aDirective == nsIContentSecurityPolicy::SCRIPT_SRC_ATTR_DIRECTIVE) {
return mRestrictScriptAttr;
}
return (mDirective == aDirective);
}
/* =============== nsCSPStyleSrcDirective ============= */
nsCSPStyleSrcDirective::nsCSPStyleSrcDirective(CSPDirective aDirective)
: nsCSPDirective(aDirective)
, mRestrictStyleElem(false)
, mRestrictStyleAttr(false)
{
}
nsCSPStyleSrcDirective::~nsCSPStyleSrcDirective() = default;
bool nsCSPStyleSrcDirective::equals(CSPDirective aDirective) const {
if (aDirective == nsIContentSecurityPolicy::STYLE_SRC_ELEM_DIRECTIVE) {
return mRestrictStyleElem;
}
if (aDirective == nsIContentSecurityPolicy::STYLE_SRC_ATTR_DIRECTIVE) {
return mRestrictStyleAttr;
}
return (mDirective == aDirective); return (mDirective == aDirective);
} }
@ -1464,15 +1475,6 @@ nsCSPPolicy::~nsCSPPolicy()
} }
} }
bool
nsCSPPolicy::permits(CSPDirective aDir,
nsIURI* aUri,
bool aSpecific) const
{
nsString outp;
return this->permits(aDir, aUri, EmptyString(), false, aSpecific, false, outp);
}
bool bool
nsCSPPolicy::permits(CSPDirective aDir, nsCSPPolicy::permits(CSPDirective aDir,
nsIURI* aUri, nsIURI* aUri,
@ -1526,7 +1528,7 @@ nsCSPPolicy::permits(CSPDirective aDir,
} }
bool bool
nsCSPPolicy::allows(nsContentPolicyType aContentType, nsCSPPolicy::allows(CSPDirective aDirective,
enum CSPKeyword aKeyword, enum CSPKeyword aKeyword,
const nsAString& aHashOrNonce, const nsAString& aHashOrNonce,
bool aParserCreated) const bool aParserCreated) const
@ -1538,15 +1540,16 @@ nsCSPPolicy::allows(nsContentPolicyType aContentType,
// Try to find a matching directive // Try to find a matching directive
for (uint32_t i = 0; i < mDirectives.Length(); i++) { for (uint32_t i = 0; i < mDirectives.Length(); i++) {
if (mDirectives[i]->restrictsContentType(aContentType)) { if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i];
continue;
}
if (mDirectives[i]->equals(aDirective)) {
if (mDirectives[i]->allows(aKeyword, aHashOrNonce, aParserCreated)) { if (mDirectives[i]->allows(aKeyword, aHashOrNonce, aParserCreated)) {
return true; return true;
} }
return false; return false;
} }
if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i];
}
} }
// {nonce,hash}-source should not consult default-src: // {nonce,hash}-source should not consult default-src:
@ -1573,13 +1576,6 @@ nsCSPPolicy::allows(nsContentPolicyType aContentType,
return true; return true;
} }
bool
nsCSPPolicy::allows(nsContentPolicyType aContentType,
enum CSPKeyword aKeyword) const
{
return allows(aContentType, aKeyword, NS_LITERAL_STRING(""), false);
}
void void
nsCSPPolicy::toString(nsAString& outStr) const nsCSPPolicy::toString(nsAString& outStr) const
{ {
@ -1634,17 +1630,18 @@ nsCSPPolicy::hasDirective(CSPDirective aDir) const
* for the ::permits() function family. * for the ::permits() function family.
*/ */
void void
nsCSPPolicy::getDirectiveStringForContentType(nsContentPolicyType aContentType, nsCSPPolicy::getDirectiveStringForContentType(CSPDirective aDirective,
nsAString& outDirective) const nsAString& outDirective) const
{ {
nsCSPDirective* defaultDir = nullptr; nsCSPDirective* defaultDir = nullptr;
for (uint32_t i = 0; i < mDirectives.Length(); i++) { for (uint32_t i = 0; i < mDirectives.Length(); i++) {
if (mDirectives[i]->restrictsContentType(aContentType)) {
mDirectives[i]->getDirName(outDirective);
return;
}
if (mDirectives[i]->isDefaultDirective()) { if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i]; defaultDir = mDirectives[i];
continue;
}
if (mDirectives[i]->equals(aDirective)) {
mDirectives[i]->getDirName(outDirective);
return;
} }
} }
// if we haven't found a matching directive yet, // if we haven't found a matching directive yet,

View file

@ -141,7 +141,11 @@ static const char* CSPStrDirectives[] = {
"block-all-mixed-content", // BLOCK_ALL_MIXED_CONTENT "block-all-mixed-content", // BLOCK_ALL_MIXED_CONTENT
"require-sri-for", // REQUIRE_SRI_FOR "require-sri-for", // REQUIRE_SRI_FOR
"sandbox", // SANDBOX_DIRECTIVE "sandbox", // SANDBOX_DIRECTIVE
"worker-src" // WORKER_SRC_DIRECTIVE "worker-src", // WORKER_SRC_DIRECTIVE
"script-src-elem", // SCRIPT_SRC_ELEM_DIRECTIVE
"script-src-attr", // SCRIPT_SRC_ATTR_DIRECTIVE
"style-src-elem", // STYLE_SRC_ELEM_DIRECTIVE
"style-src-attr" // STYLE_SRC_ATTR_DIRECTIVE
}; };
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir) inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
@ -483,8 +487,6 @@ class nsCSPDirective {
virtual void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) virtual void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
{ mSrcs = aSrcs; } { mSrcs = aSrcs; }
virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
inline bool isDefaultDirective() const inline bool isDefaultDirective() const
{ return mDirective == nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE; } { return mDirective == nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE; }
@ -520,8 +522,6 @@ class nsCSPChildSrcDirective : public nsCSPDirective {
void setRestrictWorkers() void setRestrictWorkers()
{ mRestrictWorkers = true; } { mRestrictWorkers = true; }
virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
virtual bool equals(CSPDirective aDirective) const; virtual bool equals(CSPDirective aDirective) const;
private: private:
@ -541,15 +541,37 @@ class nsCSPScriptSrcDirective : public nsCSPDirective {
explicit nsCSPScriptSrcDirective(CSPDirective aDirective); explicit nsCSPScriptSrcDirective(CSPDirective aDirective);
virtual ~nsCSPScriptSrcDirective(); virtual ~nsCSPScriptSrcDirective();
void setRestrictWorkers() void setRestrictWorkers() { mRestrictWorkers = true; }
{ mRestrictWorkers = true; } void setRestrictScriptElem() { mRestrictScriptElem = true; }
void setRestrictScriptAttr() { mRestrictScriptAttr = true; }
virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
virtual bool equals(CSPDirective aDirective) const; virtual bool equals(CSPDirective aDirective) const;
private: private:
bool mRestrictWorkers; bool mRestrictWorkers;
bool mRestrictScriptElem;
bool mRestrictScriptAttr;
};
/* =============== nsCSPStyleSrcDirective ============= */
/*
* In CSP 3, style-src is used as a fallback for style-src-elem and
* style-src-attr in case they aren't defined.
*/
class nsCSPStyleSrcDirective : public nsCSPDirective {
public:
explicit nsCSPStyleSrcDirective(CSPDirective aDirective);
virtual ~nsCSPStyleSrcDirective();
void setRestrictStyleElem() { mRestrictStyleElem = true; }
void setRestrictStyleAttr() { mRestrictStyleAttr = true; }
virtual bool equals(CSPDirective aDirective) const;
private:
bool mRestrictStyleElem;
bool mRestrictStyleAttr;
}; };
/* =============== nsBlockAllMixedContentDirective === */ /* =============== nsBlockAllMixedContentDirective === */
@ -668,15 +690,10 @@ class nsCSPPolicy {
bool aSpecific, bool aSpecific,
bool aParserCreated, bool aParserCreated,
nsAString& outViolatedDirective) const; nsAString& outViolatedDirective) const;
bool permits(CSPDirective aDir, bool allows(CSPDirective aDirective,
nsIURI* aUri,
bool aSpecific) const;
bool allows(nsContentPolicyType aContentType,
enum CSPKeyword aKeyword, enum CSPKeyword aKeyword,
const nsAString& aHashOrNonce, const nsAString& aHashOrNonce,
bool aParserCreated) const; bool aParserCreated) const;
bool allows(nsContentPolicyType aContentType,
enum CSPKeyword aKeyword) const;
void toString(nsAString& outStr) const; void toString(nsAString& outStr) const;
void toDomCSPStruct(mozilla::dom::CSP& outCSP) const; void toDomCSPStruct(mozilla::dom::CSP& outCSP) const;
@ -708,7 +725,7 @@ class nsCSPPolicy {
void getReportURIs(nsTArray<nsString> &outReportURIs) const; void getReportURIs(nsTArray<nsString> &outReportURIs) const;
void getDirectiveStringForContentType(nsContentPolicyType aContentType, void getDirectiveStringForContentType(CSPDirective aDirective,
nsAString& outDirective) const; nsAString& outDirective) const;
void getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) const; void getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) const;

View file

@ -50,7 +50,7 @@ function checkResults(reportStr) {
"http://mochi.test:8888/tests/dom/security/test/csp/test_report_for_import.html", "http://mochi.test:8888/tests/dom/security/test/csp/test_report_for_import.html",
"Incorrect referrer"); "Incorrect referrer");
is(cspReport["violated-directive"], is(cspReport["violated-directive"],
"style-src http://mochi.test:8888", "style-src-elem http://mochi.test:8888",
"Incorrect violated-directive"); "Incorrect violated-directive");
is(cspReport["original-policy"], is(cspReport["original-policy"],
"style-src http://mochi.test:8888; report-uri " + "style-src http://mochi.test:8888; report-uri " +

View file

@ -215,7 +215,7 @@ function run_test() {
function(csp) { function(csp) {
var uri = NetUtil var uri = NetUtil
// shouldLoad creates and sends out the report here. // shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT, csp.shouldLoad(Ci.nsIContentSecurityPolicy.SCRIPT_SRC_ELEM_DIRECTIVE,
NetUtil.newURI(selfSpec + "#bar"), NetUtil.newURI(selfSpec + "#bar"),
null, null, null, null); null, null, null, null);
}); });
@ -224,7 +224,7 @@ function run_test() {
makeTest(8, {"blocked-uri": "ftp://blocked.test"}, false, makeTest(8, {"blocked-uri": "ftp://blocked.test"}, false,
function(csp) { function(csp) {
// shouldLoad creates and sends out the report here. // shouldLoad creates and sends out the report here.
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT, csp.shouldLoad(Ci.nsIContentSecurityPolicy.SCRIPT_SRC_ELEM_DIRECTIVE,
NetUtil.newURI("ftp://blocked.test/profile.png"), NetUtil.newURI("ftp://blocked.test/profile.png"),
null, null, null, null); null, null, null, null);
}); });

View file

@ -20,7 +20,7 @@ dictionary CSP {
sequence<DOMString> connect-src; sequence<DOMString> connect-src;
sequence<DOMString> report-uri; sequence<DOMString> report-uri;
sequence<DOMString> frame-ancestors; sequence<DOMString> frame-ancestors;
// sequence<DOMString> reflected-xss; // not supported in Firefox // sequence<DOMString> reflected-xss; // not supported in UXP
sequence<DOMString> base-uri; sequence<DOMString> base-uri;
sequence<DOMString> form-action; sequence<DOMString> form-action;
sequence<DOMString> referrer; sequence<DOMString> referrer;
@ -31,6 +31,8 @@ dictionary CSP {
sequence<DOMString> require-sri-for; sequence<DOMString> require-sri-for;
sequence<DOMString> sandbox; sequence<DOMString> sandbox;
sequence<DOMString> worker-src; sequence<DOMString> worker-src;
sequence<DOMString> script-src-elem;
sequence<DOMString> script-src-attr;
}; };
dictionary CSPPolicies { dictionary CSPPolicies {

View file

@ -591,8 +591,16 @@ gfxFontShaper::GetRoundOffsetsToPixels(DrawTarget* aDrawTarget,
} }
// Sometimes hint metrics gets set for us, most notably for printing. // Sometimes hint metrics gets set for us, most notably for printing.
#ifdef MOZ_TREE_CAIRO
cairo_hint_metrics_t hint_metrics = cairo_hint_metrics_t hint_metrics =
cairo_scaled_font_get_hint_metrics(scaled_font); cairo_scaled_font_get_hint_metrics(scaled_font);
#else
cairo_font_options_t* font_options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, font_options);
cairo_hint_metrics_t hint_metrics =
cairo_font_options_get_hint_metrics(font_options);
cairo_font_options_destroy(font_options);
#endif
switch (hint_metrics) { switch (hint_metrics) {
case CAIRO_HINT_METRICS_OFF: case CAIRO_HINT_METRICS_OFF:

View file

@ -767,14 +767,16 @@ nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent,
return true; return true;
} }
CSPDirective directive = nsIContentSecurityPolicy::STYLE_SRC_ATTR_DIRECTIVE;
// query the nonce // query the nonce
nsAutoString nonce; nsAutoString nonce;
if (aContent) { if (aContent) {
directive = nsIContentSecurityPolicy::STYLE_SRC_ELEM_DIRECTIVE;
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce); aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce);
} }
bool allowInlineStyle = true; bool allowInlineStyle = true;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_STYLESHEET, rv = csp->GetAllowsInline(directive,
nonce, nonce,
false, // aParserCreated only applies to scripts false, // aParserCreated only applies to scripts
aStyleText, aLineNumber, aColumnNumber, aStyleText, aLineNumber, aColumnNumber,