CVE-2025-11458
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fcomponents/trusted_vault/securebox_unittest.cc |
modified |
Files Changed
components/trusted_vault/securebox.cccomponents/trusted_vault/securebox_unittest.cc
Patch
From 0e63d7ab62928f5645a42484fbf47cba43b0128f Mon Sep 17 00:00:00 2001 From: Mikel Astiz <[email protected]> Date: Fri, 26 Sep 2025 11:49:35 -0700 Subject: [PATCH] [TrustedVault] Fix public import missing size validation `SecureBoxPublicKey::CreateByImport()` should have safeguards against input data not matching the expected size, and return null in that case. Bug: 443196747 Change-Id: I0996dbe383a51b1fd8269fbe429c78f24f283989 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6990129 Reviewed-by: Maksim Moskvitin <[email protected]> Commit-Queue: Mikel Astiz <[email protected]> Cr-Commit-Position: refs/heads/main@{#1521442} --- diff --git a/components/trusted_vault/securebox.cc b/components/trusted_vault/securebox.cc index 384c7c5..ad63561 100644 --- a/components/trusted_vault/securebox.cc +++ b/components/trusted_vault/securebox.cc @@ -63,11 +63,16 @@ return result; } -// Creates public EC_KEY from |public_key_bytes|. |public_key_bytes| must be -// a X9.62 formatted NIST P-256 point. +// Creates public EC_KEY from |public_key_bytes|. Returns nullptr if +// |public_key_bytes| does not represent a X9.62 formatted NIST P-256 point. bssl::UniquePtr<EC_KEY> ECPublicKeyFromBytes( base::span<const uint8_t> public_key_bytes, const crypto::OpenSSLErrStackTracer& err_tracer) { + if (public_key_bytes.size() != kECPointLength) { + // |public_key_bytes| doesn't represent a valid NIST P-256 point. + return nullptr; + } + bssl::UniquePtr<EC_KEY> ec_key( EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); DCHECK(ec_key); diff --git a/components/trusted_vault/securebox_unittest.cc b/components/trusted_vault/securebox_unittest.cc index dfd08987..45622b3 100644 --- a/components/trusted_vault/securebox_unittest.cc +++ b/components/trusted_vault/securebox_unittest.cc @@ -25,6 +25,7 @@ using testing::Eq; using testing::IsEmpty; +using testing::IsNull; using testing::Ne; using testing::NotNull; using testing::SizeIs; @@ -43,6 +44,16 @@ const std::vector<uint8_t> kTestPayload = StringToBytes("TEST_PAYLOAD"); }; +TEST_F(SecureBoxTest, ShouldReturnNullIfCreateByImportWithIncorrectSize) { + // Sizes other than `kPublicKeyLengthInBytes` should return null. + EXPECT_THAT(SecureBoxPublicKey::CreateByImport(std::vector<uint8_t>(64, 1)), + IsNull()); + EXPECT_THAT(SecureBoxPublicKey::CreateByImport(std::vector<uint8_t>(66, 1)), + IsNull()); + EXPECT_THAT(SecureBoxPublicKey::CreateByImport(std::vector<uint8_t>()), + IsNull()); +} + TEST_F(SecureBoxTest, ShouldExportAndImportPublicKey) { std::unique_ptr<SecureBoxKeyPair> key_pair = SecureBoxKeyPair::GenerateRandom();
Regression Test / PoC
diff --git a/components/trusted_vault/securebox_unittest.cc b/components/trusted_vault/securebox_unittest.cc
index dfd08987..45622b3 100644
--- a/components/trusted_vault/securebox_unittest.cc
+++ b/components/trusted_vault/securebox_unittest.cc
@@ -25,6 +25,7 @@
using testing::Eq;
using testing::IsEmpty;
+using testing::IsNull;
using testing::Ne;
using testing::NotNull;
using testing::SizeIs;
@@ -43,6 +44,16 @@
const std::vector<uint8_t> kTestPayload = StringToBytes("TEST_PAYLOAD");
};
+TEST_F(SecureBoxTest, ShouldReturnNullIfCreateByImportWithIncorrectSize) {
+ // Sizes other than `kPublicKeyLengthInBytes` should return null.
+ EXPECT_THAT(SecureBoxPublicKey::CreateByImport(std::vector<uint8_t>(64, 1)),
+ IsNull());
+ EXPECT_THAT(SecureBoxPublicKey::CreateByImport(std::vector<uint8_t>(66, 1)),
+ IsNull());
+ EXPECT_THAT(SecureBoxPublicKey::CreateByImport(std::vector<uint8_t>()),
+ IsNull());
+}
+
TEST_F(SecureBoxTest, ShouldExportAndImportPublicKey) {
std::unique_ptr<SecureBoxKeyPair> key_pair =
SecureBoxKeyPair::GenerateRandom();
Original Bug Report
out of bound in function ECPublicKeyFromBytes
Steps to reproduce the problem
my chromim commit is 6a99accd9be43e397fe4e41571a7e1f5c656ab0d
- Apply my patch and build Chromium.(This patch only removes the account check that is unrelated to the vulnerability. Since Chromium generally does not have Chrome accounts, I have temporarily disabled it.)
- out\asan\chrome.exe –no-sandbox https://accounts.google.com/
- Enter the code in the browser’s address bar
jaavscript:let buffer = new ArrayBuffer(1);let view = new Uint8Array(buffer);view[0] = 4;chrome.addTrustedSyncEncryptionRecoveryMethod(()=>{console.log("123")},"test", buffer,2);
you will see the asan output
Problem Description
the function https://source.chromium.org/chromium/chromium/src/+/main:chrome/common/trusted_vault_encryption_keys_extension.mojom;l=28;drc=e3ad182cacc3a02eb6a13091a867815fd17a129c;bpv=0;bpt=1
AddTrustedRecoveryMethod(string gaia_id, array<uint8> public_key, int32 method_type_hint) => ();
This function receives a public_key sent from the renderer, but it does not perform any length validation. As a result, if the renderer sends malicious data, it will be passed directly to the EC_POINT_oct2point function for parsing, which leads to an out-of-bounds read.
Since the renderer parameters are not properly checked here, an exploit prerequisite is either an XSS on accounts.google.com (allowing us to execute arbitrary JavaScript), or a renderer RCE that can send arbitrary IPC messages.
let buffer = new ArrayBuffer(1);
let view = new Uint8Array(buffer);
view[0] = 4;
chrome.addTrustedSyncEncryptionRecoveryMethod(()=>{console.log("123")},"test", buffer,2);
When this JavaScript snippet is executed on the accounts.google.com page, the buffer with length 1 is passed to EC_POINT_oct2point for parsing, resulting in an out-of-bounds read in the browser process.
Summary
out of bound in function ECPublicKeyFromBytes
Custom Questions
Type of crash:
browser
Reporter credit:
raven at KunLun Lab
Additional Data
Category: Security
Chrome Channel: Not sure
Regression: N/A \