Bug 1890277: part 4) Add CSPParser support for the trusted-types directive, guarded behind the Trusted Types pref. r=tschuster,webidl,smaug
Differential Revision: https://phabricator.services.mozilla.com/D207274
This commit is contained in:
@@ -66,6 +66,7 @@ interface nsIContentSecurityPolicy : nsISerializable
|
||||
STYLE_SRC_ELEM_DIRECTIVE = 23,
|
||||
STYLE_SRC_ATTR_DIRECTIVE = 24,
|
||||
REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE = 25,
|
||||
TRUSTED_TYPES_DIRECTIVE = 26,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -207,7 +207,9 @@ invalidNumberOfTrustedTypesForDirectiveValues = Received an invalid number of to
|
||||
# LOCALIZATION NOTE (invalidRequireTrustedTypesForDirectiveValue):
|
||||
# %1$S is the passed token
|
||||
invalidRequireTrustedTypesForDirectiveValue = Received an invalid token for the ‘require-trusted-types-for‘ directive: %1$S; expected ‘script‘
|
||||
|
||||
# LOCALIZATION NOTE (invalidTrustedTypesExpression):
|
||||
# %1$S is the passed token
|
||||
invalidTrustedTypesExpression = Received an invalid token for the 'trusted-types' directive: %1$S
|
||||
|
||||
# LOCALIZATION NOTE (CSPMessagePrefix):
|
||||
# Do not translate "Content-Security-Policy", only handle spacing for the colon.
|
||||
|
||||
@@ -865,6 +865,94 @@ void nsCSPParser::handleRequireTrustedTypesForDirective(nsCSPDirective* aDir) {
|
||||
mPolicy->addDirective(aDir);
|
||||
}
|
||||
|
||||
static constexpr auto kTrustedTypesKeywordAllowDuplicates =
|
||||
u"'allow-duplicates'"_ns;
|
||||
static constexpr auto kTrustedTypesKeywordNone = u"'none'"_ns;
|
||||
|
||||
static bool IsValidTrustedTypesKeyword(const nsAString& aToken) {
|
||||
// tt-keyword = "'allow-duplicates'" / "'none'"
|
||||
return aToken.Equals(kTrustedTypesKeywordAllowDuplicates) ||
|
||||
aToken.Equals(kTrustedTypesKeywordNone);
|
||||
}
|
||||
|
||||
static bool IsValidTrustedTypesWildcard(const nsAString& aToken) {
|
||||
// tt-wildcard = "*"
|
||||
return aToken.Length() == 1 && aToken.First() == WILDCARD;
|
||||
}
|
||||
|
||||
static bool IsValidTrustedTypesPolicyNameChar(char16_t aChar) {
|
||||
// tt-policy-name = 1*( ALPHA / DIGIT / "-" / "#" / "=" / "_" / "/" / "@" /
|
||||
// "." / "%")
|
||||
return nsContentUtils::IsAlphanumeric(aChar) || aChar == DASH ||
|
||||
aChar == NUMBER_SIGN || aChar == EQUALS || aChar == UNDERLINE ||
|
||||
aChar == SLASH || aChar == ATSYMBOL || aChar == DOT ||
|
||||
aChar == PERCENT_SIGN;
|
||||
}
|
||||
|
||||
static bool IsValidTrustedTypesPolicyName(const nsAString& aToken) {
|
||||
// tt-policy-name = 1*( ALPHA / DIGIT / "-" / "#" / "=" / "_" / "/" / "@" /
|
||||
// "." / "%")
|
||||
|
||||
if (aToken.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < aToken.Length(); ++i) {
|
||||
if (!IsValidTrustedTypesPolicyNameChar(aToken.CharAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/trusted-types/dist/spec/#trusted-types-csp-directive
|
||||
static bool IsValidTrustedTypesExpression(const nsAString& aToken) {
|
||||
// tt-expression = tt-policy-name / tt-keyword / tt-wildcard
|
||||
return IsValidTrustedTypesPolicyName(aToken) ||
|
||||
IsValidTrustedTypesKeyword(aToken) ||
|
||||
IsValidTrustedTypesWildcard(aToken);
|
||||
}
|
||||
|
||||
void nsCSPParser::handleTrustedTypesDirective(nsCSPDirective* aDir) {
|
||||
CSPPARSERLOG(("nsCSPParser::handleTrustedTypesDirective"));
|
||||
|
||||
nsTArray<nsCSPBaseSrc*> trustedTypesExpressions;
|
||||
|
||||
// "srcs" start and index 1. Here they should represent the tt-expressions
|
||||
// (https://w3c.github.io/trusted-types/dist/spec/#trusted-types-csp-directive).
|
||||
for (uint32_t i = 1; i < mCurDir.Length(); ++i) {
|
||||
mCurToken = mCurDir[i];
|
||||
|
||||
CSPPARSERLOG(("nsCSPParser::handleTrustedTypesDirective, mCurToken: %s",
|
||||
NS_ConvertUTF16toUTF8(mCurToken).get()));
|
||||
|
||||
if (!IsValidTrustedTypesExpression(mCurToken)) {
|
||||
AutoTArray<nsString, 1> token = {mCurToken};
|
||||
logWarningErrorToConsole(nsIScriptError::errorFlag,
|
||||
"invalidTrustedTypesExpression", token);
|
||||
|
||||
for (auto* trustedTypeExpression : trustedTypesExpressions) {
|
||||
delete trustedTypeExpression;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
trustedTypesExpressions.AppendElement(
|
||||
new nsCSPTrustedTypesDirectiveExpression(mCurToken));
|
||||
}
|
||||
|
||||
if (trustedTypesExpressions.IsEmpty()) {
|
||||
// No tt-expression is equivalent to 'none', see
|
||||
// <https://w3c.github.io/trusted-types/dist/spec/#trusted-types-csp-directive>.
|
||||
trustedTypesExpressions.AppendElement(new nsCSPKeywordSrc(CSP_NONE));
|
||||
}
|
||||
|
||||
aDir->addSrcs(trustedTypesExpressions);
|
||||
mPolicy->addDirective(aDir);
|
||||
}
|
||||
|
||||
// directive-value = *( WSP / <VCHAR except ";" and ","> )
|
||||
void nsCSPParser::directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs) {
|
||||
CSPPARSERLOG(("nsCSPParser::directiveValue"));
|
||||
@@ -883,8 +971,9 @@ nsCSPDirective* nsCSPParser::directiveName() {
|
||||
CSPDirective directive = CSP_StringToCSPDirective(mCurToken);
|
||||
if (directive == nsIContentSecurityPolicy::NO_DIRECTIVE ||
|
||||
(!StaticPrefs::dom_security_trusted_types_enabled() &&
|
||||
directive ==
|
||||
nsIContentSecurityPolicy::REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE)) {
|
||||
(directive ==
|
||||
nsIContentSecurityPolicy::REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE ||
|
||||
directive == nsIContentSecurityPolicy::TRUSTED_TYPES_DIRECTIVE))) {
|
||||
AutoTArray<nsString, 1> params = {mCurToken};
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"couldNotProcessUnknownDirective", params);
|
||||
@@ -1071,6 +1160,11 @@ void nsCSPParser::directive() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cspDir->equals(nsIContentSecurityPolicy::TRUSTED_TYPES_DIRECTIVE)) {
|
||||
handleTrustedTypesDirective(cspDir);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
mHasHashOrNonce = false;
|
||||
|
||||
@@ -73,6 +73,7 @@ class nsCSPParser {
|
||||
void reportURIList(nsCSPDirective* aDir);
|
||||
void sandboxFlagList(nsCSPDirective* aDir);
|
||||
void handleRequireTrustedTypesForDirective(nsCSPDirective* aDir);
|
||||
void handleTrustedTypesDirective(nsCSPDirective* aDir);
|
||||
void sourceList(nsTArray<nsCSPBaseSrc*>& outSrcs);
|
||||
nsCSPBaseSrc* sourceExpression();
|
||||
nsCSPSchemeSrc* schemeSource();
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/dom/CSPDictionariesBinding.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
@@ -1029,6 +1030,23 @@ void nsCSPRequireTrustedTypesForDirectiveValue::toString(
|
||||
aOutStr.Append(mValue);
|
||||
}
|
||||
|
||||
/* =============== nsCSPTrustedTypesDirectiveExpression =============== */
|
||||
|
||||
nsCSPTrustedTypesDirectiveExpression::nsCSPTrustedTypesDirectiveExpression(
|
||||
const nsAString& aExpression)
|
||||
: mExpression{aExpression} {}
|
||||
|
||||
bool nsCSPTrustedTypesDirectiveExpression::visit(
|
||||
nsCSPSrcVisitor* aVisitor) const {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Should only be called for other overloads of this method.");
|
||||
return false;
|
||||
}
|
||||
|
||||
void nsCSPTrustedTypesDirectiveExpression::toString(nsAString& aOutStr) const {
|
||||
aOutStr.Append(mExpression);
|
||||
}
|
||||
|
||||
/* ===== nsCSPDirective ====================== */
|
||||
|
||||
nsCSPDirective::nsCSPDirective(CSPDirective aDirective) {
|
||||
@@ -1311,6 +1329,9 @@ bool nsCSPDirective::allowsAllInlineBehavior(CSPDirective aDir) const {
|
||||
void nsCSPDirective::toString(nsAString& outStr) const {
|
||||
// Append directive name
|
||||
outStr.AppendASCII(CSP_CSPDirectiveToString(mDirective));
|
||||
|
||||
MOZ_ASSERT(!mSrcs.IsEmpty());
|
||||
|
||||
outStr.AppendLiteral(" ");
|
||||
|
||||
// Append srcs
|
||||
@@ -1454,6 +1475,13 @@ void nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const {
|
||||
outCSP.mRequire_trusted_types_for.Value() = std::move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::TRUSTED_TYPES_DIRECTIVE:
|
||||
outCSP.mTrusted_types.Construct();
|
||||
// Here, "srcs" represents tt-expressions
|
||||
// (https://w3c.github.io/trusted-types/dist/spec/#trusted-types-csp-directive).
|
||||
outCSP.mTrusted_types.Value() = std::move(srcs);
|
||||
return;
|
||||
|
||||
default:
|
||||
NS_ASSERTION(false, "cannot find directive to convert CSP to JSON");
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ static const char* CSPStrDirectives[] = {
|
||||
"style-src-elem", // STYLE_SRC_ELEM_DIRECTIVE
|
||||
"style-src-attr", // STYLE_SRC_ATTR_DIRECTIVE
|
||||
"require-trusted-types-for", // REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE
|
||||
"trusted-types", // TRUSTED_TYPES_DIRECTIVE
|
||||
};
|
||||
|
||||
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir) {
|
||||
@@ -400,6 +401,20 @@ class nsCSPRequireTrustedTypesForDirectiveValue : public nsCSPBaseSrc {
|
||||
const nsString mValue;
|
||||
};
|
||||
|
||||
/* =============== nsCSPTrustedTypesDirectiveExpression =============== */
|
||||
|
||||
class nsCSPTrustedTypesDirectiveExpression : public nsCSPBaseSrc {
|
||||
public:
|
||||
explicit nsCSPTrustedTypesDirectiveExpression(const nsAString& aExpression);
|
||||
virtual ~nsCSPTrustedTypesDirectiveExpression() = default;
|
||||
|
||||
bool visit(nsCSPSrcVisitor* aVisitor) const override;
|
||||
void toString(nsAString& aOutStr) const override;
|
||||
|
||||
private:
|
||||
const nsString mExpression;
|
||||
};
|
||||
|
||||
/* =============== nsCSPSrcVisitor ================== */
|
||||
|
||||
class nsCSPSrcVisitor {
|
||||
@@ -435,6 +450,7 @@ class nsCSPDirective {
|
||||
virtual void toString(nsAString& outStr) const;
|
||||
void toDomCSPStruct(mozilla::dom::CSP& outCSP) const;
|
||||
|
||||
// Takes ownership of the passed sources.
|
||||
virtual void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs) {
|
||||
mSrcs = aSrcs.Clone();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ dictionary CSP {
|
||||
sequence<DOMString> script-src-elem;
|
||||
sequence<DOMString> script-src-attr;
|
||||
sequence<DOMString> require-trusted-types-for;
|
||||
sequence<DOMString> trusted-types;
|
||||
};
|
||||
|
||||
[GenerateToJSON]
|
||||
|
||||
Reference in New Issue
Block a user