Bug 1839165 - Throttle the number of CSP reports that are send. r=freddyb

Differential Revision: https://phabricator.services.mozilla.com/D181392
This commit is contained in:
Tom Schuster 2023-07-24 11:11:58 +00:00
parent 3df9efb9b4
commit f704cb4b7d
5 changed files with 75 additions and 4 deletions

View File

@ -20,6 +20,7 @@ CSPROViolationWithURI = The pages settings observed the loading of a resource
# LOCALIZATION NOTE (triedToSendReport):
# %1$S is the URI we attempted to send a report to.
triedToSendReport = Tried to send report to invalid URI: “%1$S”
tooManyReports = Prevented too many CSP reports from being sent within a short period of time.
# LOCALIZATION NOTE (couldNotParseReportURI):
# %1$S is the report URI that could not be parsed
couldNotParseReportURI = couldnt parse report URI: %1$S

View File

@ -1147,12 +1147,63 @@ nsresult nsCSPContext::GatherSecurityPolicyViolationEventData(
return NS_OK;
}
bool nsCSPContext::ShouldThrottleReport(
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
// Fetch rate limiting preferences
const uint32_t kLimitCount =
StaticPrefs::security_csp_reporting_limit_count();
const uint32_t kTimeSpanSeconds =
StaticPrefs::security_csp_reporting_limit_timespan();
// Disable throttling if either of the preferences is set to 0.
if (kLimitCount == 0 || kTimeSpanSeconds == 0) {
return false;
}
TimeDuration throttleSpan = TimeDuration::FromSeconds(kTimeSpanSeconds);
if (mSendReportLimitSpanStart.IsNull() ||
((TimeStamp::Now() - mSendReportLimitSpanStart) > throttleSpan)) {
// Initial call or timespan exceeded, reset counter and timespan.
mSendReportLimitSpanStart = TimeStamp::Now();
mSendReportLimitCount = 1;
// Also make sure we warn about omitted messages. (XXX or only do this once
// per context?)
mWarnedAboutTooManyReports = false;
return false;
}
if (mSendReportLimitCount < kLimitCount) {
mSendReportLimitCount++;
return false;
}
// Rate limit reached
if (!mWarnedAboutTooManyReports) {
logToConsole("tooManyReports", {}, aViolationEventInit.mSourceFile,
aViolationEventInit.mSample, aViolationEventInit.mLineNumber,
aViolationEventInit.mColumnNumber, nsIScriptError::errorFlag);
mWarnedAboutTooManyReports = true;
}
return true;
}
nsresult nsCSPContext::SendReports(
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit,
uint32_t aViolatedPolicyIndex) {
EnsureIPCPoliciesRead();
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
nsTArray<nsString> reportURIs;
mPolicies[aViolatedPolicyIndex]->getReportURIs(reportURIs);
// There is nowhere to send reports to.
if (reportURIs.IsEmpty()) {
return NS_OK;
}
if (ShouldThrottleReport(aViolationEventInit)) {
return NS_OK;
}
dom::CSPReport report;
// blocked-uri
@ -1211,10 +1262,6 @@ nsresult nsCSPContext::SendReports(
}
// ---------- Assembled, now send it to all the report URIs ----------- //
nsTArray<nsString> reportURIs;
mPolicies[aViolatedPolicyIndex]->getReportURIs(reportURIs);
nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
nsCOMPtr<nsIURI> reportURI;
nsCOMPtr<nsIChannel> reportChannel;

View File

@ -151,6 +151,10 @@ class nsCSPContext : public nsIContentSecurityPolicy {
private:
void EnsureIPCPoliciesRead();
bool ShouldThrottleReport(
const mozilla::dom::SecurityPolicyViolationEventInit&
aViolationEventInit);
bool permitsInternal(CSPDirective aDir,
mozilla::dom::Element* aTriggeringElement,
nsICSPEventListener* aCSPEventListener,
@ -192,6 +196,10 @@ class nsCSPContext : public nsIContentSecurityPolicy {
nsTArray<ConsoleMsgQueueElem> mConsoleMsgQueue;
bool mQueueUpMessages;
nsCOMPtr<nsIEventTarget> mEventTarget;
mozilla::TimeStamp mSendReportLimitSpanStart;
uint32_t mSendReportLimitCount = 1;
bool mWarnedAboutTooManyReports = false;
};
// Class that listens to violation report transmission and logs errors.

View File

@ -13489,6 +13489,18 @@
value: true
mirror: always
# Limit the number of CSP reports that are send in a specific timespan.
- name: security.csp.reporting.limit.count
type: uint32_t
value: 100
mirror: always
# Time span in seconds for reporting limit.
- name: security.csp.reporting.limit.timespan
type: uint32_t
value: 2
mirror: always
# If true, all toplevel data: URI navigations will be blocked.
# Please note that manually entering a data: URI in the
# URL-Bar will not be blocked when flipping this pref.

View File

@ -21,6 +21,9 @@ Services.prefs.setIntPref(
4096
);
// Do not limit the number of CSP reports.
Services.prefs.setIntPref("security.csp.reporting.limit.count", 0);
// Do not trunacate the blocked-uri in CSP reports for frame navigations.
Services.prefs.setBoolPref(
"security.csp.truncate_blocked_uri_for_frame_navigations",