mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1890277: part 2) Add require-trusted-types-for
directive to CSP parser, guarded behind the Trusted Types pref. r=tschuster,webidl,smaug
Differential Revision: https://phabricator.services.mozilla.com/D206998
This commit is contained in:
parent
2fcd7e5c5c
commit
db3ca28481
@ -40,31 +40,32 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||||||
* add it to the CSPStrDirectives array in nsCSPUtils.h.
|
* add it to the CSPStrDirectives array in nsCSPUtils.h.
|
||||||
*/
|
*/
|
||||||
cenum CSPDirective : 8 {
|
cenum CSPDirective : 8 {
|
||||||
NO_DIRECTIVE = 0,
|
NO_DIRECTIVE = 0,
|
||||||
DEFAULT_SRC_DIRECTIVE = 1,
|
DEFAULT_SRC_DIRECTIVE = 1,
|
||||||
SCRIPT_SRC_DIRECTIVE = 2,
|
SCRIPT_SRC_DIRECTIVE = 2,
|
||||||
OBJECT_SRC_DIRECTIVE = 3,
|
OBJECT_SRC_DIRECTIVE = 3,
|
||||||
STYLE_SRC_DIRECTIVE = 4,
|
STYLE_SRC_DIRECTIVE = 4,
|
||||||
IMG_SRC_DIRECTIVE = 5,
|
IMG_SRC_DIRECTIVE = 5,
|
||||||
MEDIA_SRC_DIRECTIVE = 6,
|
MEDIA_SRC_DIRECTIVE = 6,
|
||||||
FRAME_SRC_DIRECTIVE = 7,
|
FRAME_SRC_DIRECTIVE = 7,
|
||||||
FONT_SRC_DIRECTIVE = 8,
|
FONT_SRC_DIRECTIVE = 8,
|
||||||
CONNECT_SRC_DIRECTIVE = 9,
|
CONNECT_SRC_DIRECTIVE = 9,
|
||||||
REPORT_URI_DIRECTIVE = 10,
|
REPORT_URI_DIRECTIVE = 10,
|
||||||
FRAME_ANCESTORS_DIRECTIVE = 11,
|
FRAME_ANCESTORS_DIRECTIVE = 11,
|
||||||
REFLECTED_XSS_DIRECTIVE = 12,
|
REFLECTED_XSS_DIRECTIVE = 12,
|
||||||
BASE_URI_DIRECTIVE = 13,
|
BASE_URI_DIRECTIVE = 13,
|
||||||
FORM_ACTION_DIRECTIVE = 14,
|
FORM_ACTION_DIRECTIVE = 14,
|
||||||
WEB_MANIFEST_SRC_DIRECTIVE = 15,
|
WEB_MANIFEST_SRC_DIRECTIVE = 15,
|
||||||
UPGRADE_IF_INSECURE_DIRECTIVE = 16,
|
UPGRADE_IF_INSECURE_DIRECTIVE = 16,
|
||||||
CHILD_SRC_DIRECTIVE = 17,
|
CHILD_SRC_DIRECTIVE = 17,
|
||||||
BLOCK_ALL_MIXED_CONTENT = 18,
|
BLOCK_ALL_MIXED_CONTENT = 18,
|
||||||
SANDBOX_DIRECTIVE = 19,
|
SANDBOX_DIRECTIVE = 19,
|
||||||
WORKER_SRC_DIRECTIVE = 20,
|
WORKER_SRC_DIRECTIVE = 20,
|
||||||
SCRIPT_SRC_ELEM_DIRECTIVE = 21,
|
SCRIPT_SRC_ELEM_DIRECTIVE = 21,
|
||||||
SCRIPT_SRC_ATTR_DIRECTIVE = 22,
|
SCRIPT_SRC_ATTR_DIRECTIVE = 22,
|
||||||
STYLE_SRC_ELEM_DIRECTIVE = 23,
|
STYLE_SRC_ELEM_DIRECTIVE = 23,
|
||||||
STYLE_SRC_ATTR_DIRECTIVE = 24,
|
STYLE_SRC_ATTR_DIRECTIVE = 24,
|
||||||
|
REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE = 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -201,6 +201,13 @@ duplicateDirective = Duplicate %1$S directives detected. All but the first inst
|
|||||||
# LOCALIZATION NOTE (couldntParseInvalidSandboxFlag):
|
# LOCALIZATION NOTE (couldntParseInvalidSandboxFlag):
|
||||||
# %1$S is the option that could not be understood
|
# %1$S is the option that could not be understood
|
||||||
couldntParseInvalidSandboxFlag = Couldn’t parse invalid sandbox flag ‘%1$S’
|
couldntParseInvalidSandboxFlag = Couldn’t parse invalid sandbox flag ‘%1$S’
|
||||||
|
# LOCALIZATION NOTE (invalidNumberOfTrustedTypesForDirectiveValues):
|
||||||
|
# %1$S is the number of passed tokens.
|
||||||
|
invalidNumberOfTrustedTypesForDirectiveValues = Received an invalid number of tokens for the 'require-trusted-types-for' directive: %1$S; expected 1
|
||||||
|
# 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 (CSPMessagePrefix):
|
# LOCALIZATION NOTE (CSPMessagePrefix):
|
||||||
# Do not translate "Content-Security-Policy", only handle spacing for the colon.
|
# Do not translate "Content-Security-Policy", only handle spacing for the colon.
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "mozilla/TextUtils.h"
|
#include "mozilla/TextUtils.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
#include "mozilla/StaticPrefs_security.h"
|
#include "mozilla/StaticPrefs_security.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
@ -19,6 +20,9 @@
|
|||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "nsUnicharUtils.h"
|
#include "nsUnicharUtils.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
@ -813,6 +817,54 @@ void nsCSPParser::sandboxFlagList(nsCSPDirective* aDir) {
|
|||||||
mPolicy->addDirective(aDir);
|
mPolicy->addDirective(aDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/trusted-types/dist/spec/#integration-with-content-security-policy
|
||||||
|
static constexpr nsLiteralString kValidRequireTrustedTypesForDirectiveValue =
|
||||||
|
u"'script'"_ns;
|
||||||
|
|
||||||
|
static bool IsValidRequireTrustedTypesForDirectiveValue(
|
||||||
|
const nsAString& aToken) {
|
||||||
|
return aToken.Equals(kValidRequireTrustedTypesForDirectiveValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsCSPParser::handleRequireTrustedTypesForDirective(nsCSPDirective* aDir) {
|
||||||
|
// "srcs" start at index 1. Here "srcs" should represent Trusted Types' sink
|
||||||
|
// groups
|
||||||
|
// (https://w3c.github.io/trusted-types/dist/spec/#require-trusted-types-for-csp-directive).
|
||||||
|
|
||||||
|
if (mCurDir.Length() != 2) {
|
||||||
|
nsString numberOfTokensStr;
|
||||||
|
|
||||||
|
// Casting is required to avoid ambiguous function calls on some platforms.
|
||||||
|
numberOfTokensStr.AppendInt(static_cast<uint64_t>(mCurDir.Length()));
|
||||||
|
|
||||||
|
AutoTArray<nsString, 1> numberOfTokensArr = {std::move(numberOfTokensStr)};
|
||||||
|
logWarningErrorToConsole(nsIScriptError::errorFlag,
|
||||||
|
"invalidNumberOfTrustedTypesForDirectiveValues",
|
||||||
|
numberOfTokensArr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurToken = mCurDir.LastElement();
|
||||||
|
|
||||||
|
CSPPARSERLOG(
|
||||||
|
("nsCSPParser::handleRequireTrustedTypesForDirective, mCurToken: %s",
|
||||||
|
NS_ConvertUTF16toUTF8(mCurToken).get()));
|
||||||
|
|
||||||
|
if (!IsValidRequireTrustedTypesForDirectiveValue(mCurToken)) {
|
||||||
|
AutoTArray<nsString, 1> token = {mCurToken};
|
||||||
|
logWarningErrorToConsole(nsIScriptError::errorFlag,
|
||||||
|
"invalidRequireTrustedTypesForDirectiveValue",
|
||||||
|
token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsCSPBaseSrc*> srcs = {
|
||||||
|
new nsCSPRequireTrustedTypesForDirectiveValue(mCurToken)};
|
||||||
|
|
||||||
|
aDir->addSrcs(srcs);
|
||||||
|
mPolicy->addDirective(aDir);
|
||||||
|
}
|
||||||
|
|
||||||
// directive-value = *( WSP / <VCHAR except ";" and ","> )
|
// directive-value = *( WSP / <VCHAR except ";" and ","> )
|
||||||
void nsCSPParser::directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs) {
|
void nsCSPParser::directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs) {
|
||||||
CSPPARSERLOG(("nsCSPParser::directiveValue"));
|
CSPPARSERLOG(("nsCSPParser::directiveValue"));
|
||||||
@ -829,7 +881,10 @@ nsCSPDirective* nsCSPParser::directiveName() {
|
|||||||
|
|
||||||
// Check if it is a valid directive
|
// Check if it is a valid directive
|
||||||
CSPDirective directive = CSP_StringToCSPDirective(mCurToken);
|
CSPDirective directive = CSP_StringToCSPDirective(mCurToken);
|
||||||
if (directive == nsIContentSecurityPolicy::NO_DIRECTIVE) {
|
if (directive == nsIContentSecurityPolicy::NO_DIRECTIVE ||
|
||||||
|
(!StaticPrefs::dom_security_trusted_types_enabled() &&
|
||||||
|
directive ==
|
||||||
|
nsIContentSecurityPolicy::REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE)) {
|
||||||
AutoTArray<nsString, 1> params = {mCurToken};
|
AutoTArray<nsString, 1> params = {mCurToken};
|
||||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||||
"couldNotProcessUnknownDirective", params);
|
"couldNotProcessUnknownDirective", params);
|
||||||
@ -1008,6 +1063,14 @@ void nsCSPParser::directive() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case handling since these directives don't contain source lists.
|
||||||
|
if (CSP_IsDirective(
|
||||||
|
mCurDir[0],
|
||||||
|
nsIContentSecurityPolicy::REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE)) {
|
||||||
|
handleRequireTrustedTypesForDirective(cspDir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -72,6 +72,7 @@ class nsCSPParser {
|
|||||||
void referrerDirectiveValue(nsCSPDirective* aDir);
|
void referrerDirectiveValue(nsCSPDirective* aDir);
|
||||||
void reportURIList(nsCSPDirective* aDir);
|
void reportURIList(nsCSPDirective* aDir);
|
||||||
void sandboxFlagList(nsCSPDirective* aDir);
|
void sandboxFlagList(nsCSPDirective* aDir);
|
||||||
|
void handleRequireTrustedTypesForDirective(nsCSPDirective* aDir);
|
||||||
void sourceList(nsTArray<nsCSPBaseSrc*>& outSrcs);
|
void sourceList(nsTArray<nsCSPBaseSrc*>& outSrcs);
|
||||||
nsCSPBaseSrc* sourceExpression();
|
nsCSPBaseSrc* sourceExpression();
|
||||||
nsCSPSchemeSrc* schemeSource();
|
nsCSPSchemeSrc* schemeSource();
|
||||||
|
@ -243,6 +243,20 @@ void CSP_LogMessage(const nsAString& aMessage, const nsAString& aSourceName,
|
|||||||
console->LogMessage(error);
|
console->LogMessage(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSPDirective CSP_StringToCSPDirective(const nsAString& aDir) {
|
||||||
|
nsString lowerDir = PromiseFlatString(aDir);
|
||||||
|
ToLowerCase(lowerDir);
|
||||||
|
|
||||||
|
uint32_t numDirs = (sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0]));
|
||||||
|
|
||||||
|
for (uint32_t i = 1; i < numDirs; i++) {
|
||||||
|
if (lowerDir.EqualsASCII(CSPStrDirectives[i])) {
|
||||||
|
return static_cast<CSPDirective>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nsIContentSecurityPolicy::NO_DIRECTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines CSP_LogMessage and CSP_GetLocalizedStr into one call.
|
* Combines CSP_LogMessage and CSP_GetLocalizedStr into one call.
|
||||||
*/
|
*/
|
||||||
@ -997,6 +1011,24 @@ void nsCSPSandboxFlags::toString(nsAString& outStr) const {
|
|||||||
outStr.Append(mFlags);
|
outStr.Append(mFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===== nsCSPRequireTrustedTypesForDirectiveValue ===================== */
|
||||||
|
|
||||||
|
nsCSPRequireTrustedTypesForDirectiveValue::
|
||||||
|
nsCSPRequireTrustedTypesForDirectiveValue(const nsAString& aValue)
|
||||||
|
: mValue{aValue} {}
|
||||||
|
|
||||||
|
bool nsCSPRequireTrustedTypesForDirectiveValue::visit(
|
||||||
|
nsCSPSrcVisitor* aVisitor) const {
|
||||||
|
MOZ_ASSERT_UNREACHABLE(
|
||||||
|
"This method should only be called for other overloads of this method.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsCSPRequireTrustedTypesForDirectiveValue::toString(
|
||||||
|
nsAString& aOutStr) const {
|
||||||
|
aOutStr.Append(mValue);
|
||||||
|
}
|
||||||
|
|
||||||
/* ===== nsCSPDirective ====================== */
|
/* ===== nsCSPDirective ====================== */
|
||||||
|
|
||||||
nsCSPDirective::nsCSPDirective(CSPDirective aDirective) {
|
nsCSPDirective::nsCSPDirective(CSPDirective aDirective) {
|
||||||
@ -1414,6 +1446,14 @@ void nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const {
|
|||||||
outCSP.mScript_src_attr.Value() = std::move(srcs);
|
outCSP.mScript_src_attr.Value() = std::move(srcs);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case nsIContentSecurityPolicy::REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE:
|
||||||
|
outCSP.mRequire_trusted_types_for.Construct();
|
||||||
|
|
||||||
|
// Here, the srcs represent the sink group
|
||||||
|
// (https://w3c.github.io/trusted-types/dist/spec/#integration-with-content-security-policy).
|
||||||
|
outCSP.mRequire_trusted_types_for.Value() = std::move(srcs);
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
NS_ASSERTION(false, "cannot find directive to convert CSP to JSON");
|
NS_ASSERTION(false, "cannot find directive to convert CSP to JSON");
|
||||||
}
|
}
|
||||||
|
@ -93,24 +93,14 @@ static const char* CSPStrDirectives[] = {
|
|||||||
"script-src-attr", // SCRIPT_SRC_ATTR_DIRECTIVE
|
"script-src-attr", // SCRIPT_SRC_ATTR_DIRECTIVE
|
||||||
"style-src-elem", // STYLE_SRC_ELEM_DIRECTIVE
|
"style-src-elem", // STYLE_SRC_ELEM_DIRECTIVE
|
||||||
"style-src-attr", // STYLE_SRC_ATTR_DIRECTIVE
|
"style-src-attr", // STYLE_SRC_ATTR_DIRECTIVE
|
||||||
|
"require-trusted-types-for", // REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir) {
|
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir) {
|
||||||
return CSPStrDirectives[static_cast<uint32_t>(aDir)];
|
return CSPStrDirectives[static_cast<uint32_t>(aDir)];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline CSPDirective CSP_StringToCSPDirective(const nsAString& aDir) {
|
CSPDirective CSP_StringToCSPDirective(const nsAString& aDir);
|
||||||
nsString lowerDir = PromiseFlatString(aDir);
|
|
||||||
ToLowerCase(lowerDir);
|
|
||||||
|
|
||||||
uint32_t numDirs = (sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0]));
|
|
||||||
for (uint32_t i = 1; i < numDirs; i++) {
|
|
||||||
if (lowerDir.EqualsASCII(CSPStrDirectives[i])) {
|
|
||||||
return static_cast<CSPDirective>(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nsIContentSecurityPolicy::NO_DIRECTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FOR_EACH_CSP_KEYWORD(MACRO) \
|
#define FOR_EACH_CSP_KEYWORD(MACRO) \
|
||||||
MACRO(CSP_SELF, "'self'") \
|
MACRO(CSP_SELF, "'self'") \
|
||||||
@ -396,6 +386,20 @@ class nsCSPSandboxFlags : public nsCSPBaseSrc {
|
|||||||
nsString mFlags;
|
nsString mFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* =============== nsCSPRequireTrustedTypesForDirectiveValue =============== */
|
||||||
|
|
||||||
|
class nsCSPRequireTrustedTypesForDirectiveValue : public nsCSPBaseSrc {
|
||||||
|
public:
|
||||||
|
explicit nsCSPRequireTrustedTypesForDirectiveValue(const nsAString& aValue);
|
||||||
|
virtual ~nsCSPRequireTrustedTypesForDirectiveValue() = default;
|
||||||
|
|
||||||
|
bool visit(nsCSPSrcVisitor* aVisitor) const override;
|
||||||
|
void toString(nsAString& aOutStr) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const nsString mValue;
|
||||||
|
};
|
||||||
|
|
||||||
/* =============== nsCSPSrcVisitor ================== */
|
/* =============== nsCSPSrcVisitor ================== */
|
||||||
|
|
||||||
class nsCSPSrcVisitor {
|
class nsCSPSrcVisitor {
|
||||||
|
@ -32,6 +32,7 @@ dictionary CSP {
|
|||||||
sequence<DOMString> worker-src;
|
sequence<DOMString> worker-src;
|
||||||
sequence<DOMString> script-src-elem;
|
sequence<DOMString> script-src-elem;
|
||||||
sequence<DOMString> script-src-attr;
|
sequence<DOMString> script-src-attr;
|
||||||
|
sequence<DOMString> require-trusted-types-for;
|
||||||
};
|
};
|
||||||
|
|
||||||
[GenerateToJSON]
|
[GenerateToJSON]
|
||||||
|
Loading…
Reference in New Issue
Block a user