Commit 56db65a6 authored by Mike West's avatar Mike West Committed by Commit Bot

Restrict `file:` stylesheets to `.css` extensions.

Bug: 788936
Change-Id: Icd4e22745561d57c691fd0f0e75bb8c3e4a59303
Reviewed-on: https://chromium-review.googlesource.com/795717
Commit-Queue: Mike West <mkwst@chromium.org>
Reviewed-by: default avatarnainar <nainar@chromium.org>
Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520610}
parent 7fe493a1
......@@ -422,6 +422,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnablePWAFullCodeCache(
base::FeatureList::IsEnabled(features::kPWAFullCodeCache));
WebRuntimeFeatures::EnableRequireCSSExtensionForFile(
base::FeatureList::IsEnabled(features::kRequireCSSExtensionForFile));
};
} // namespace content
......@@ -266,6 +266,10 @@ const base::Feature kRenderingPipelineThrottling{
const base::Feature kReportRendererPeakMemoryStats{
"ReportRendererPeakMemoryStats", base::FEATURE_DISABLED_BY_DEFAULT};
// When loading CSS from a 'file:' URL, require a CSS-like file extension.
const base::Feature kRequireCSSExtensionForFile{
"RequireCSSExtensionForFile", base::FEATURE_ENABLED_BY_DEFAULT};
// Loading Dispatcher v0 support with ResourceLoadScheduler (crbug.com/729954).
const base::Feature kResourceLoadScheduler{"ResourceLoadScheduler",
base::FEATURE_DISABLED_BY_DEFAULT};
......
......@@ -74,6 +74,7 @@ CONTENT_EXPORT extern const base::Feature kPWAFullCodeCache;
CONTENT_EXPORT extern const base::Feature kRendererSideResourceScheduler;
CONTENT_EXPORT extern const base::Feature kRenderingPipelineThrottling;
CONTENT_EXPORT extern const base::Feature kReportRendererPeakMemoryStats;
CONTENT_EXPORT extern const base::Feature kRequireCSSExtensionForFile;
CONTENT_EXPORT extern const base::Feature kResourceLoadScheduler;
CONTENT_EXPORT extern const base::Feature kScrollAnchoring;
CONTENT_EXPORT
......
CONSOLE WARNING: CSS cannot be loaded from `file:` URLs unless they end in a `.css` file extension.
This is a testharness.js-based test.
PASS `red.not-css` should not load
Harness: the test ran to completion.
<!DOCTYPE html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<link rel="stylesheet" href="./resources/green.css"></link>
<link rel="stylesheet" href="./resources/red.not-css"></link>
<body>
<div></div>
<script>
test(_ => {
assert_equals(getComputedStyle(document.querySelector('div')).backgroundColor, "rgb(0, 128, 0)", 'green.css should be applied');
}, "`red.not-css` should not load");
</script>
</body>
CONSOLE WARNING: CSS cannot be loaded from `file:` URLs unless they end in a `.css` file extension.
Updating attribute value shouldn't result import loading.
Before update:
PASS target.sheet is non-null.
......
......@@ -357,7 +357,8 @@ void StyleSheetContents::ParseAuthorStyleSheet(
IsQuirksModeBehavior(parser_context_->Mode()) && is_same_origin_request
? CSSStyleSheetResource::MIMETypeCheck::kLax
: CSSStyleSheetResource::MIMETypeCheck::kStrict;
String sheet_text = cached_style_sheet->SheetText(mime_type_check);
String sheet_text =
cached_style_sheet->SheetText(parser_context_, mime_type_check);
const ResourceResponse& response = cached_style_sheet->GetResponse();
source_map_url_ = response.HttpHeaderField(HTTPNames::SourceMap);
......
......@@ -220,7 +220,7 @@ void ProcessingInstruction::SetCSSStyleSheet(
// We don't need the cross-origin security check here because we are
// getting the sheet text in "strict" mode. This enforces a valid CSS MIME
// type.
ParseStyleSheet(sheet->SheetText());
ParseStyleSheet(sheet->SheetText(parser_context));
}
void ProcessingInstruction::SetXSLStyleSheet(const String& href,
......
......@@ -544,6 +544,11 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"PaymentRequest's supportedMethods taking an array",
"a single string", M64, "5177301645918208")};
case WebFeature::kLocalCSSFileExtensionRejected:
return {"LocalCSSFileExtensionRejected", M64,
String("CSS cannot be loaded from `file:` URLs unless they end "
"in a `.css` file extension.")};
case WebFeature::kWebAudioDezipperGainNodeGain:
return {"WebAudioDezipperGainNodeGain", Unknown,
DeprecatedWebAudioDezippering("GainNode.gain")};
......
......@@ -304,7 +304,7 @@ void CSSPreloaderResourceClient::ScanCSS(
// augmented to take care of this case without performing an additional
// copy.
double start_time = MonotonicallyIncreasingTimeMS();
const String& chunk = resource->SheetText();
const String& chunk = resource->SheetText(nullptr);
if (chunk.IsNull())
return;
CSSPreloadScanner css_preload_scanner;
......
......@@ -342,7 +342,7 @@ bool InspectorPageAgent::CachedResourceContent(Resource* cached_resource,
case Resource::kCSSStyleSheet:
MaybeEncodeTextContent(
ToCSSStyleSheetResource(cached_resource)
->SheetText(CSSStyleSheetResource::MIMETypeCheck::kLax),
->SheetText(nullptr, CSSStyleSheetResource::MIMETypeCheck::kLax),
cached_resource->ResourceBuffer(), result, base64_encoded);
return true;
case Resource::kScript:
......
......@@ -27,6 +27,7 @@
#include "core/loader/resource/CSSStyleSheetResource.h"
#include "core/css/StyleSheetContents.h"
#include "core/frame/WebFeature.h"
#include "core/loader/resource/StyleSheetResourceClient.h"
#include "platform/SharedBuffer.h"
#include "platform/loader/fetch/FetchParameters.h"
......@@ -36,6 +37,7 @@
#include "platform/loader/fetch/ResourceLoaderOptions.h"
#include "platform/loader/fetch/TextResourceDecoderOptions.h"
#include "platform/network/http_names.h"
#include "platform/network/mime/MIMETypeRegistry.h"
#include "platform/runtime_enabled_features.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "platform/wtf/Time.h"
......@@ -124,8 +126,9 @@ void CSSStyleSheetResource::DidAddClient(ResourceClient* c) {
}
const String CSSStyleSheetResource::SheetText(
const CSSParserContext* parser_context,
MIMETypeCheck mime_type_check) const {
if (!CanUseSheet(mime_type_check))
if (!CanUseSheet(parser_context, mime_type_check))
return String();
// Use cached decoded sheet text when available
......@@ -194,10 +197,38 @@ void CSSStyleSheetResource::DestroyDecodedDataForFailedRevalidation() {
DestroyDecodedDataIfPossible();
}
bool CSSStyleSheetResource::CanUseSheet(MIMETypeCheck mime_type_check) const {
bool CSSStyleSheetResource::CanUseSheet(const CSSParserContext* parser_context,
MIMETypeCheck mime_type_check) const {
if (ErrorOccurred())
return false;
// For `file:` URLs, we may need to be a little more strict than the below.
// Though we'll likely change this in the future, for the moment we're going
// to enforce a file-extension requirement on stylesheets loaded from `file:`
// URLs and see how far it gets us.
KURL sheet_url = GetResponse().Url();
if (sheet_url.IsLocalFile()) {
if (parser_context) {
parser_context->Count(WebFeature::kLocalCSSFile);
}
// Grab |sheet_url|'s filename's extension (if present), and check whether
// or not it maps to a `text/css` MIME type:
String extension;
int last_dot = sheet_url.LastPathComponent().ReverseFind('.');
if (last_dot != -1)
extension = sheet_url.LastPathComponent().Substring(last_dot + 1);
if (!EqualIgnoringASCIICase(
MIMETypeRegistry::GetMIMETypeForExtension(extension), "text/css")) {
if (parser_context) {
parser_context->CountDeprecation(
WebFeature::kLocalCSSFileExtensionRejected);
}
if (RuntimeEnabledFeatures::RequireCSSExtensionForFileEnabled()) {
return false;
}
}
}
// This check exactly matches Firefox. Note that we grab the Content-Type
// header directly because we want to see what the value is BEFORE content
// sniffing. Firefox does this by setting a "type hint" on the channel. This
......
......@@ -52,7 +52,8 @@ class CORE_EXPORT CSSStyleSheetResource final : public StyleSheetResource {
~CSSStyleSheetResource() override;
void Trace(blink::Visitor*) override;
const String SheetText(MIMETypeCheck = MIMETypeCheck::kStrict) const;
const String SheetText(const CSSParserContext*,
MIMETypeCheck = MIMETypeCheck::kStrict) const;
void DidAddClient(ResourceClient*) override;
......@@ -79,7 +80,7 @@ class CORE_EXPORT CSSStyleSheetResource final : public StyleSheetResource {
const ResourceLoaderOptions&,
const TextResourceDecoderOptions&);
bool CanUseSheet(MIMETypeCheck) const;
bool CanUseSheet(const CSSParserContext*, MIMETypeCheck) const;
void NotifyFinished() override;
void SetParsedStyleSheetCache(StyleSheetContents*);
......
......@@ -374,6 +374,10 @@ void WebRuntimeFeatures::EnableRenderingPipelineThrottling(bool enable) {
RuntimeEnabledFeatures::SetRenderingPipelineThrottlingEnabled(enable);
}
void WebRuntimeFeatures::EnableRequireCSSExtensionForFile(bool enable) {
RuntimeEnabledFeatures::SetRequireCSSExtensionForFileEnabled(enable);
}
void WebRuntimeFeatures::EnableResourceLoadScheduler(bool enable) {
RuntimeEnabledFeatures::SetResourceLoadSchedulerEnabled(enable);
}
......
......@@ -862,6 +862,10 @@
name: "ReportingObserver",
status: "experimental",
},
{
name: "RequireCSSExtensionForFile",
status: "stable",
},
{
name: "ResizeObserver",
status: "stable",
......
......@@ -129,6 +129,7 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableReducedReferrerGranularity(bool);
BLINK_PLATFORM_EXPORT static void EnableRemotePlaybackAPI(bool);
BLINK_PLATFORM_EXPORT static void EnableRenderingPipelineThrottling(bool);
BLINK_PLATFORM_EXPORT static void EnableRequireCSSExtensionForFile(bool);
BLINK_PLATFORM_EXPORT static void EnableResourceLoadScheduler(bool);
BLINK_PLATFORM_EXPORT static void EnableRootLayerScrolling(bool);
BLINK_PLATFORM_EXPORT static void EnableScriptedSpeech(bool);
......
......@@ -1774,6 +1774,8 @@ enum WebFeature {
kV8RTCPeerConnection_GetReceivers_Method = 2253,
kV8RTCPeerConnection_AddTrack_Method = 2254,
kV8RTCPeerConnection_RemoveTrack_Method = 2255,
kLocalCSSFile = 2256,
kLocalCSSFileExtensionRejected = 2257,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
......
......@@ -17101,6 +17101,8 @@ Called by update_net_error_codes.py.-->
<int value="2253" label="V8RTCPeerConnection_GetReceivers_Method"/>
<int value="2254" label="V8RTCPeerConnection_AddTrack_Method"/>
<int value="2255" label="V8RTCPeerConnection_RemoveTrack_Method"/>
<int value="2256" label="LocalCSSFile"/>
<int value="2257" label="LocalCSSFileExtensionRejected"/>
</enum>
<enum name="FeedbackSource">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment