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 <mastiz@chromium.org>
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 <mmoskvitin@google.com>
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
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 \