/* -*- 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/. */
#ifdef DEBUG /** * This function is only used for verification purposes within * GatherSecurityPolicyViolationEventData.
*/ staticbool ValidateDirectiveName(const nsAString& aDirective) { staticconstauto directives = []() {
std::unordered_set<std::string> directives;
constexpr size_t dirLen = sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0]); for (size_t i = 0; i < dirLen; ++i) {
directives.insert(CSPStrDirectives[i]);
} return directives;
}();
case CSPViolationData::BlockedContentSource::Inline:
aString.AssignLiteral("inline"); break;
case CSPViolationData::BlockedContentSource::Eval:
aString.AssignLiteral("eval"); break;
case CSPViolationData::BlockedContentSource::Self:
aString.AssignLiteral("self"); break;
case CSPViolationData::BlockedContentSource::WasmEval:
aString.AssignLiteral("wasm-eval"); break; case CSPViolationData::BlockedContentSource::TrustedTypesPolicy:
aString.AssignLiteral("trusted-types-policy"); break; case CSPViolationData::BlockedContentSource::TrustedTypesSink:
aString.AssignLiteral("trusted-types-sink"); break;
}
}
// This ShouldLoad function is called from nsCSPService::ShouldLoad, // which already checked a number of things, including: // * aContentLocation is not null; we can consume this without further checks // * scheme is not a allowlisted scheme (about: chrome:, etc). // * CSP is enabled // * Content Type is not allowlisted (CSP Reports, TYPE_DOCUMENT, etc). // * Fast Path for Apps
// Default decision, CSP can revise it if there's a policy to enforce
*outDecision = nsIContentPolicy::ACCEPT;
// If the content type doesn't map to a CSP directive, there's nothing for // CSP to do.
CSPDirective dir = CSP_ContentTypeToDirective(aContentType); if (dir == nsIContentSecurityPolicy::NO_DIRECTIVE) { return NS_OK;
}
bool permitted = permitsInternal(
dir,
nullptr, // aTriggeringElement
aCSPEventListener, aLoadInfo, aContentLocation, aOriginalURIIfRedirect, false, // allow fallback to default-src
aSendViolationReports, true); // send blocked URI in violation reports
nsAutoString violatedDirective;
nsAutoString violatedDirectiveString; for (uint32_t p = 0; p < mPolicies.Length(); p++) { if (!mPolicies[p]->permits(aDir, aLoadInfo, aContentLocation,
!!aOriginalURIIfRedirect, aSpecific,
violatedDirective, violatedDirectiveString)) { // If the policy is violated and not report-only, reject the load and // report to the console if (!mPolicies[p]->getReportOnlyFlag()) {
CSPCONTEXTLOG(("nsCSPContext::permitsInternal, false"));
permits = false;
}
// Callers should set |aSendViolationReports| to false if this is a // preload - the decision may be wrong due to the inability to get the // nonce, and will incorrectly fail the unit tests. if (aSendViolationReports) { auto loc = JSCallingLocation::Get();
AsyncReportViolation(
aCSPEventListener, std::move(cspViolationData),
aOriginalURIIfRedirect, /* in case of redirect originalURI is not
null */
violatedDirective, violatedDirectiveString,
u""_ns, // no observer subject false); // aReportSample (no sample)
}
}
}
NS_IMETHODIMP
nsCSPContext::EnsureIPCPoliciesRead() { // Most likely the parser errors already happened before serializing // the policy for IPC. bool previous = mSuppressParserLogMessages;
mSuppressParserLogMessages = true;
// Use mSelfURI from setRequestContextWith{Document,Principal} (bug 991474)
MOZ_ASSERT(
mLoadingPrincipal, "did you forget to call setRequestContextWith{Document,Principal}?");
MOZ_ASSERT(
mSelfURI, "did you forget to call setRequestContextWith{Document,Principal}?");
NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_UNEXPECTED);
NS_ENSURE_TRUE(mSelfURI, NS_ERROR_UNEXPECTED);
for (uint32_t i = 0; i < mPolicies.Length(); i++) { if (!mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE, CSP_UNSAFE_EVAL, u""_ns)) { // policy is violated: must report the violation and allow the inline // script if the policy is report-only.
*outShouldReportViolation = true; if (!mPolicies[i]->getReportOnlyFlag()) {
*outAllowsEval = false;
}
}
} return NS_OK;
}
for (uint32_t i = 0; i < mPolicies.Length(); i++) { // Either 'unsafe-eval' or 'wasm-unsafe-eval' can allow this if (!mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE, CSP_WASM_UNSAFE_EVAL,
u""_ns) &&
!mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE, CSP_UNSAFE_EVAL, u""_ns)) { // policy is violated: must report the violation and allow the inline // script if the policy is report-only.
*outShouldReportViolation = true; if (!mPolicies[i]->getReportOnlyFlag()) {
*outAllowsWasmEval = false;
}
}
}
return NS_OK;
}
// Helper function to report inline violations void nsCSPContext::reportInlineViolation(
CSPDirective aDirective, Element* aTriggeringElement,
nsICSPEventListener* aCSPEventListener, const nsAString& aNonce, bool aReportSample, const nsAString& aSample, const nsAString& aViolatedDirective, const nsAString& aViolatedDirectiveString, CSPDirective aEffectiveDirective,
uint32_t aViolatedPolicyIndex, // TODO, use report only flag for that
uint32_t aLineNumber, uint32_t aColumnNumber) {
nsString observerSubject; // if the nonce is non empty, then we report the nonce error, otherwise // let's report the hash error; no need to report the unsafe-inline error // anymore. if (!aNonce.IsEmpty()) {
observerSubject = (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
aDirective == SCRIPT_SRC_ATTR_DIRECTIVE)
? NS_LITERAL_STRING_FROM_CSTRING(
SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC)
: NS_LITERAL_STRING_FROM_CSTRING(
STYLE_NONCE_VIOLATION_OBSERVER_TOPIC);
} else {
observerSubject = (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
aDirective == SCRIPT_SRC_ATTR_DIRECTIVE)
? NS_LITERAL_STRING_FROM_CSTRING(
SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC)
: NS_LITERAL_STRING_FROM_CSTRING(
STYLE_HASH_VIOLATION_OBSERVER_TOPIC);
}
auto loc = JSCallingLocation::Get(); if (!loc) {
nsCString sourceFile; // use selfURI as the source if (mSelfURI) {
mSelfURI->GetSpec(sourceFile);
loc.mResource = AsVariant(std::move(sourceFile));
}
loc.mLine = aLineNumber;
loc.mColumn = aColumnNumber;
}
// Step 1. If §6.7.3.2 Does a source list allow all inline behavior for // type? returns "Allows" given list and type, return "Matches". if (mPolicies[i]->allowsAllInlineBehavior(aDirective)) { continue;
}
// Step 2. If type is "script" or "style", and §6.7.3.1 Is element // nonceable? returns "Nonceable" when executed upon element: if ((aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
aDirective == STYLE_SRC_ELEM_DIRECTIVE) &&
aTriggeringElement && !aNonce.IsEmpty()) { #ifdef DEBUG // NOTE: Folllowing Chrome "Is element nonceable?" doesn't apply to // <style>. if (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE) { // Our callers should have checked this.
MOZ_ASSERT(nsContentSecurityUtils::GetIsElementNonceableNonce(
*aTriggeringElement) == aNonce);
} #endif
// Step 2.1. For each expression of list: [...] if (mPolicies[i]->allows(aDirective, CSP_NONCE, aNonce)) { continue;
}
}
// Check the content length to ensure the content is not allocated more than // once. Even though we are in a for loop, it is probable that there is only // one policy, so this check may be unnecessary. if (content.IsEmpty() && aTriggeringElement) {
nsCOMPtr<nsIScriptElement> element =
do_QueryInterface(aTriggeringElement); if (element) {
element->GetScriptText(content);
}
} if (content.IsEmpty()) {
content = aContentOfPseudoScript;
}
// Step 3. Let unsafe-hashes flag be false. // Step 4. For each expression of list: [...] bool unsafeHashesFlag =
mPolicies[i]->allows(aDirective, CSP_UNSAFE_HASHES, u""_ns);
// Step 5. If type is "script" or "style", or unsafe-hashes flag is true: // // aHasUnsafeHash is true for event handlers (type "script attribute"), // style= attributes (type "style attribute") and the javascript: protocol. if (!aHasUnsafeHash || unsafeHashesFlag) { if (mPolicies[i]->allows(aDirective, CSP_HASH, content)) { continue;
}
}
// TODO(Bug 1844290): Figure out how/if strict-dynamic for inline scripts is // specified bool allowed = false; if ((aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
aDirective == SCRIPT_SRC_ATTR_DIRECTIVE) &&
mPolicies[i]->allows(aDirective, CSP_STRICT_DYNAMIC, u""_ns)) {
allowed = !aParserCreated;
}
if (!allowed) { // policy is violoated: deny the load unless policy is report only and // report the violation. if (!mPolicies[i]->getReportOnlyFlag()) {
*outAllowsInline = false;
}
nsAutoString violatedDirective;
nsAutoString violatedDirectiveString; bool reportSample = false;
mPolicies[i]->getViolatedDirectiveInformation(
aDirective, violatedDirective, violatedDirectiveString,
&reportSample);
/** * For each policy, log any violation on the Error Console and send a report * if a report-uri is present in the policy * * @param aViolationType * one of the VIOLATION_TYPE_* constants, e.g. inline-script or eval * @param aSourceFile * name of the source file containing the violation (if available) * @param aContentSample * sample of the violating content (to aid debugging) * @param aLineNum * source line number of the violation (if available) * @param aColumnNum * source column number of the violation (if available) * @param aNonce * (optional) If this is a nonce violation, include the nonce so we can * recheck to determine which policies were violated and send the * appropriate reports. * @param aContent * (optional) If this is a hash violation, include contents of the inline * resource in the question so we can recheck the hash in order to * determine which policies were violated and send the appropriate * reports.
*/
NS_IMETHODIMP
nsCSPContext::LogViolationDetails(
uint16_t aViolationType, Element* aTriggeringElement,
nsICSPEventListener* aCSPEventListener, const nsACString& aSourceFile, const nsAString& aScriptSample, int32_t aLineNum, int32_t aColumnNum, const nsAString& aNonce, const nsAString& aContent) {
EnsureIPCPoliciesRead();
NS_IMETHODIMP
nsCSPContext::SetRequestContextWithDocument(Document* aDocument) {
MOZ_ASSERT(aDocument, "Can't set context without doc");
NS_ENSURE_ARG(aDocument);
mLoadingContext = do_GetWeakReference(aDocument);
mSelfURI = aDocument->GetDocumentURI();
mLoadingPrincipal = aDocument->NodePrincipal();
aDocument->GetReferrer(mReferrer);
mInnerWindowID = aDocument->InnerWindowID(); // the innerWindowID is not available for CSPs delivered through the // header at the time setReqeustContext is called - let's queue up // console messages until it becomes available, see flushConsoleMessages
mQueueUpMessages = !mInnerWindowID;
mCallingChannelLoadGroup = aDocument->GetDocumentLoadGroup(); // set the flag on the document for CSP telemetry
mEventTarget = GetMainThreadSerialEventTarget();
MOZ_ASSERT(mLoadingPrincipal, "need a valid requestPrincipal");
MOZ_ASSERT(mSelfURI, "need mSelfURI to translate 'self' into actual URI"); return NS_OK;
}
mLoadingPrincipal = aRequestPrincipal;
mSelfURI = aSelfURI;
mReferrer = aReferrer;
mInnerWindowID = aInnerWindowId; // if no document is available, then it also does not make sense to queue // console messages sending messages to the browser console instead of the web // console in that case.
mQueueUpMessages = false;
mCallingChannelLoadGroup = nullptr;
mEventTarget = nullptr;
MOZ_ASSERT(mLoadingPrincipal, "need a valid requestPrincipal");
MOZ_ASSERT(mSelfURI, "need mSelfURI to translate 'self' into actual URI"); return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::EnsureEventTarget(nsIEventTarget* aEventTarget) {
NS_ENSURE_ARG(aEventTarget); // Don't bother if we did have a valid event target (if the csp object is // tied to a document in SetRequestContextWithDocument) if (mEventTarget) { return NS_OK;
}
// should flush messages even if doc is not available
nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext); if (doc) {
mInnerWindowID = doc->InnerWindowID();
privateWindow =
doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
}
mQueueUpMessages = false;
for (uint32_t i = 0; i < mConsoleMsgQueue.Length(); i++) {
ConsoleMsgQueueElem& elem = mConsoleMsgQueue[i];
CSP_LogMessage(elem.mMsg, elem.mSourceName, elem.mSourceLine,
elem.mLineNumber, elem.mColumnNumber, elem.mSeverityFlag,
elem.mCategory, mInnerWindowID, privateWindow);
}
mConsoleMsgQueue.Clear();
}
void nsCSPContext::logToConsole(constchar* aName, const nsTArray<nsString>& aParams, const nsACString& aSourceName, const nsAString& aSourceLine,
uint32_t aLineNumber, uint32_t aColumnNumber,
uint32_t aSeverityFlag) { // we are passing aName as the category so we can link to the // appropriate MDN docs depending on the specific error.
nsDependentCString category(aName);
/** * Strip URI for reporting according to: * https://w3c.github.io/webappsec-csp/#security-violation-reports * * @param aSelfURI * The URI of the CSP policy. Used for cross-origin checks. * @param aURI * The URI of the blocked resource. In case of a redirect, this it the * initial URI the request started out with, not the redirected URI. * @param aEffectiveDirective * The effective directive that triggered this report * @return The ASCII serialization of the uri to be reported ignoring * the ref part of the URI.
*/ void StripURIForReporting(nsIURI* aSelfURI, nsIURI* aURI, const nsAString& aEffectiveDirective,
nsACString& outStrippedURI) { if (aSelfURI->SchemeIs("chrome")) {
aURI->GetSpecIgnoringRef(outStrippedURI); return;
}
// If the origin of aURI is a globally unique identifier (for example, // aURI has a scheme of data, blob, or filesystem), then // return the ASCII serialization of uri’s scheme. bool isHttpOrWs = (aURI->SchemeIs("http") || aURI->SchemeIs("https") ||
aURI->SchemeIs("ws") || aURI->SchemeIs("wss"));
if (!isHttpOrWs) { // not strictly spec compliant, but what we really care about is // http/https. If it's not http/https, then treat aURI // as if it's a globally unique identifier and just return the scheme.
aURI->GetScheme(outStrippedURI); return;
}
// For cross-origin URIs in frame-src also strip the path. // This prevents detailed tracking of pages loaded into an iframe // by the embedding page using a report-only policy. if (aEffectiveDirective.EqualsLiteral("frame-src") ||
aEffectiveDirective.EqualsLiteral("object-src")) {
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); if (NS_FAILED(ssm->CheckSameOriginURI(aSelfURI, aURI, false, false))) {
aURI->GetPrePath(outStrippedURI); return;
}
}
// Return aURI, with any fragment component removed.
aURI->GetSpecIgnoringRef(outStrippedURI);
}
// effective-directive // The name of the policy directive that was violated.
aViolationEventInit.mEffectiveDirective = aEffectiveDirective;
// violated-directive // In CSP2, the policy directive that was violated, as it appears in the // policy. In CSP3, the same as effective-directive.
aViolationEventInit.mViolatedDirective = aEffectiveDirective;
// source-file if (!aCSPViolationData.mSourceFile.IsEmpty()) { // if aSourceFile is a URI, we have to make sure to strip fragments
nsCOMPtr<nsIURI> sourceURI;
NS_NewURI(getter_AddRefs(sourceURI), aCSPViolationData.mSourceFile); if (sourceURI) {
nsAutoCString stripped;
StripURIForReporting(mSelfURI, sourceURI, aEffectiveDirective, stripped);
CopyUTF8toUTF16(stripped, aViolationEventInit.mSourceFile);
} else {
CopyUTF8toUTF16(aCSPViolationData.mSourceFile,
aViolationEventInit.mSourceFile);
}
}
// Disable throttling if either of the preferences is set to 0. if (kLimitCount == 0 || kTimeSpanSeconds == 0) { returnfalse;
}
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; returnfalse;
}
if (mSendReportLimitCount < kLimitCount) {
mSendReportLimitCount++; returnfalse;
}
if (aViolationEventInit.mColumnNumber != 0) {
report.mCsp_report.mColumn_number.Construct();
report.mCsp_report.mColumn_number.Value() =
aViolationEventInit.mColumnNumber;
}
nsString csp_report; if (!report.ToJSON(csp_report)) { return NS_ERROR_FAILURE;
}
// ---------- Assembled, now send it to all the report URIs ----------- //
nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
nsCOMPtr<nsIURI> reportURI;
nsCOMPtr<nsIChannel> reportChannel;
nsresult rv; for (uint32_t r = 0; r < reportURIs.Length(); r++) {
nsAutoCString reportURICstring = NS_ConvertUTF16toUTF8(reportURIs[r]); // try to create a new uri from every report-uri string
rv = NS_NewURI(getter_AddRefs(reportURI), reportURIs[r]); if (NS_FAILED(rv)) {
AutoTArray<nsString, 1> params = {reportURIs[r]};
CSPCONTEXTLOG(("Could not create nsIURI for report URI %s",
reportURICstring.get()));
logToConsole("triedToSendReport", params,
NS_ConvertUTF16toUTF8(aViolationEventInit.mSourceFile),
aViolationEventInit.mSample, aViolationEventInit.mLineNumber,
aViolationEventInit.mColumnNumber,
nsIScriptError::errorFlag); continue; // don't return yet, there may be more URIs
}
// try to create a new channel for every report-uri if (doc) {
rv =
NS_NewChannel(getter_AddRefs(reportChannel), reportURI, doc,
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
nsIContentPolicy::TYPE_CSP_REPORT);
} else {
rv = NS_NewChannel(
getter_AddRefs(reportChannel), reportURI, mLoadingPrincipal,
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
nsIContentPolicy::TYPE_CSP_REPORT);
}
if (NS_FAILED(rv)) {
CSPCONTEXTLOG(("Could not create new channel for report URI %s",
reportURICstring.get())); continue; // don't return yet, there may be more URIs
}
// log a warning to console if scheme is not http or https bool isHttpScheme =
reportURI->SchemeIs("http") || reportURI->SchemeIs("https");
// make sure this is an anonymous request (no cookies) so in case the // policy URI is injected, it can't be abused for CSRF.
nsLoadFlags flags;
rv = reportChannel->GetLoadFlags(&flags);
NS_ENSURE_SUCCESS(rv, rv);
flags |= nsIRequest::LOAD_ANONYMOUS;
flags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
rv = reportChannel->SetLoadFlags(flags);
NS_ENSURE_SUCCESS(rv, rv);
// we need to set an nsIChannelEventSink on the channel object // so we can tell it to not follow redirects when posting the reports
RefPtr<CSPReportRedirectSink> reportSink = new CSPReportRedirectSink(); if (doc && doc->GetDocShell()) {
nsCOMPtr<nsINetworkInterceptController> interceptController =
do_QueryInterface(doc->GetDocShell());
reportSink->SetInterceptController(interceptController);
}
reportChannel->SetNotificationCallbacks(reportSink);
// apply the loadgroup taken by setRequestContextWithDocument. If there's // no loadgroup, AsyncOpen will fail on process-split necko (since the // channel cannot query the iBrowserChild).
rv = reportChannel->SetLoadGroup(mCallingChannelLoadGroup);
NS_ENSURE_SUCCESS(rv, rv);
// wire in the string input stream to send the report
nsCOMPtr<nsIStringInputStream> sis(
do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID));
NS_ASSERTION(sis, "nsIStringInputStream is needed but not available to send CSP " "violation reports");
rv = sis->SetUTF8Data(NS_ConvertUTF16toUTF8(csp_report));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(reportChannel)); if (!uploadChannel) { // It's possible the URI provided can't be uploaded to, in which case // we skip this one. We'll already have warned about a non-HTTP URI // earlier. continue;
}
// if this is an HTTP channel, set the request method to post
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(reportChannel)); if (httpChannel) {
rv = httpChannel->SetRequestMethod("POST"_ns);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
RefPtr<CSPViolationReportListener> listener = new CSPViolationReportListener();
rv = reportChannel->AsyncOpen(listener);
// AsyncOpen should not fail, but could if there's no load group (like if // SetRequestContextWith{Document,Principal} is not given a channel). This // should fail quietly and not return an error since it's really ok if // reports don't go out, but it's good to log the error locally.
if (NS_FAILED(rv)) {
AutoTArray<nsString, 1> params = {reportURIs[r]};
CSPCONTEXTLOG(("AsyncOpen failed for report URI %s",
NS_ConvertUTF16toUTF8(params[0]).get()));
logToConsole("triedToSendReport", params,
NS_ConvertUTF16toUTF8(aViolationEventInit.mSourceFile),
aViolationEventInit.mSample, aViolationEventInit.mLineNumber,
aViolationEventInit.mColumnNumber,
nsIScriptError::errorFlag);
} else {
CSPCONTEXTLOG(
("Sent violation report to URI %s", reportURICstring.get()));
}
} return NS_OK;
}
// Don't collect samples for code that is probably not shipped by us. if (source.first.EqualsLiteral("chromeuri") ||
source.first.EqualsLiteral("resourceuri") ||
source.first.EqualsLiteral("abouturi")) { // aInit's sample requires the 'report-sample' keyword.
extra.sample = Some(NS_ConvertUTF16toUTF8(aCSPViolationData.mSample));
}
nsresult nsCSPContext::FireViolationEvent(
Element* aTriggeringElement, nsICSPEventListener* aCSPEventListener, const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) { if (aCSPEventListener) {
nsAutoString json; if (aViolationEventInit.ToJSON(json)) {
aCSPEventListener->OnCSPViolationEvent(json);
}
return NS_OK;
}
// 1. If target is not null, and global is a Window, and target’s // shadow-including root is not global’s associated Document, set target to // null.
RefPtr<EventTarget> eventTarget = aTriggeringElement;
if (!eventTarget) { // If target is a Window, set target to target’s associated Document.
eventTarget = doc;
}
if (!eventTarget && mInnerWindowID && XRE_IsParentProcess()) { if (RefPtr<WindowGlobalParent> parent =
WindowGlobalParent::GetByInnerWindowId(mInnerWindowID)) {
nsAutoString json; if (aViolationEventInit.ToJSON(json)) {
Unused << parent->SendDispatchSecurityPolicyViolation(json);
}
} return NS_OK;
}
if (!eventTarget) { // If we are here, we are probably dealing with workers. Those are handled // via nsICSPEventListener. Nothing to do here. return NS_OK;
}
/** * Dispatched from the main thread to send reports for one CSP violation.
*/ class CSPReportSenderRunnable final : public Runnable { public:
CSPReportSenderRunnable(nsICSPEventListener* aCSPEventListener,
CSPViolationData&& aCSPViolationData,
nsIURI* aOriginalURI, bool aReportOnlyFlag, const nsAString& aViolatedDirectiveName, const nsAString& aViolatedDirectiveNameAndValue, const nsAString& aObserverSubject, bool aReportSample,
nsCSPContext* aCSPContext)
: mozilla::Runnable("CSPReportSenderRunnable"),
mCSPEventListener(aCSPEventListener),
mCSPViolationData(std::move(aCSPViolationData)),
mOriginalURI(aOriginalURI),
mReportOnlyFlag(aReportOnlyFlag),
mReportSample(aReportSample),
mViolatedDirectiveName(aViolatedDirectiveName),
mViolatedDirectiveNameAndValue(aViolatedDirectiveNameAndValue),
mCSPContext(aCSPContext) {
NS_ASSERTION(!aViolatedDirectiveName.IsEmpty(), "Can not send reports without a violated directive"); // the observer subject is an nsISupports: either an nsISupportsCString // from the arg passed in directly, or if that's empty, it's the blocked // source. if (aObserverSubject.IsEmpty() &&
mCSPViolationData.mResource.is<nsCOMPtr<nsIURI>>()) {
mObserverSubject = mCSPViolationData.mResource.as<nsCOMPtr<nsIURI>>(); return;
}
// 2) send reports for the policy that was violated
mCSPContext->SendReports(init, mCSPViolationData.mViolatedPolicyIndex);
// 3) log to console (one per policy violation)
ReportToConsole();
// 4) For internal pages we might send the failure to telemetry.
mCSPContext->RecordInternalViolationTelemetry(mCSPViolationData, init);
// 5) fire violation event // A frame-ancestors violation has occurred, but we should not dispatch // the violation event to a potentially cross-origin ancestor. if (!mViolatedDirectiveName.EqualsLiteral("frame-ancestors")) {
mCSPContext->FireViolationEvent(mCSPViolationData.mElement,
mCSPEventListener, init);
}
case CSPViolationData::BlockedContentSource::Self: case CSPViolationData::BlockedContentSource::Unknown: {
nsAutoString source(u""_ns); if (mCSPViolationData.mResource.is<nsCOMPtr<nsIURI>>()) {
nsAutoCString uri; auto blockedURI = mCSPViolationData.mResource.as<nsCOMPtr<nsIURI>>();
blockedURI->GetSpec(uri);
/** * Based on the given loadinfo, determines if this CSP context allows the * ancestry. * * In order to determine the URI of the parent document (one causing the load * of this protected document), this function traverses all Browsing Contexts
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.36 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.