Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Translate
DescriptionUse after free in Translate
ComponentTranslate
Bug ClassUAF
Tracker379516109
Fix commit3725ff38e13b (chromium/src) +26/-38
CISA KEVNot listed
Creditedlime(@limeSec_) from TIANGONG Team of Legendsec at QI-ANXIN Group
Disclosed2024-12-10

Files Changed

  • testing/variations/fieldtrial_testing_config.json
  • third_party/blink/web_tests/TestExpectations
  • third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
  • third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
  • third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
  • third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
From 3725ff38e13b18721aee8c33a77914855eeab8a1 Mon Sep 17 00:00:00 2001
From: Fergal Daly <[email protected]>
Date: Fri, 29 Nov 2024 06:45:56 +0000
Subject: [PATCH] Disable LanguageDetectionAPI.

We intend to disable it for users via the kill switch. Disabling it in
the test config is a prerequisite for doing that.

Following http://go/finch-killswitch

Bug: 379516109
Change-Id: I64c6bb31ccc671d64adcbcd269aca9c6f0c23332
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6056711
Auto-Submit: Fergal Daly <[email protected]>
Commit-Queue: Tsuyoshi Horo <[email protected]>
Reviewed-by: Tsuyoshi Horo <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1389647}
---

diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index d56c5eb..dd12219 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -13111,6 +13111,27 @@
             ]
         }
     ],
