Bug 1645745 - Suppress CSP parser errors/warnings in certain cases. r=freddyb

Differential Revision: https://phabricator.services.mozilla.com/D163815
This commit is contained in:
Tom Schuster 2022-12-19 11:52:45 +00:00
parent ab6806623e
commit f66c3665b0
6 changed files with 46 additions and 8 deletions

View File

@ -314,17 +314,27 @@ nsresult nsCSPContext::InitFromOther(nsCSPContext* aOtherContext) {
mSkipAllowInlineStyleCheck = aOtherContext->mSkipAllowInlineStyleCheck;
// This policy was already parsed somewhere else, don't emit parsing errors.
mSuppressParserLogMessages = true;
for (auto policy : aOtherContext->mPolicies) {
nsAutoString policyStr;
policy->toString(policyStr);
AppendPolicy(policyStr, policy->getReportOnlyFlag(),
policy->getDeliveredViaMetaTagFlag());
}
mSuppressParserLogMessages = aOtherContext->mSuppressParserLogMessages;
mIPCPolicies = aOtherContext->mIPCPolicies.Clone();
return NS_OK;
}
void nsCSPContext::EnsureIPCPoliciesRead() {
// Most likely the parser errors already happened before serializing
// the policy for IPC.
bool previous = mSuppressParserLogMessages;
mSuppressParserLogMessages = true;
if (mIPCPolicies.Length() > 0) {
nsresult rv;
for (auto& policy : mIPCPolicies) {
@ -334,6 +344,8 @@ void nsCSPContext::EnsureIPCPoliciesRead() {
}
mIPCPolicies.Clear();
}
mSuppressParserLogMessages = previous;
}
NS_IMETHODIMP
@ -435,7 +447,8 @@ nsCSPContext::AppendPolicy(const nsAString& aPolicyString, bool aReportOnly,
}
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(
aPolicyString, mSelfURI, aReportOnly, this, aDeliveredViaMetaTag);
aPolicyString, mSelfURI, aReportOnly, this, aDeliveredViaMetaTag,
mSuppressParserLogMessages);
if (policy) {
if (policy->hasDirective(
nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {

View File

@ -58,6 +58,10 @@ class nsCSPContext : public nsIContentSecurityPolicy {
// Init a CSP from a different CSP
nsresult InitFromOther(nsCSPContext* otherContext);
// Used to suppress errors and warnings produced by the parser.
// Use this when doing an one-off parsing of the CSP.
void SuppressParserLogMessages() { mSuppressParserLogMessages = true; }
/**
* SetRequestContextWithDocument() needs to be called before the
* innerWindowID is initialized on the document. Use this function
@ -182,6 +186,8 @@ class nsCSPContext : public nsIContentSecurityPolicy {
nsWeakPtr mLoadingContext;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
bool mSuppressParserLogMessages = false;
// helper members used to queue up web console messages till
// the windowID becomes available. see flushConsoleMessages()
nsTArray<ConsoleMsgQueueElem> mConsoleMsgQueue;

View File

@ -40,7 +40,8 @@ static const uint32_t kHashSourceValidFnsLen = 3;
/* ===== nsCSPParser ==================== */
nsCSPParser::nsCSPParser(policyTokens& aTokens, nsIURI* aSelfURI,
nsCSPContext* aCSPContext, bool aDeliveredViaMetaTag)
nsCSPContext* aCSPContext, bool aDeliveredViaMetaTag,
bool aSuppressLogMessages)
: mCurChar(nullptr),
mEndChar(nullptr),
mHasHashOrNonce(false),
@ -57,7 +58,8 @@ nsCSPParser::nsCSPParser(policyTokens& aTokens, nsIURI* aSelfURI,
mSelfURI(aSelfURI),
mPolicy(nullptr),
mCSPContext(aCSPContext),
mDeliveredViaMetaTag(aDeliveredViaMetaTag) {
mDeliveredViaMetaTag(aDeliveredViaMetaTag),
mSuppressLogMessages(aSuppressLogMessages) {
CSPPARSERLOG(("nsCSPParser::nsCSPParser"));
}
@ -161,6 +163,11 @@ void nsCSPParser::logWarningErrorToConsole(uint32_t aSeverityFlag,
const char* aProperty,
const nsTArray<nsString>& aParams) {
CSPPARSERLOG(("nsCSPParser::logWarningErrorToConsole: %s", aProperty));
if (mSuppressLogMessages) {
return;
}
// send console messages off to the context and let the context
// deal with it (potentially messages need to be queued up)
mCSPContext->logToConsole(aProperty, aParams,
@ -1221,7 +1228,8 @@ nsCSPPolicy* nsCSPParser::policy() {
nsCSPPolicy* nsCSPParser::parseContentSecurityPolicy(
const nsAString& aPolicyString, nsIURI* aSelfURI, bool aReportOnly,
nsCSPContext* aCSPContext, bool aDeliveredViaMetaTag) {
nsCSPContext* aCSPContext, bool aDeliveredViaMetaTag,
bool aSuppressLogMessages) {
if (CSPPARSERLOGENABLED()) {
CSPPARSERLOG(("nsCSPParser::parseContentSecurityPolicy, policy: %s",
NS_ConvertUTF16toUTF8(aPolicyString).get()));
@ -1244,7 +1252,8 @@ nsCSPPolicy* nsCSPParser::parseContentSecurityPolicy(
nsTArray<CopyableTArray<nsString> > tokens;
PolicyTokenizer::tokenizePolicy(aPolicyString, tokens);
nsCSPParser parser(tokens, aSelfURI, aCSPContext, aDeliveredViaMetaTag);
nsCSPParser parser(tokens, aSelfURI, aCSPContext, aDeliveredViaMetaTag,
aSuppressLogMessages);
// Start the parser to generate a new CSPPolicy using the generated tokens.
nsCSPPolicy* policy = parser.policy();

View File

@ -53,11 +53,13 @@ class nsCSPParser {
nsIURI* aSelfURI,
bool aReportOnly,
nsCSPContext* aCSPContext,
bool aDeliveredViaMetaTag);
bool aDeliveredViaMetaTag,
bool aSuppressLogMessages);
private:
nsCSPParser(policyTokens& aTokens, nsIURI* aSelfURI,
nsCSPContext* aCSPContext, bool aDeliveredViaMetaTag);
nsCSPContext* aCSPContext, bool aDeliveredViaMetaTag,
bool aSuppressLogMessages);
~nsCSPParser();
@ -209,6 +211,7 @@ class nsCSPParser {
nsCSPPolicy* mPolicy;
nsCSPContext* mCSPContext; // used for console logging
bool mDeliveredViaMetaTag;
bool mSuppressLogMessages;
};
#endif /* nsCSPParser_h___ */

View File

@ -1005,6 +1005,11 @@ nsresult CheckCSPFrameAncestorPolicy(nsIChannel* aChannel,
}
RefPtr<nsCSPContext> csp = new nsCSPContext();
// This CSPContext is only used for checking frame-ancestors, we
// will parse the CSP again anyway. (Unless this blocks the load, but
// parser warnings aren't really important in that case)
csp->SuppressParserLogMessages();
nsCOMPtr<nsIURI> selfURI;
nsAutoString referrerSpec;
if (httpChannel) {

View File

@ -1374,7 +1374,9 @@ void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
nsresult rv = NS_OK;
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp = mDocument->GetPreloadCsp();
if (!preloadCsp) {
preloadCsp = new nsCSPContext();
RefPtr<nsCSPContext> csp = new nsCSPContext();
csp->SuppressParserLogMessages();
preloadCsp = csp;
rv = preloadCsp->SetRequestContextWithDocument(mDocument);
NS_ENSURE_SUCCESS_VOID(rv);
}