Bug 1594766: Respect Nosniff header for empty content-types r=ckerschb

Backed out changeset 35436d4e7917

Differential Revision: https://phabricator.services.mozilla.com/D60156

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Sebastian Streich 2020-02-12 16:20:46 +00:00
Родитель 0c4f11b187
Коммит ac5daf49e7
5 изменённых файлов: 71 добавлений и 29 удалений

Просмотреть файл

@ -54,32 +54,16 @@
*
*/
/*
What the Sniffer Should sniff, given a querystring for file_nosniff_navigation.sjs
*/
const EXPECTED_MIMES={
"xml": "text/xml",
"html": "text/html",
"img": "image/png",
"css": "text/plain",
"js": "text/plain",
"json": "text/plain",
"": "text/plain"
}
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", ()=>{
let noMimeFrames = Array.from(document.querySelectorAll(".no-mime"));
noMimeFrames.forEach( frame => {
// In case of no Provided Content Type + XTCO set, we still should do sniffing
let sniffedMimeType = frame.contentWindow.document.contentType;
let contentTypeQuery = (new URL(frame.src)).search.substr(1);
let expectedMime = EXPECTED_MIMES[contentTypeQuery];
let result = expectedMime == sniffedMimeType;
window.opener.ok(result, `${contentTypeQuery} without MIME send -> was Sniffed: ${frame.contentWindow.document.contentType}`);
// In case of no Provided Content Type, not rendering or assuming text/plain is valid
let result = frame.contentWindow.document.URL == "about:blank" || frame.contentWindow.document.contentType == "text/plain";
let sniffTarget = (new URL(frame.src)).search;
window.opener.ok(result, `${sniffTarget} without MIME - was not Sniffed`);
});
let mismatchedMimes = Array.from(document.querySelectorAll(".mismatch-mime"));
@ -87,7 +71,7 @@ window.addEventListener("load", ()=>{
// In case the Server mismatches the Mime Type (sends content X as image/png)
// assert that we do not sniff and correct this.
let result = frame.contentWindow.document.contentType == "image/png";
let sniffTarget = (new URL(frame.src)).search.substr(1);
let sniffTarget = (new URL(frame.src)).search;
window.opener.ok(result, `${sniffTarget} send as image/png - was not Sniffed`);
});
@ -98,7 +82,7 @@ window.addEventListener("load", ()=>{
// We must not default here to text/plain
// as the Server at least provided a mime type.
let result = frame.contentWindow.document.URL == "about:blank";
let sniffTarget = (new URL(frame.src)).search.substr(1);;
let sniffTarget = (new URL(frame.src)).search;
window.opener.ok(result, `${sniffTarget} send as garbage/garbage - was not Sniffed`);
});

Просмотреть файл

@ -2580,6 +2580,13 @@ NS_IMETHODIMP
imgLoader::GetMIMETypeFromContent(nsIRequest* aRequest,
const uint8_t* aContents, uint32_t aLength,
nsACString& aContentType) {
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (channel) {
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
if (loadInfo->GetSkipContentSniffing()) {
return NS_ERROR_NOT_AVAILABLE;
}
}
return GetMimeTypeFromContent((const char*)aContents, aLength, aContentType);
}

Просмотреть файл

@ -2770,15 +2770,10 @@ void NS_SniffContent(const char* aSnifferType, nsIRequest* aRequest,
* The JSON-Viewer relies on its own sniffer to determine, if it can
* render the page, so we need to make an exception if the Server provides
* a application/ mime, as it might be json.
* Bug 1594766
* We also dont't skip sniffing if the currentContentType is empty
* because of legacy page compatibility issues.
*/
nsAutoCString currentContentType;
channel->GetContentType(currentContentType);
if (!currentContentType.IsEmpty() &&
!StringBeginsWith(currentContentType,
if (!StringBeginsWith(currentContentType,
NS_LITERAL_CSTRING("application/"))) {
Telemetry::AccumulateCategorical(
mozilla::Telemetry::LABELS_XCTO_NOSNIFF_TOPLEVEL_NAV_EXCEPTIONS::

Просмотреть файл

@ -354,6 +354,14 @@ nsUnknownDecoder::GetMIMETypeFromContent(nsIRequest* aRequest,
nsACString& type) {
// This is only used by sniffer, therefore we do not need to lock anything
// here.
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (channel) {
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
if (loadInfo->GetSkipContentSniffing()) {
return NS_ERROR_NOT_AVAILABLE;
}
}
mBuffer = const_cast<char*>(reinterpret_cast<const char*>(aData));
mBufferLen = aLength;
DetermineContentType(aRequest);
@ -382,6 +390,11 @@ bool nsUnknownDecoder::AllowSniffing(nsIRequest* aRequest) {
return false;
}
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
if (loadInfo->GetSkipContentSniffing()) {
return false;
}
return !uri->SchemeIs("file");
}
@ -423,11 +436,43 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest) {
if (!mContentType.IsEmpty()) return;
}
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (channel) {
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
if (loadInfo->GetSkipContentSniffing()) {
/*
* If we did not get a useful Content-Type from the server
* but also have sniffing disabled, just determine whether
* to use text/plain or octetstream and log an error to the Console
*/
LastDitchSniff(aRequest);
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
if (httpChannel) {
nsAutoCString type;
httpChannel->GetContentType(type);
nsCOMPtr<nsIURI> requestUri;
httpChannel->GetURI(getter_AddRefs(requestUri));
nsAutoCString spec;
requestUri->GetSpec(spec);
if (spec.Length() > 50) {
spec.Truncate(50);
spec.AppendLiteral("...");
}
httpChannel->LogMimeTypeMismatch(
NS_LITERAL_CSTRING("XTCOWithMIMEValueMissing"), false,
NS_ConvertUTF8toUTF16(spec),
// Type is not used in the Error Message but required
NS_ConvertUTF8toUTF16(type));
}
return;
}
}
const char* testData = mBuffer;
uint32_t testDataLen = mBufferLen;
// Check if data are compressed.
nsAutoCString decodedData;
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (channel) {
// ConvertEncodedData is always called only on a single thread for each
@ -599,6 +644,9 @@ bool nsUnknownDecoder::SniffForXML(nsIRequest* aRequest) {
bool nsUnknownDecoder::SniffURI(nsIRequest* aRequest) {
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
if (loadInfo->GetSkipContentSniffing()) {
return false;
}
nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1"));
if (mimeService) {
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
@ -854,6 +902,10 @@ void nsBinaryDetector::DetermineContentType(nsIRequest* aRequest) {
}
nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->LoadInfo();
if (loadInfo->GetSkipContentSniffing()) {
LastDitchSniff(aRequest);
return;
}
// It's an HTTP channel. Check for the text/plain mess
nsAutoCString contentTypeHdr;
Unused << httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),

Просмотреть файл

@ -140,6 +140,10 @@ nsMediaSniffer::GetMIMETypeFromContent(nsIRequest* aRequest,
nsACString& aSniffedType) {
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (channel) {
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
if (loadInfo->GetSkipContentSniffing()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsLoadFlags loadFlags = 0;
channel->GetLoadFlags(&loadFlags);
if (!(loadFlags & nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE)) {