+    "LanguageDetectionAPI": [
+        {
+            "platforms": [
+                "android_webview",
+                "android",
+                "chromeos",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Disabled",
+                    "disable_features": [
+                        "LanguageDetectionAPI"
+                    ]
+                }
+            ]
+        }
+    ],
     "LauncherGameSearchStudy": [
         {
             "platforms": [
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c7b681f..30e882cd1 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1468,7 +1468,11 @@
 # Bug in <select multiple> tap behavior:
 crbug.com/1045672 fast/forms/select/listbox-tap.html [ Failure ]
 
-# Under development, passes with --no-sandbox.
+# Flipping the kill switch on this feature.
+crbug.com/379516109 external/wpt/ai/language_detection/canDetect.tentative.window.html [ Failure Timeout ]
+crbug.com/379516109 external/wpt/ai/language_detection/capabilities.tentative.https.window.html [ Failure Timeout ]
+
+# Under development, passes with --no-sandbox. See also https://crbug.com/379516109
 crbug.com/354069716 external/wpt/ai/language_detection/detect-en.tentative.window.html [ Failure Timeout ]
 crbug.com/354069716 external/wpt/ai/language_detection/detector.https.tentative.window.html [ Failure Timeout ]
 
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 1565484..ef10d64 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -11,11 +11,6 @@
     getter ondownloadprogress
     method constructor
     setter ondownloadprogress
-interface AILanguageDetectorCapabilities
-    attribute @@toStringTag
-    getter available
-    method constructor
-    method languageAvailable
 interface AILanguageModel : EventTarget
     attribute @@toStringTag
     getter maxTokens
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 0c69c75f..5f317a5 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -16,11 +16,6 @@
 [Worker]     getter ondownloadprogress
 [Worker]     method constructor
 [Worker]     setter ondownloadprogress
-[Worker] interface AILanguageDetectorCapabilities
-[Worker]     attribute @@toStringTag
-[Worker]     getter available
-[Worker]     method constructor
-[Worker]     method languageAvailable
 [Worker] interface AILanguageModel : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter maxTokens
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 86acfa31..6f1a31aa0 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5,7 +5,6 @@
 [INTERFACES]
 interface AI
     attribute @@toStringTag
-    getter languageDetector
     getter languageModel
     getter rewriter
     getter summarizer
@@ -17,21 +16,6 @@
     getter ondownloadprogress
     method constructor
     setter ondownloadprogress
-interface AILanguageDetector
-    attribute @@toStringTag
-    method constructor
-    method destroy
-    method detect
-interface AILanguageDetectorCapabilities
-    attribute @@toStringTag
-    getter available
-    method constructor
-    method languageAvailable
-interface AILanguageDetectorFactory
-    attribute @@toStringTag
-    method capabilities
-    method constructor
-    method create
 interface AILanguageModel : EventTarget
     attribute @@toStringTag
     getter maxTokens
@@ -5691,10 +5675,6 @@
     setter composite
     setter pseudoElement
     setter target
-interface LanguageDetector
-    attribute @@toStringTag
-    method constructor
-    method detect
 interface LanguageTranslator
     attribute @@toStringTag
     method constructor
@@ -10054,10 +10034,8 @@
     method constructor
 interface Translation
     attribute @@toStringTag
-    method canDetect
     method canTranslate
     method constructor
-    method createDetector
     method createTranslator
 interface TreeWalker
     attribute @@toStringTag
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index 53f76c8..c6d3c02 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -16,11 +16,6 @@
 [Worker]     getter ondownloadprogress
 [Worker]     method constructor
 [Worker]     setter ondownloadprogress
-[Worker] interface AILanguageDetectorCapabilities
-[Worker]     attribute @@toStringTag
-[Worker]     getter available
-[Worker]     method constructor
-[Worker]     method languageAvailable
 [Worker] interface AILanguageModel : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter maxTokens
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c7b681f..30e882cd1 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1468,7 +1468,11 @@
 # Bug in <select multiple> tap behavior:
 crbug.com/1045672 fast/forms/select/listbox-tap.html [ Failure ]
 
-# Under development, passes with --no-sandbox.
+# Flipping the kill switch on this feature.
+crbug.com/379516109 external/wpt/ai/language_detection/canDetect.tentative.window.html [ Failure Timeout ]
+crbug.com/379516109 external/wpt/ai/language_detection/capabilities.tentative.https.window.html [ Failure Timeout ]
+
+# Under development, passes with --no-sandbox. See also https://crbug.com/379516109
 crbug.com/354069716 external/wpt/ai/language_detection/detect-en.tentative.window.html [ Failure Timeout ]
 crbug.com/354069716 external/wpt/ai/language_detection/detector.https.tentative.window.html [ Failure Timeout ]
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 1565484..ef10d64 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -11,11 +11,6 @@
     getter ondownloadprogress
     method constructor
     setter ondownloadprogress
-interface AILanguageDetectorCapabilities
-    attribute @@toStringTag
-    getter available
-    method constructor
-    method languageAvailable
 interface AILanguageModel : EventTarget
     attribute @@toStringTag
     getter maxTokens
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 0c69c75f..5f317a5 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -16,11 +16,6 @@
 [Worker]     getter ondownloadprogress
 [Worker]     method constructor
 [Worker]     setter ondownloadprogress
-[Worker] interface AILanguageDetectorCapabilities
-[Worker]     attribute @@toStringTag
-[Worker]     getter available
-[Worker]     method constructor
-[Worker]     method languageAvailable
 [Worker] interface AILanguageModel : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter maxTokens
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 86acfa31..6f1a31aa0 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5,7 +5,6 @@
 [INTERFACES]
 interface AI
     attribute @@toStringTag
-    getter languageDetector
     getter languageModel
     getter rewriter
     getter summarizer
@@ -17,21 +16,6 @@
     getter ondownloadprogress
     method constructor
     setter ondownloadprogress
-interface AILanguageDetector
-    attribute @@toStringTag
-    method constructor
-    method destroy
-    method detect
-interface AILanguageDetectorCapabilities
-    attribute @@toStringTag
-    getter available
-    method constructor
-    method languageAvailable
-interface AILanguageDetectorFactory
-    attribute @@toStringTag
-    method capabilities
-    method constructor
-    method create
 interface AILanguageModel : EventTarget
     attribute @@toStringTag
     getter maxTokens
@@ -5691,10 +5675,6 @@
     setter composite
     setter pseudoElement
     setter target
-interface LanguageDetector
-    attribute @@toStringTag
-    method constructor
-    method detect
 interface LanguageTranslator
     attribute @@toStringTag
     method constructor
@@ -10054,10 +10034,8 @@
     method constructor
 interface Translation
     attribute @@toStringTag
-    method canDetect
     method canTranslate
     method constructor
-    method createDetector
     method createTranslator
 interface TreeWalker
     attribute @@toStringTag
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index 53f76c8..c6d3c02 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -16,11 +16,6 @@
 [Worker]     getter ondownloadprogress
 [Worker]     method constructor
 [Worker]     setter ondownloadprogress
-[Worker] interface AILanguageDetectorCapabilities
-[Worker]     attribute @@toStringTag
-[Worker]     getter available
-[Worker]     method constructor
-[Worker]     method languageAvailable
 [Worker] interface AILanguageModel : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter maxTokens
Loading diff…

Original Bug Report

reported by [email protected]

AddressSanitizer:heap-use-after-free on LanguageDetectionModel::NotifyModelLoaded

Steps to reproduce the problem

repro:

  1. launch chrome with –enable-features=LanguageDetectionAPI

  2. apply patch.diff which simplify trigger

  3. run poc.html.

Problem Description

  1. In the function LanguageDetectionModel:: NotifyModelLoaded, there is an iterator operation. When AILanguageDetector performs detection, the callback OnDetectComplete will be added to the model_loaded_callbacks_, and the OnDetectComplete function body will have a user-defined callback resolve ->Resolve. The following is the reverse reference of the chain.
void LanguageDetectionModel::NotifyModelLoaded() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  for (auto&& callback_ : model_loaded_callbacks_) {
    std::move(callback_).Run(*this);
  }
  loaded_ = true;
  model_loaded_callbacks_.clear();
}
------------------------
void LanguageDetectionModel::AddOnModelLoadedCallback(
    ModelLoadedCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (loaded_ || model_loaded_callbacks_.size() >= kMaxPendingCallbacksCount) {
    std::move(callback).Run(*this);
  } else {
    model_loaded_callbacks_.emplace_back(std::move(callback));
  }
}
------------------------
void DetectLanguage(const WTF::String& text,
                    DetectLanguageCallback on_complete) {
  auto& model = language_detection::GetLanguageDetectionModel();
  model.AddOnModelLoadedCallback(
      WTF::BindOnce(DetectLanguageWithModel, text, std::move(on_complete)));
}
------------------------
ScriptPromise<IDLSequence<LanguageDetectionResult>> AILanguageDetector::detect(
    ScriptState* script_state,
    const WTF::String& input,
    AILanguageDetectorDetectOptions* options,
    ExceptionState& exception_state) {
[...]

  DetectLanguage(input, WTF::BindOnce(AILanguageDetector::OnDetectComplete,
                                      WrapPersistent(resolver)));
  return resolver->Promise();
}
-----------------------
void AILanguageDetector::OnDetectComplete(
    ScriptPromiseResolver<IDLSequence<LanguageDetectionResult>>* resolver,
    base::expected<WTF::Vector<LanguagePrediction>, DetectLanguageError>
        result) {
  if (result.has_value()) {
    // Order the result from most to least confident.
    std::sort(result.value().rbegin(), result.value().rend());
    resolver->Resolve(ConvertResult(result.value()));
  } else {
    switch (result.error()) {
      case DetectLanguageError::kUnavailable:
        resolver->Reject("Model not available");
    }
  }
}
  1. LanguageDetectionModel:: NotifyModelLoaded is called in LanguageDetectionAgent:: updateLanguageDetectionModel, which can be traced back to LanguageDetectionAgent:: WasShown. However, in thisWasShown, Mojo calls are made to communicate with the browser throughVNet anguageDetectionHandler () ->VNet anguageDetectionModel `` The finalcallbackreturns therendererfor calling, which represents an asynchronous process in the middle of therendererexecution. This means that we can construct a POC. Before running theLanguageDetectionAgent:: Updating LanguageDetectionModel, we will fill the corresponding quantity and contain user-defined iterator invalidation code in the model_loaded_callback`. Ultimately, it will lead to the failure of iterators. Causing UAF.
void LanguageDetectionAgent::WasShown() {
  // Check if the the render frame was initially hidden and
  // the model request was delayed until the frame was in
  // the foreground.
[...]
  GetLanguageDetectionHandler()->GetLanguageDetectionModel(
      base::BindOnce(&LanguageDetectionAgent::UpdateLanguageDetectionModel,
                     weak_pointer_factory_.GetWeakPtr()));
}
  1. https://source.chromium.org/chromium/chromium/src/+/main:components/language_detection/core/language_detection_model.cc;l=230?q=LanguageDetectionModel::NotifyModelLoaded&ss=chromium%2Fchromium%2Fsrc

  2. https://source.chromium.org/chromium/chromium/src/+/main:components/language_detection/content/renderer/language_detection_agent.cc;l=107?q=LanguageDetectionAgent::WasShown&ss=chromium%2Fchromium%2Fsrc

bitset: https://source.chromium.org/chromium/chromium/src/+/6742751ccf591d9ba1670c3082efbf345084b7d0

why need patch? simplify trigger progress. No impact on the vulnerability principle.

fix sugesstions: swap the model_loaded_callbacks_. see fix.diff

Summary

AddressSanitizer:heap-use-after-free on LanguageDetectionModel::NotifyModelLoaded

Custom Questions

Type of crash:

tab

Crash state:

see asan.log

Reporter credit:

lime(@limeSec)

Additional Data

Category: Security
Chrome Channel: Not sure
Regression: N/A

View on issue tracker