From 6fe326c7bb74c39a713b8d33f7462e2b5fe3ffb6 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 30 Oct 2024 09:06:43 +0100 Subject: [PATCH] Issue #2648 - Apply CSP to documents sent through multipart/x-mixed-replace --- .../converters/nsMultiMixedConv.cpp | 29 +++++++++++++++++++ .../streamconv/converters/nsMultiMixedConv.h | 4 ++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.cpp b/netwerk/streamconv/converters/nsMultiMixedConv.cpp index 44a0dfd705..af21747ce6 100644 --- a/netwerk/streamconv/converters/nsMultiMixedConv.cpp +++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp @@ -644,6 +644,7 @@ nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context, mContentType.Truncate(); mContentLength = UINT64_MAX; mContentDisposition.Truncate(); + mContentSecurityPolicy.Truncate(); mIsByteRangeRequest = false; mByteRangeStart = 0; mByteRangeEnd = 0; @@ -715,6 +716,12 @@ nsMultiMixedConv::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { if (NS_FAILED(rv)) { return rv; } + nsCString csp; + rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-security-policy"), + csp); + if (NS_SUCCEEDED(rv)) { + mRootContentSecurityPolicy = csp; + } } else { // try asking the channel directly rv = channel->GetContentType(delimiter); @@ -1062,6 +1069,28 @@ nsMultiMixedConv::ParseHeaders(nsIChannel *aChannel, char *&aPtr, mIsByteRangeRequest = true; if (mContentLength == UINT64_MAX) mContentLength = uint64_t(mByteRangeEnd - mByteRangeStart + 1); + } else if (headerStr.LowerCaseEqualsLiteral("content-security-policy")) { + mContentSecurityPolicy = headerVal; + nsCOMPtr httpChannel = do_QueryInterface(aChannel); + if (httpChannel) { + nsCString resultCSP = mRootContentSecurityPolicy; + if (!mContentSecurityPolicy.IsEmpty()) { + // We are updating the root channel CSP header respectively for + // each part as: CSP-root + CSP-partN, where N is the part number. + // Here we append current part's CSP to root CSP and reset CSP + // header for each part. + if (!resultCSP.IsEmpty()) { + resultCSP.Append(";"); + } + resultCSP.Append(mContentSecurityPolicy); + } + nsresult rv = httpChannel->SetResponseHeader( + NS_LITERAL_CSTRING("Content-Security-Policy"), + resultCSP, false); + if (NS_FAILED(rv)) { + return NS_ERROR_CORRUPTED_CONTENT; + } + } } } *newLine = tmpChar; diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.h b/netwerk/streamconv/converters/nsMultiMixedConv.h index fa058b0720..c96cb55b88 100644 --- a/netwerk/streamconv/converters/nsMultiMixedConv.h +++ b/netwerk/streamconv/converters/nsMultiMixedConv.h @@ -96,7 +96,7 @@ protected: // main stream and sending them off the destination stream listener, than doing any real // stream parsing/converting. // -// WARNING: This converter requires that it's destination stream listener be able to handle +// WARNING: This converter requires that its destination stream listener be able to handle // multiple OnStartRequest(), OnDataAvailable(), and OnStopRequest() call combinations. // Each series represents the beginning, data production, and ending phase of each sub- // part of the original stream. @@ -156,6 +156,8 @@ protected: nsCOMPtr mContext; nsCString mContentType; nsCString mContentDisposition; + nsCString mContentSecurityPolicy; + nsCString mRootContentSecurityPolicy; uint64_t mContentLength; char *mBuffer;