зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1391243 - Implementing Report-To Directive r=sefeng,farre
Updated Content Security Policy reporting to align with current W3C reporting standards. Reporting now supports the usage of the report-to directive, which utilizes a client's response header field to determine where a report should be sent upon a content security policy violation occurring. Unlike the previous report-uri directive, which parsed endpoint URIs directly from the response header, report-to utilizes endpoint groups to store the URIs that will receive the report. This patch handles the reception of a CSP violation, creation of a report from said violation, and report delivery, while the parsing of the endpoint URIs are handled by D193461. While the deprecated report-uri directive remains supported, it is now only used for reporting if a client does not specify a report- to header. Differential Revision: https://phabricator.services.mozilla.com/D197480
This commit is contained in:
Родитель
04290144fe
Коммит
da762ea8c3
|
@ -72,6 +72,7 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
STYLE_SRC_ATTR_DIRECTIVE = 24,
|
||||
REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE = 25,
|
||||
TRUSTED_TYPES_DIRECTIVE = 26,
|
||||
REPORT_TO_DIRECTIVE = 27,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -154,9 +154,9 @@ strictDynamicButNoHashOrNonce = Keyword ‘strict-dynamic’ within “%1$S” w
|
|||
# LOCALIZATION NOTE (reportURInotHttpsOrHttp2):
|
||||
# %1$S is the ETLD of the report URI that is not HTTP or HTTPS
|
||||
reportURInotHttpsOrHttp2 = The report URI (%1$S) should be an HTTP or HTTPS URI.
|
||||
# LOCALIZATION NOTE (reportURInotInReportOnlyHeader):
|
||||
# LOCALIZATION NOTE (reportURINorReportToNotInReportOnlyHeader):
|
||||
# %1$S is the ETLD of the page with the policy
|
||||
reportURInotInReportOnlyHeader = This site (%1$S) has a Report-Only policy without a report URI. CSP will not block and cannot report violations of this policy.
|
||||
reportURINorReportToNotInReportOnlyHeader = This site (%1$S) has a Report-Only policy without a report-uri directive nor a report-to directive. CSP will not block and cannot report violations of this policy.
|
||||
# LOCALIZATION NOTE (failedToParseUnrecognizedSource):
|
||||
# %1$S is the CSP Source that could not be parsed
|
||||
failedToParseUnrecognizedSource = Failed to parse unrecognized source %1$S
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/CSPViolationReportBody.h"
|
||||
#include "mozilla/dom/ReportingBinding.h"
|
||||
#include "mozilla/JSONWriter.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
CSPViolationReportBody::CSPViolationReportBody(
|
||||
nsIGlobalObject* aGlobal,
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aEvent)
|
||||
: ReportBody(aGlobal),
|
||||
mDocumentURL(aEvent.mDocumentURI),
|
||||
mBlockedURL(aEvent.mBlockedURI),
|
||||
mReferrer(aEvent.mReferrer),
|
||||
mEffectiveDirective(aEvent.mEffectiveDirective),
|
||||
mOriginalPolicy(aEvent.mOriginalPolicy),
|
||||
mSourceFile(aEvent.mSourceFile),
|
||||
mSample(aEvent.mSample),
|
||||
mDisposition(aEvent.mDisposition),
|
||||
mStatusCode(aEvent.mStatusCode),
|
||||
mLineNumber(Nullable<uint32_t>(aEvent.mLineNumber)),
|
||||
mColumnNumber(Nullable<uint32_t>(aEvent.mColumnNumber)) {}
|
||||
|
||||
CSPViolationReportBody::~CSPViolationReportBody() = default;
|
||||
|
||||
JSObject* CSPViolationReportBody::WrapObject(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
|
||||
return CSPViolationReportBody_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::GetBlockedURL(nsAString& aURL) const {
|
||||
aURL = mDocumentURL;
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::GetDocumentURL(nsAString& aURL) const {
|
||||
aURL = mBlockedURL;
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::GetReferrer(nsAString& aReferrer) const {
|
||||
aReferrer = mReferrer;
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::GetEffectiveDirective(
|
||||
nsAString& aDirective) const {
|
||||
aDirective = mEffectiveDirective;
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::GetOriginalPolicy(nsAString& aPolicy) const {
|
||||
aPolicy = mOriginalPolicy;
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::GetSourceFile(nsAString& aFile) const {
|
||||
aFile = mSourceFile;
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::GetSample(nsAString& aSample) const {
|
||||
aSample = mSample;
|
||||
}
|
||||
|
||||
mozilla::dom::SecurityPolicyViolationEventDisposition
|
||||
CSPViolationReportBody::Disposition() const {
|
||||
return mDisposition;
|
||||
}
|
||||
|
||||
uint16_t CSPViolationReportBody::StatusCode() const { return mStatusCode; }
|
||||
|
||||
Nullable<uint32_t> CSPViolationReportBody::GetLineNumber() const {
|
||||
return mLineNumber;
|
||||
}
|
||||
|
||||
Nullable<uint32_t> CSPViolationReportBody::GetColumnNumber() const {
|
||||
return mColumnNumber;
|
||||
}
|
||||
|
||||
void CSPViolationReportBody::ToJSON(JSONWriter& aJSONWriter) const {
|
||||
if (mDocumentURL.IsEmpty()) {
|
||||
aJSONWriter.NullProperty("documentURL");
|
||||
} else {
|
||||
aJSONWriter.StringProperty("documentURL",
|
||||
NS_ConvertUTF16toUTF8(mDocumentURL));
|
||||
}
|
||||
|
||||
if (mBlockedURL.IsEmpty()) {
|
||||
aJSONWriter.NullProperty("blockedURL");
|
||||
} else {
|
||||
aJSONWriter.StringProperty("blockedURL",
|
||||
NS_ConvertUTF16toUTF8(mBlockedURL));
|
||||
}
|
||||
|
||||
if (mReferrer.IsEmpty()) {
|
||||
aJSONWriter.NullProperty("referrer");
|
||||
} else {
|
||||
aJSONWriter.StringProperty("referrer", NS_ConvertUTF16toUTF8(mReferrer));
|
||||
}
|
||||
|
||||
if (mEffectiveDirective.IsEmpty()) {
|
||||
aJSONWriter.NullProperty("effectiveDirective");
|
||||
} else {
|
||||
aJSONWriter.StringProperty("effectiveDirective",
|
||||
NS_ConvertUTF16toUTF8(mEffectiveDirective));
|
||||
}
|
||||
|
||||
if (mOriginalPolicy.IsEmpty()) {
|
||||
aJSONWriter.NullProperty("originalPolicy");
|
||||
} else {
|
||||
aJSONWriter.StringProperty("originalPolicy",
|
||||
NS_ConvertUTF16toUTF8(mOriginalPolicy));
|
||||
}
|
||||
|
||||
if (mSourceFile.IsEmpty()) {
|
||||
aJSONWriter.NullProperty("sourceFile");
|
||||
} else {
|
||||
aJSONWriter.StringProperty("sourceFile",
|
||||
NS_ConvertUTF16toUTF8(mSourceFile));
|
||||
}
|
||||
|
||||
if (mSample.IsEmpty()) {
|
||||
aJSONWriter.NullProperty("sample");
|
||||
} else {
|
||||
aJSONWriter.StringProperty("sample", NS_ConvertUTF16toUTF8(mSample));
|
||||
}
|
||||
|
||||
switch (mDisposition) {
|
||||
case mozilla::dom::SecurityPolicyViolationEventDisposition::Report:
|
||||
aJSONWriter.StringProperty("disposition", "report");
|
||||
break;
|
||||
case mozilla::dom::SecurityPolicyViolationEventDisposition::Enforce:
|
||||
aJSONWriter.StringProperty("disposition", "enforce");
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid disposition");
|
||||
break;
|
||||
}
|
||||
|
||||
aJSONWriter.IntProperty("statusCode", mStatusCode);
|
||||
|
||||
if (mLineNumber.IsNull()) {
|
||||
aJSONWriter.NullProperty("lineNumber");
|
||||
} else {
|
||||
aJSONWriter.IntProperty("lineNumber", mLineNumber.Value());
|
||||
}
|
||||
|
||||
if (mColumnNumber.IsNull()) {
|
||||
aJSONWriter.NullProperty("columnNumber");
|
||||
} else {
|
||||
aJSONWriter.IntProperty("columnNumber", mColumnNumber.Value());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_CSPViolationReportBody_h
|
||||
#define mozilla_dom_CSPViolationReportBody_h
|
||||
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/ReportBody.h"
|
||||
#include "mozilla/dom/SecurityPolicyViolationEvent.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class CSPViolationReportBody final : public ReportBody {
|
||||
public:
|
||||
CSPViolationReportBody(
|
||||
nsIGlobalObject* aGlobal,
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aEvent);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void GetBlockedURL(nsAString& aURL) const;
|
||||
|
||||
void GetDocumentURL(nsAString& aURL) const;
|
||||
|
||||
void GetReferrer(nsAString& aReferrer) const;
|
||||
|
||||
void GetEffectiveDirective(nsAString& aDirective) const;
|
||||
|
||||
void GetOriginalPolicy(nsAString& aPolicy) const;
|
||||
|
||||
void GetSourceFile(nsAString& aFile) const;
|
||||
|
||||
void GetSample(nsAString& aSample) const;
|
||||
|
||||
mozilla::dom::SecurityPolicyViolationEventDisposition Disposition() const;
|
||||
|
||||
uint16_t StatusCode() const;
|
||||
|
||||
Nullable<uint32_t> GetLineNumber() const;
|
||||
|
||||
Nullable<uint32_t> GetColumnNumber() const;
|
||||
|
||||
protected:
|
||||
void ToJSON(JSONWriter& aJSONWriter) const override;
|
||||
|
||||
private:
|
||||
~CSPViolationReportBody();
|
||||
|
||||
const nsString mDocumentURL;
|
||||
const nsString mBlockedURL;
|
||||
const nsString mReferrer;
|
||||
const nsString mEffectiveDirective;
|
||||
const nsString mOriginalPolicy;
|
||||
const nsString mSourceFile;
|
||||
const nsString mSample;
|
||||
const mozilla::dom::SecurityPolicyViolationEventDisposition mDisposition;
|
||||
const uint16_t mStatusCode;
|
||||
const Nullable<uint32_t> mLineNumber;
|
||||
const Nullable<uint32_t> mColumnNumber;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif // mozilla_dom_CSPViolationReportBody_h
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
EXPORTS.mozilla.dom = [
|
||||
"CrashReport.h",
|
||||
"CSPViolationReportBody.h",
|
||||
"DeprecationReportBody.h",
|
||||
"EndpointForReportChild.h",
|
||||
"EndpointForReportParent.h",
|
||||
|
@ -21,6 +22,7 @@ EXPORTS.mozilla.dom = [
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
"CrashReport.cpp",
|
||||
"CSPViolationReportBody.cpp",
|
||||
"DeprecationReportBody.cpp",
|
||||
"EndpointForReportChild.cpp",
|
||||
"EndpointForReportParent.cpp",
|
||||
|
|
|
@ -44,7 +44,7 @@ function runTests(extraParams = "") {
|
|||
// Check if the report has been received.
|
||||
return checkReport()
|
||||
.then(reports => {
|
||||
is(reports.length, 3, "We have 1 report");
|
||||
ok(reports.length >= 3, "We should have received a minimum of 3 reports");
|
||||
|
||||
let report = reports[0];
|
||||
is(report.contentType, "application/reports+json", "Correct mime-type");
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
// Setting prefs.
|
||||
SpecialPowers.pushPrefEnv({ set: [
|
||||
["dom_reporting_delivering_timeout", 1],
|
||||
["dom_reporting_delivering_maxFailures", 2],
|
||||
["dom.reporting.delivering.timeout", 1],
|
||||
["dom.reporting.delivering.maxFailures", 2],
|
||||
["dom.reporting.delivering.maxReports", 3],
|
||||
]})
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsCSPContext.h"
|
||||
#include "nsCSPParser.h"
|
||||
#include "nsCSPService.h"
|
||||
#include "nsCSPUtils.h"
|
||||
#include "nsGlobalWindowOuter.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
|
@ -45,7 +46,9 @@
|
|||
#include "mozilla/StaticPrefs_security.h"
|
||||
#include "mozilla/dom/CSPReportBinding.h"
|
||||
#include "mozilla/dom/CSPDictionariesBinding.h"
|
||||
#include "mozilla/dom/CSPViolationReportBody.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/dom/ReportingUtils.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
@ -1171,17 +1174,52 @@ nsresult nsCSPContext::SendReports(
|
|||
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;
|
||||
}
|
||||
|
||||
nsAutoString reportGroup;
|
||||
mPolicies[aViolatedPolicyIndex]->getReportGroup(reportGroup);
|
||||
|
||||
// CSP Level 3 Reporting
|
||||
if (!reportGroup.IsEmpty()) {
|
||||
return SendReportsToEndpoints(reportGroup, aViolationEventInit);
|
||||
}
|
||||
|
||||
nsTArray<nsString> reportURIs;
|
||||
mPolicies[aViolatedPolicyIndex]->getReportURIs(reportURIs);
|
||||
|
||||
//[Deprecated] CSP Level 2 Reporting
|
||||
if (!reportURIs.IsEmpty()) {
|
||||
return SendReportsToURIs(reportURIs, aViolationEventInit);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCSPContext::SendReportsToEndpoints(
|
||||
nsAutoString& reportGroup,
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
|
||||
nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsPIDOMWindowInner* window = doc->GetInnerWindow();
|
||||
if (NS_WARN_IF(!window)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<CSPViolationReportBody> body =
|
||||
new CSPViolationReportBody(window->AsGlobal(), aViolationEventInit);
|
||||
|
||||
ReportingUtils::Report(window->AsGlobal(), nsGkAtoms::cspViolation,
|
||||
reportGroup, aViolationEventInit.mDocumentURI, body);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsCSPContext::SendReportsToURIs(
|
||||
const nsTArray<nsString>& reportURIs,
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
|
||||
dom::CSPReport report;
|
||||
|
||||
// blocked-uri
|
||||
|
|
|
@ -100,6 +100,16 @@ class nsCSPContext : public nsIContentSecurityPolicy {
|
|||
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit,
|
||||
uint32_t aViolatedPolicyIndex);
|
||||
|
||||
nsresult SendReportsToEndpoints(
|
||||
nsAutoString& reportGroup,
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit&
|
||||
aViolationEventInit);
|
||||
|
||||
nsresult SendReportsToURIs(
|
||||
const nsTArray<nsString>& reportURIs,
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit&
|
||||
aViolationEventInit);
|
||||
|
||||
nsresult FireViolationEvent(
|
||||
mozilla::dom::Element* aTriggeringElement,
|
||||
nsICSPEventListener* aCSPEventListener,
|
||||
|
|
|
@ -83,6 +83,14 @@ bool isValidHexDig(char16_t aHexDig) {
|
|||
(aHexDig >= 'a' && aHexDig <= 'f'));
|
||||
}
|
||||
|
||||
bool isGroupDelim(char16_t aSymbol) {
|
||||
return (aSymbol == '{' || aSymbol == '}' || aSymbol == ',' ||
|
||||
aSymbol == '/' || aSymbol == ':' || aSymbol == ';' ||
|
||||
aSymbol == '<' || aSymbol == '=' || aSymbol == '>' ||
|
||||
aSymbol == '?' || aSymbol == '@' || aSymbol == '[' ||
|
||||
aSymbol == '\\' || aSymbol == ']' || aSymbol == '"');
|
||||
}
|
||||
|
||||
static bool isValidBase64Value(const char16_t* cur, const char16_t* end) {
|
||||
// Using grammar at
|
||||
// https://w3c.github.io/webappsec-csp/#grammardef-nonce-source
|
||||
|
@ -783,6 +791,44 @@ void nsCSPParser::reportURIList(nsCSPDirective* aDir) {
|
|||
mPolicy->addDirective(aDir);
|
||||
}
|
||||
|
||||
void nsCSPParser::reportGroup(nsCSPDirective* aDir) {
|
||||
CSPPARSERLOG(("nsCSPParser::reportGroup"));
|
||||
|
||||
if (mCurDir.Length() < 2) {
|
||||
AutoTArray<nsString, 1> directiveName = {mCurToken};
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"ignoringDirectiveWithNoValues", directiveName);
|
||||
delete aDir;
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsCSPBaseSrc*> srcs;
|
||||
mCurToken = mCurDir[1];
|
||||
|
||||
CSPPARSERLOG(("nsCSPParser::reportGroup, mCurToken: %s, mCurValue: %s",
|
||||
NS_ConvertUTF16toUTF8(mCurToken).get(),
|
||||
NS_ConvertUTF16toUTF8(mCurValue).get()));
|
||||
|
||||
resetCurChar(mCurToken);
|
||||
while (!atEnd()) {
|
||||
if (isGroupDelim(*mCurChar) ||
|
||||
nsContentUtils::IsHTMLWhitespace(*mCurChar)) {
|
||||
AutoTArray<nsString, 1> params = {mCurToken};
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"invalidGroupSyntax", params);
|
||||
delete aDir;
|
||||
return;
|
||||
}
|
||||
advance();
|
||||
}
|
||||
|
||||
nsCSPGroup* group = new nsCSPGroup(mCurToken);
|
||||
srcs.AppendElement(group);
|
||||
aDir->addSrcs(srcs);
|
||||
mPolicy->addDirective(aDir);
|
||||
aDir = nullptr;
|
||||
};
|
||||
|
||||
/* Helper function for parsing sandbox flags. This function solely concatenates
|
||||
* all the source list tokens (the sandbox flags) so the attribute parser
|
||||
* (nsContentUtils::ParseSandboxAttributeToFlags) can parse them.
|
||||
|
@ -1147,6 +1193,14 @@ void nsCSPParser::directive() {
|
|||
return;
|
||||
}
|
||||
|
||||
// special case handling for report-to directive (since it doesn't contain
|
||||
// a valid source list but rather an endpoint group)
|
||||
if (CSP_IsDirective(mCurDir[0],
|
||||
nsIContentSecurityPolicy::REPORT_TO_DIRECTIVE)) {
|
||||
reportGroup(cspDir);
|
||||
return;
|
||||
}
|
||||
|
||||
// special case handling for sandbox directive (since it doe4sn't contain
|
||||
// a valid source list but rather special sandbox flags)
|
||||
if (CSP_IsDirective(mCurDir[0],
|
||||
|
@ -1380,14 +1434,16 @@ nsCSPPolicy* nsCSPParser::parseContentSecurityPolicy(
|
|||
// Check that report-only policies define a report-uri, otherwise log warning.
|
||||
if (aReportOnly) {
|
||||
policy->setReportOnlyFlag(true);
|
||||
if (!policy->hasDirective(nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE)) {
|
||||
if (!policy->hasDirective(nsIContentSecurityPolicy::REPORT_TO_DIRECTIVE) &&
|
||||
!policy->hasDirective(nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE)) {
|
||||
nsAutoCString prePath;
|
||||
nsresult rv = aSelfURI->GetPrePath(prePath);
|
||||
NS_ENSURE_SUCCESS(rv, policy);
|
||||
AutoTArray<nsString, 1> params;
|
||||
CopyUTF8toUTF16(prePath, *params.AppendElement());
|
||||
parser.logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"reportURInotInReportOnlyHeader", params);
|
||||
"reportURINorReportToNotInReportOnlyHeader",
|
||||
params);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsCSPContext.h"
|
||||
#include "nsIURI.h"
|
||||
#include "PolicyTokenizer.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
bool isNumberToken(char16_t aSymbol);
|
||||
bool isValidHexDig(char16_t aHexDig);
|
||||
|
@ -71,6 +72,7 @@ class nsCSPParser {
|
|||
void directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs);
|
||||
void referrerDirectiveValue(nsCSPDirective* aDir);
|
||||
void reportURIList(nsCSPDirective* aDir);
|
||||
void reportGroup(nsCSPDirective* aDir);
|
||||
void sandboxFlagList(nsCSPDirective* aDir);
|
||||
void handleRequireTrustedTypesForDirective(nsCSPDirective* aDir);
|
||||
void handleTrustedTypesDirective(nsCSPDirective* aDir);
|
||||
|
|
|
@ -999,6 +999,16 @@ void nsCSPReportURI::toString(nsAString& outStr) const {
|
|||
outStr.AppendASCII(spec.get());
|
||||
}
|
||||
|
||||
/* ===== nsCSPReportGroup ===================== */
|
||||
|
||||
nsCSPGroup::nsCSPGroup(const nsAString& aGroup) : mGroup(aGroup) {}
|
||||
|
||||
nsCSPGroup::~nsCSPGroup() = default;
|
||||
|
||||
bool nsCSPGroup::visit(nsCSPSrcVisitor* aVisitor) const { return false; }
|
||||
|
||||
void nsCSPGroup::toString(nsAString& aOutStr) const { aOutStr.Append(mGroup); }
|
||||
|
||||
/* ===== nsCSPSandboxFlags ===================== */
|
||||
|
||||
nsCSPSandboxFlags::nsCSPSandboxFlags(const nsAString& aFlags) : mFlags(aFlags) {
|
||||
|
@ -1519,6 +1529,11 @@ void nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const {
|
|||
outCSP.mTrusted_types.Value() = std::move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::REPORT_TO_DIRECTIVE:
|
||||
outCSP.mReport_to.Construct();
|
||||
outCSP.mReport_to.Value() = std::move(srcs);
|
||||
return;
|
||||
|
||||
default:
|
||||
NS_ASSERTION(false, "cannot find directive to convert CSP to JSON");
|
||||
}
|
||||
|
@ -1537,6 +1552,14 @@ void nsCSPDirective::getReportURIs(nsTArray<nsString>& outReportURIs) const {
|
|||
}
|
||||
}
|
||||
|
||||
void nsCSPDirective::getReportGroup(nsAString& outReportGroup) const {
|
||||
NS_ASSERTION((mDirective == nsIContentSecurityPolicy::REPORT_TO_DIRECTIVE),
|
||||
"not a report-to directive");
|
||||
|
||||
MOZ_ASSERT(mSrcs.Length() <= 1);
|
||||
mSrcs[0]->toString(outReportGroup);
|
||||
}
|
||||
|
||||
bool nsCSPDirective::visitSrcs(nsCSPSrcVisitor* aVisitor) const {
|
||||
for (uint32_t i = 0; i < mSrcs.Length(); i++) {
|
||||
if (!mSrcs[i]->visit(aVisitor)) {
|
||||
|
@ -1887,6 +1910,15 @@ void nsCSPPolicy::getReportURIs(nsTArray<nsString>& outReportURIs) const {
|
|||
}
|
||||
}
|
||||
|
||||
void nsCSPPolicy::getReportGroup(nsAString& outReportGroup) const {
|
||||
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
|
||||
if (mDirectives[i]->equals(nsIContentSecurityPolicy::REPORT_TO_DIRECTIVE)) {
|
||||
mDirectives[i]->getReportGroup(outReportGroup);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool nsCSPPolicy::visitDirectiveSrcs(CSPDirective aDir,
|
||||
nsCSPSrcVisitor* aVisitor) const {
|
||||
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
|
||||
|
|
|
@ -97,6 +97,7 @@ static const char* CSPStrDirectives[] = {
|
|||
"style-src-attr", // STYLE_SRC_ATTR_DIRECTIVE
|
||||
"require-trusted-types-for", // REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE
|
||||
"trusted-types", // TRUSTED_TYPES_DIRECTIVE
|
||||
"report-to", // REPORT_TO_DIRECTIVE
|
||||
};
|
||||
|
||||
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir) {
|
||||
|
@ -377,6 +378,20 @@ class nsCSPReportURI : public nsCSPBaseSrc {
|
|||
nsCOMPtr<nsIURI> mReportURI;
|
||||
};
|
||||
|
||||
/* =============== nsCSPGroup ============ */
|
||||
|
||||
class nsCSPGroup : public nsCSPBaseSrc {
|
||||
public:
|
||||
explicit nsCSPGroup(const nsAString& aGroup);
|
||||
virtual ~nsCSPGroup();
|
||||
|
||||
bool visit(nsCSPSrcVisitor* aVisitor) const override;
|
||||
void toString(nsAString& aOutStr) const override;
|
||||
|
||||
private:
|
||||
nsString mGroup;
|
||||
};
|
||||
|
||||
/* =============== nsCSPSandboxFlags ================== */
|
||||
|
||||
class nsCSPSandboxFlags : public nsCSPBaseSrc {
|
||||
|
@ -478,6 +493,8 @@ class nsCSPDirective {
|
|||
|
||||
void getReportURIs(nsTArray<nsString>& outReportURIs) const;
|
||||
|
||||
void getReportGroup(nsAString& outReportGroup) const;
|
||||
|
||||
bool visitSrcs(nsCSPSrcVisitor* aVisitor) const;
|
||||
|
||||
virtual void getDirName(nsAString& outStr) const;
|
||||
|
@ -698,6 +715,8 @@ class nsCSPPolicy {
|
|||
|
||||
void getReportURIs(nsTArray<nsString>& outReportURIs) const;
|
||||
|
||||
void getReportGroup(nsAString& outReportGroup) const;
|
||||
|
||||
void getViolatedDirectiveInformation(CSPDirective aDirective,
|
||||
nsAString& aDirectiveName,
|
||||
nsAString& aDirectiveNameAndValue,
|
||||
|
|
|
@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=847081
|
|||
var stringBundleService = SpecialPowers.Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(SpecialPowers.Ci.nsIStringBundleService);
|
||||
var localizer = stringBundleService.createBundle("chrome://global/locale/security/csp.properties");
|
||||
var warningMsg = localizer.formatStringFromName("reportURInotInReportOnlyHeader", [window.location.origin]);
|
||||
var warningMsg = localizer.formatStringFromName("reportURINorReportToNotInReportOnlyHeader", [window.location.origin]);
|
||||
|
||||
function cleanup() {
|
||||
SpecialPowers.postConsoleSentinel();
|
||||
|
@ -28,7 +28,7 @@ function cleanup() {
|
|||
}
|
||||
|
||||
// Since Bug 1584993 we parse the CSP in the parent too, hence the
|
||||
// same error message appears twice in the console.
|
||||
// same error message appears twice in the console.
|
||||
var recordConsoleMsgOnce = false;
|
||||
|
||||
SpecialPowers.registerConsoleListener(function ConsoleMsgListener(aMsg) {
|
||||
|
|
|
@ -34,6 +34,7 @@ dictionary CSP {
|
|||
sequence<DOMString> script-src-attr;
|
||||
sequence<DOMString> require-trusted-types-for;
|
||||
sequence<DOMString> trusted-types;
|
||||
sequence<DOMString> report-to;
|
||||
};
|
||||
|
||||
[GenerateToJSON]
|
||||
|
|
|
@ -70,6 +70,22 @@ interface TestingDeprecatedInterface {
|
|||
readonly attribute boolean deprecatedAttribute;
|
||||
};
|
||||
|
||||
[Exposed=Window, Pref="dom.reporting.enabled"]
|
||||
interface CSPViolationReportBody : ReportBody {
|
||||
[Default] object toJSON();
|
||||
readonly attribute USVString documentURL;
|
||||
readonly attribute USVString? referrer;
|
||||
readonly attribute USVString? blockedURL;
|
||||
readonly attribute DOMString effectiveDirective;
|
||||
readonly attribute DOMString originalPolicy;
|
||||
readonly attribute USVString? sourceFile;
|
||||
readonly attribute DOMString? sample;
|
||||
readonly attribute SecurityPolicyViolationEventDisposition disposition;
|
||||
readonly attribute unsigned short statusCode;
|
||||
readonly attribute unsigned long? lineNumber;
|
||||
readonly attribute unsigned long? columnNumber;
|
||||
};
|
||||
|
||||
// Used internally to process the JSON
|
||||
[GenerateInit]
|
||||
dictionary ReportingHeaderValue {
|
||||
|
|
|
@ -1,56 +1,3 @@
|
|||
[idlharness.window.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[CSPViolationReportBody interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute sample]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute effectiveDirective]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute disposition]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute lineNumber]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute blockedURL]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute sourceFile]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute documentURL]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute referrer]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute statusCode]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute originalPolicy]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: attribute columnNumber]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
|
||||
[CSPViolationReportBody interface: operation toJSON()]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1631237
|
||||
implementation-status: backlog
|
||||
prefs: [dom.reporting.enabled:true]
|
||||
prefs: [dom.reporting.enabled:true,
|
||||
dom.reporting.header.enabled:true,
|
||||
dom.reporting.delivering.timeout:0]
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[cross-origin-report-no-credentials.https.sub.html]
|
||||
[Reporting endpoints did not receive credentials.]
|
||||
expected: FAIL
|
|
@ -1,5 +1,3 @@
|
|||
[cross-origin-same-site-credentials.https.sub.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Reporting endpoints received credentials.]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
[document-reporting-named-endpoints.https.sub.html]
|
||||
expected: TIMEOUT
|
||||
[csp violation report observed]
|
||||
expected: TIMEOUT
|
||||
|
||||
[document policy violation observed]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
[Buffer filled]
|
||||
expected: FAIL
|
||||
|
||||
[CSP Report limits were honored]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Test Report limits were honored]
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -7,4 +7,3 @@
|
|||
expected:
|
||||
if os == "win": FAIL
|
||||
if os == "linux": [FAIL, TIMEOUT]
|
||||
[TIMEOUT, FAIL]
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
[same-origin-report-credentials.https.sub.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Reporting endpoints received credentials.]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[same-origin-same-site-credentials.https.sub.html]
|
||||
[Reporting endpoints received credentials.]
|
||||
expected: FAIL
|
|
@ -1705,6 +1705,7 @@ STATIC_ATOMS = [
|
|||
Atom("cs_", "cs"),
|
||||
Atom("csymbol_", "csymbol"),
|
||||
Atom("csp", "csp"),
|
||||
Atom("cspViolation", "csp-violation"),
|
||||
Atom("curl_", "curl"),
|
||||
Atom("decimalpoint_", "decimalpoint"),
|
||||
Atom("definition", "definition"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче