CVE-2025-8582
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/renderer/core/dom/decoded_data_document_parser.cc |
modified | |
ifthird_party/blink/renderer/core/html/parser/text_resource_decoder.cc |
modified | |
TESTthird_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc |
modified |
Files Changed
chrome/browser/chrome_web_platform_security_metrics_browsertest.ccthird_party/blink/renderer/core/dom/decoded_data_document_parser.ccthird_party/blink/renderer/core/frame/deprecation/deprecation.json5third_party/blink/renderer/core/html/parser/text_resource_decoder.ccthird_party/blink/renderer/core/html/parser/text_resource_decoder_test.ccthird_party/blink/renderer/platform/runtime_enabled_features.json5third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP-late.tentative-expected.txt
Patch
From a2d76e87da6b467dfcc11e84327e7c00f0a1b5a7 Mon Sep 17 00:00:00 2001
From: Jun Kokatsu <jkokatsu@google.com>
Date: Wed, 18 Jun 2025 09:06:21 -0700
Subject: [PATCH] Disable auto-detection of ISO-2022-JP charset
Per approval in the intent to ship thread[1], this CL removes support
for auto-detection of ISO-2022-JP charset in HTML.
Timelines:
- Warning messages added in [2], in M137.
- Flag added and disabled, now, in M139.
- Flag and code can be removed in M141 or so, once there are no problems
when M139 goes to stable.
[1]:
https://groups.google.com/a/chromium.org/g/blink-dev/c/yIgrr5YNGJ4/m/jKvlEerFCAAJ
[2]:
https://chromiumdash.appspot.com/commit/0dd1c5ff57ca550269c61455b9a3385289c033bc
Bug: 40089450
Change-Id: Id3bd642da8c630188775276909e6e2bffbad174c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6378605
Auto-Submit: Jun Kokatsu <jkokatsu@google.com>
Reviewed-by: Mason Freed <masonf@chromium.org>
Reviewed-by: Charlie Reis <creis@chromium.org>
Commit-Queue: Mason Freed <masonf@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1475633}
---
diff --git a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
index 531f43f..81bb210 100644
--- a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
+++ b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
@@ -162,6 +162,8 @@
blink::features::kSubSampleWindowProxyUsageMetrics,
// PNA metrics may not record correctly if LNA checks are enabled.
network::features::kLocalNetworkAccessChecks,
+ // Disabling this flag just to test that the flag is working.
+ blink::features::kRemoveCharsetAutoDetectionForISO2022JP,
};
}
@@ -2999,7 +3001,6 @@
EXPECT_TRUE(content::NavigateToURL(
web_contents(), https_server().GetURL("/security/utf8.html")));
CheckCounter(WebFeature::kCharsetAutoDetection, 0);
- CheckCounter(WebFeature::kCharsetAutoDetectionISO2022JP, 0);
}
IN_PROC_BROWSER_TEST_F(ChromeWebPlatformSecurityMetricsBrowserTest,
@@ -3007,15 +3008,16 @@
EXPECT_TRUE(content::NavigateToURL(
web_contents(), https_server().GetURL("/security/no_charset.html")));
CheckCounter(WebFeature::kCharsetAutoDetection, 1);
- CheckCounter(WebFeature::kCharsetAutoDetectionISO2022JP, 0);
}
IN_PROC_BROWSER_TEST_F(ChromeWebPlatformSecurityMetricsBrowserTest,
ISO2022JPDetection) {
EXPECT_TRUE(content::NavigateToURL(
web_contents(), https_server().GetURL("/security/iso_2022_jp.html")));
- CheckCounter(WebFeature::kCharsetAutoDetection, 1);
- CheckCounter(WebFeature::kCharsetAutoDetectionISO2022JP, 1);
+ // Given RemoveCharsetAutoDetectionForISO2022JP is disabled in
+ // ChromeWebPlatformSecurityMetricsBrowserTest, this should pass.
+ EXPECT_EQ("ISO-2022-JP",
+ content::EvalJs(web_contents(), "document.characterSet"));
}
// TODO(arthursonzogni): Add basic test(s) for the WebFeatures:
diff --git a/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc b/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc
index 4d4c2e0..2f11166 100644
--- a/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc
+++ b/third_party/blink/renderer/core/dom/decoded_data_document_parser.cc
@@ -66,10 +66,6 @@
String decoded = decoder_->Decode(bytes, &auto_detected_charset);
if (!auto_detected_charset.empty()) {
GetDocument()->CountUse(WebFeature::kCharsetAutoDetection);
- if (auto_detected_charset == "ISO-2022-JP") {
- GetDocument()->CountDeprecation(
- WebFeature::kCharsetAutoDetectionISO2022JP);
- }
}
UpdateDocument(decoded);
}
diff --git a/third_party/blink/renderer/core/frame/deprecation/deprecation.json5 b/third_party/blink/renderer/core/frame/deprecation/deprecation.json5
index ba3820c9..2a04e37 100644
--- a/third_party/blink/renderer/core/frame/deprecation/deprecation.json5
+++ b/third_party/blink/renderer/core/frame/deprecation/deprecation.json5
@@ -80,15 +80,6 @@
chrome_status_feature: 5735596811091968,
},
{
- name: "CharsetAutoDetectionISO2022JP",
- message: "Auto-detection of ISO-2022-JP character set is deprecated and it will be disabled in the near future. Please specify character set in the Content Type header or by using a meta tag (https://developer.mozilla.org/en-US/docs/Glossary/Character_encoding).",
- translation_note: "Warning displayed to developers that they did not specify character encoding for HTML document, and that auto-detection of specific character set (i.e. ISO-2022-JP) used by the webiste won't be supported in the near futre.",
- web_features: [
- "kCharsetAutoDetectionISO2022JP",
- ],
- chrome_status_feature: 6576566521561088,
- },
- {
name: "ChromeLoadTimesConnectionInfo",
message: "`chrome.loadTimes()` is deprecated, instead use standardized API: Navigation Timing 2.",
translation_note: "This warning occurs when the website attempts to invoke the deprecated `chrome.loadTimes().connectionInfo` API.",
diff --git a/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc b/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
index 8d8731b4..a7620ee5 100644
--- a/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
+++ b/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
@@ -28,6 +28,7 @@
#include "base/strings/string_view_util.h"
#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/text_encoding_detector.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include "third_party/blink/renderer/platform/wtf/text/text_codec.h"
@@ -342,14 +343,21 @@
if (DetectTextEncoding(
base::as_bytes(data), options_.HintEncoding().Utf8().c_str(),
options_.HintURL(), options_.HintLanguage(), &detected_encoding)) {
- SetEncoding(detected_encoding, kEncodingFromContentSniffing);
- if (auto_detected_charset != nullptr &&
- (options_.GetContentType() ==
- TextResourceDecoderOptions::kHTMLContent ||
- options_.GetContentType() ==
- TextResourceDecoderOptions::kXMLContent)) {
- *auto_detected_charset = detected_encoding.GetName();
+ if (options_.GetContentType() == TextResourceDecoderOptions::kHTMLContent ||
+ options_.GetContentType() == TextResourceDecoderOptions::kXMLContent) {
+ const AtomicString& charset = detected_encoding.GetName();
+ if (charset == "ISO-2022-JP" &&
+ RuntimeEnabledFeatures::
+ RemoveCharsetAutoDetectionForISO2022JPEnabled()) {
+ // Auto-detection of ISO-2022-JP is disabled: crbug.com/40089450
+ return;
+ }
+
+ if (auto_detected_charset != nullptr) {
+ *auto_detected_charset = charset;
+ }
}
+ SetEncoding(detected_encoding, kEncodingFromContentSniffing);
}
if (detected_encoding != UnknownEncoding()) {
detection_completed_ = true;
diff --git a/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc b/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
index e6003eed..b43b680 100644
--- a/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
+++ b/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
@@ -185,4 +185,19 @@
EXPECT_EQ(Utf8Encoding(), decoder->Encoding());
}
+TEST(TextResourceDecoderTest, DoNotAutoDetectISO2022JP) {
+ test::TaskEnvironment task_environment;
+ std::unique_ptr<TextResourceDecoder> decoder =
+ std::make_unique<TextResourceDecoder>(
+ TextResourceDecoderOptions::CreateWithAutoDetection(
+ TextResourceDecoderOptions::kHTMLContent, Utf8Encoding(),
+ UnknownEncoding(), NullURL()));
+ // ISO-2022-JP escape sequences.
+ const unsigned char kISO2022JP[] = {0x1b, 0x24, 0x42, 0x30, 0x42,
+ 0x30, 0x44, 0x1b, 0x28, 0x42};
+ String auto_detected_charset;
+ decoder->Decode(base::span(kISO2022JP), &auto_detected_charset);
+ EXPECT_TRUE(auto_detected_charset.empty());
+}
+
} // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index f3e26ce..50016912 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -3969,6 +3969,13 @@
"default": "experimental"},
},
{
+ // This feature acts as a kill switch for ISO-2022-JP auto-detection.
+ // This will be shipped in M139, and it can be removed in M141.
+ // See https://chromestatus.com/feature/6576566521561088.
+ name: "RemoveCharsetAutoDetectionForISO2022JP",
+ status: "stable",
+ },
+ {
name: "RemoveDanglingMarkupInTarget",
status: "stable",
},
diff --git a/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP-late.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP-late.tentative-expected.txt
new file mode 100644
index 0000000..a697926
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP-late.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Check detection result
+ assert_equals: Expected ISO-2022-JP expected "ISO-2022-JP" but got "windows-1252"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP.tentative-expected.txt
new file mode 100644
Regression Test / PoC
diff --git a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
index 531f43f..81bb210 100644
--- a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
+++ b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
@@ -162,6 +162,8 @@
blink::features::kSubSampleWindowProxyUsageMetrics,
// PNA metrics may not record correctly if LNA checks are enabled.
network::features::kLocalNetworkAccessChecks,
+ // Disabling this flag just to test that the flag is working.
+ blink::features::kRemoveCharsetAutoDetectionForISO2022JP,
};
}
@@ -2999,7 +3001,6 @@
EXPECT_TRUE(content::NavigateToURL(
web_contents(), https_server().GetURL("/security/utf8.html")));
CheckCounter(WebFeature::kCharsetAutoDetection, 0);
- CheckCounter(WebFeature::kCharsetAutoDetectionISO2022JP, 0);
}
IN_PROC_BROWSER_TEST_F(ChromeWebPlatformSecurityMetricsBrowserTest,
@@ -3007,15 +3008,16 @@
EXPECT_TRUE(content::NavigateToURL(
web_contents(), https_server().GetURL("/security/no_charset.html")));
CheckCounter(WebFeature::kCharsetAutoDetection, 1);
- CheckCounter(WebFeature::kCharsetAutoDetectionISO2022JP, 0);
}
IN_PROC_BROWSER_TEST_F(ChromeWebPlatformSecurityMetricsBrowserTest,
ISO2022JPDetection) {
EXPECT_TRUE(content::NavigateToURL(
web_contents(), https_server().GetURL("/security/iso_2022_jp.html")));
- CheckCounter(WebFeature::kCharsetAutoDetection, 1);
- CheckCounter(WebFeature::kCharsetAutoDetectionISO2022JP, 1);
+ // Given RemoveCharsetAutoDetectionForISO2022JP is disabled in
+ // ChromeWebPlatformSecurityMetricsBrowserTest, this should pass.
+ EXPECT_EQ("ISO-2022-JP",
+ content::EvalJs(web_contents(), "document.characterSet"));
}
// TODO(arthursonzogni): Add basic test(s) for the WebFeatures:
diff --git a/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc b/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
index e6003eed..b43b680 100644
--- a/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
+++ b/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
@@ -185,4 +185,19 @@
EXPECT_EQ(Utf8Encoding(), decoder->Encoding());
}
+TEST(TextResourceDecoderTest, DoNotAutoDetectISO2022JP) {
+ test::TaskEnvironment task_environment;
+ std::unique_ptr<TextResourceDecoder> decoder =
+ std::make_unique<TextResourceDecoder>(
+ TextResourceDecoderOptions::CreateWithAutoDetection(
+ TextResourceDecoderOptions::kHTMLContent, Utf8Encoding(),
+ UnknownEncoding(), NullURL()));
+ // ISO-2022-JP escape sequences.
+ const unsigned char kISO2022JP[] = {0x1b, 0x24, 0x42, 0x30, 0x42,
+ 0x30, 0x44, 0x1b, 0x28, 0x42};
+ String auto_detected_charset;
+ decoder->Decode(base::span(kISO2022JP), &auto_detected_charset);
+ EXPECT_TRUE(auto_detected_charset.empty());
+}
+
} // namespace blink
diff --git a/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP-late.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP-late.tentative-expected.txt
new file mode 100644
index 0000000..a697926
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP-late.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Check detection result
+ assert_equals: Expected ISO-2022-JP expected "ISO-2022-JP" but got "windows-1252"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP.tentative-expected.txt
new file mode 100644
index 0000000..a697926
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/encoding-detection/ja-ISO-2022-JP.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+[FAIL] Check detection result
+ assert_equals: Expected ISO-2022-JP expected "ISO-2022-JP" but got "windows-1252"
+Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/iso-2022-jp-auto-detection-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/iso-2022-jp-auto-detection-expected.txt
deleted file mode 100644
index 80c2957..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/iso-2022-jp-auto-detection-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Tests that deprecation issues for ISO-2022-JP are reported
-Inspector issue: {
- issue : {
- code : DeprecationIssue
- details : {
- deprecationIssueDetails : {
- affectedFrame : {
- frameId : <string>
- }
- sourceCodeLocation : {
- columnNumber : 0
- lineNumber : 0
- url : https://example.test:8443/inspector-protocol/resources/iso_2022_jp.html
- }
- type : CharsetAutoDetectionISO2022JP
- }
- }
- }
-}
-
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/iso-2022-jp-auto-detection.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/iso-2022-jp-auto-detection.js
deleted file mode 100644
index 259458b..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/iso-2022-jp-auto-detection.js
+++ /dev/null
@@ -1,13 +0,0 @@
-(async testRunner => {
- const {page, session, dp} = await testRunner.startBlank(
- `Tests that deprecation issues for ISO-2022-JP are reported`);
- await dp.Audits.enable();
- const promise = dp.Audits.onceIssueAdded();
-
- page.navigate(
- 'https://example.test:8443/inspector-protocol/resources/iso_2022_jp.html');
-
- const result = await promise;
- testRunner.log(result.params, "Inspector issue: ");
- testRunner.completeTest();
- });
\ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iso_2022_jp.html b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iso_2022_jp.html
deleted file mode 100644
index f86a7cb..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iso_2022_jp.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>XSS</title>
-</head>
-<body>
-<img alt="$@">(B <img alt="id=foo ">
-</body></html>
\ No newline at end of file
Original Bug Report
Security: ASCII can be autodetected as ISO-2022-JP
VULNERABILITY DETAILS
All-ASCII HTML can get autodetected as ISO-2022-JP, which makes ASCII content that doesn’t look like markup treated as active content. This may lead to XSS if the site serves user-supplied content.
As a mitigating factor, to be vulnerable a site has to violate two best practices:
- The site needs not to declare its character encoding. (Pretty realistic, unfortunately.)
- Instead of escaping all less-than signs in user-supplied content as would be proper, the site needs to try to filter out markup specifically. (The proof of concept includes an ASCII less-than sign byte followed by a non-alphabetic byte, so there’s a chance there are filter out there that wouldn’t consider it as matching a regexp for an HTML tag.)
However, from the work I’ve seen Mike West do, I have inferred that Chrome considers these kinds of site mistakes to be in scope for browser-based counter-measures.
As a remedy, I suggest excluding ISO-2022-JP from potential autodetection outcomes.
VERSION Google Chrome 62.0.3202.75 (Official Build) (64-bit) Revision 67b212ffb03c4401235f8961e2d15371b96cde27-refs/branch-heads/3202@{#750} OS Ubuntu 16.04
REPRODUCTION CASE Load https://hsivonen.com/test/p/iso-2022-jp-autodetect.htm in Chrome.
ADDITIONAL INFO For bug unhiding, coordination with unhiding https://bugzilla.mozilla.org/show_bug.cgi?id=1362365 would be appreciated.