Chrome · DeviceBoundSessionCredentials
CVE-2026-87449
Logic Error in DeviceBoundSessionCredentials
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
net/device_bound_sessions/registration_fetcher.cc
Patch
From 6dce8e75d9b25edc36726a8b58ac63b81bfe8a13 Mon Sep 17 00:00:00 2001 From: Ali Hijazi <[email protected]> Date: Sat, 15 Aug 2026 08:55:16 -0700 Subject: [PATCH] [DBSC] Enforce Fetch-Metadata and secure redirects Network fetches for Device Bound Session Credentials (DBSC) bypass the network::URLLoader, which ordinarily injects standard W3C Fetch-Metadata headers. Without explicit metadata decoration, outgoing Discovery, Registration, and Refresh requests lacked `Origin`, `Sec-Fetch-Mode`, `Sec-Fetch-Dest`, and `Sec-Fetch-Site` assertions. Furthermore, `URLFetcher`'s redirect handling previously allowed unvalidated HTTP 3xx protocol downgrades (exposing DBSC cryptographic tokens and session cookies to plaintext leakage) and failed to synchronize `Sec-Fetch-Site` metadata upon traversing same-site or cross-origin redirect boundaries. - Installs W3C Resource-Isolation headers (`no-cors`, `empty`, `Origin`, and `Sec-Fetch-Site`) across all Discovery and Registration/Refresh pipelines. - Implements rigorous redirect defenses in `URLFetcher::OnReceivedRedirect`: * Aborts plaintext (HTTP) protocol-downgrade transitions via `net::ERR_UNSAFE_REDIRECT`, neutralizing token-leakage risks. * Dynamically re-calculates and mutates `Sec-Fetch-Site` header values at each redirect hop relative to the baseline `referring_origin`. Bug: 501850947 Change-Id: I8a2ea35547d58567f9551e2557b61fcd2951cfef Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8139249 Reviewed-by: Adam Rice <[email protected]> Commit-Queue: Ali Hijazi <[email protected]> Cr-Commit-Position: refs/heads/main@{#1680192} --- diff --git a/net/device_bound_sessions/registration_fetcher.cc b/net/device_bound_sessions/registration_fetcher.cc index efe2d49..1ad0ee2 100644 --- a/net/device_bound_sessions/registration_fetcher.cc +++ b/net/device_bound_sessions/registration_fetcher.cc @@ -16,6 +16,7 @@ #include "base/functional/callback_helpers.h" #include "base/functional/concurrent_closures.h" #include "base/metrics/histogram_functions.h" +#include "base/notreached.h" #include "base/rand_util.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" @@ -27,6 +28,7 @@ #include "net/base/features.h" #include "net/base/net_errors.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "net/base/url_util.h" #include "net/device_bound_sessions/registration_request_param.h" #include "net/device_bound_sessions/session_binding_utils.h" #include "net/device_bound_sessions/session_challenge_param.h" @@ -35,6 +37,7 @@ #include "net/device_bound_sessions/session_key.h" #include "net/device_bound_sessions/session_params.h" #include "net/device_bound_sessions/url_fetcher.h" +#include "net/http/http_request_headers.h" #include "net/log/net_log_event_type.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context.h" @@ -205,6 +208,7 @@ public: RegistrationFetcherImpl( const GURL& fetcher_endpoint, + url::Origin referring_origin, std::optional<std::string> session_identifier, SessionService& session_service, unexportable_keys::UnexportableKeyService& key_service, @@ -215,6 +219,7 @@ const std::optional<url::Origin>& original_request_initiator, unexportable_keys::BackgroundTaskPriority priority) : fetcher_endpoint_(fetcher_endpoint), + referring_origin_(std::move(referring_origin)), session_identifier_(std::move(session_identifier)), session_service_(session_service), key_service_(key_service), @@ -374,13 +379,9 @@ // TODO(crbug.com/495096658): Assert that `IsForRefreshRequest()` is false // once the tests are fixed. url_fetcher_ = std::make_unique<URLFetcher>( - context_, well_known_url, net_log_source_, IsForRefreshRequest()); - url_fetcher_->request().set_method("GET"); - url_fetcher_->request().set_disallow_credentials(); - url_fetcher_->request().set_site_for_cookies( - isolation_info_.site_for_cookies()); - url_fetcher_->request().set_initiator(original_request_initiator_); - url_fetcher_->request().set_isolation_info(isolation_info_); + context_, well_known_url, referring_origin_, net_log_source_, + IsForRefreshRequest()); + ConfigureWellKnownRequest(url_fetcher_->request()); url_fetcher_->Start(base::BindOnce( &RegistrationFetcherImpl::OnProviderWellKnownRequestComplete, GetWeakPtr(), request_params.TakeChallenge(), @@ -409,9 +410,40 @@ } private: + // Consolidates common URLRequest initialization, credential isolation, and + // W3C Resource-Isolation 'no-cors'/'empty' Fetch-Metadata parameters utilized + // uniformly across both Discovery (GET) and Registration (POST) DBSC + // operations. + // TODO(crbug.com/546625323): Stop duplicating request header and + // Fetch-Metadata population logic, and explore offloading header construction + // to `SessionService` or reusing `//services/network/sec_header_helpers.h`. + void SetupCommonFetchMetadata(URLRequest& request) { + request.set_site_for_cookies(site_for_cookies_); + request.set_initiator(original_request_initiator_); + request.set_isolation_info(isolation_info_); + + request.SetExtraRequestHeaderByName(kSecFetchModeHeaderName, "no-cors", + /*overwrite=*/true); + request.SetExtraRequestHeaderByName(kSecFetchDestHeaderName, "empty", + /*overwrite=*/true); + request.SetExtraRequestHeaderByName( + kSecFetchSiteHeaderName, + SecFetchSiteForReferringOrigin(referring_origin_, request.url()), + /*overwrite=*/true); + } + + // Configures and decorates an outbound `.well-known` DBSC discovery + // URLRequest via a side-effect-free, credentialless HTTP GET operation. + void ConfigureWellKnownRequest(URLRequest& request) { + request.set_method("GET"); + request.set_disallow_credentials(); + SetupCommonFetchMetadata(request); + } + void StartFetcherEndpointRequest() { url_fetcher_ = std::make_unique<URLFetcher>( - context_, fetcher_endpoint_, net_log_source_, IsForRefreshRequest()); + context_, fetcher_endpoint_, referring_origin_, net_log_source_, + IsForRefreshRequest()); ConfigureRequest(url_fetcher_->request()); if (last_registration_token_.has_value()) { url_fetcher_->request().SetExtraRequestHeaderByName( @@ -438,13 +470,9 @@ replacements.SetPathStr("/.well-known/device-bound-sessions"); GURL well_known_url = fetcher_endpoint_.ReplaceComponents(replacements); url_fetcher_ = std::make_unique<URLFetcher>( - context_, well_known_url, net_log_source_, IsForRefreshRequest()); - url_fetcher_->request().set_method("GET"); - url_fetcher_->request().set_disallow_credentials(); - url_fetcher_->request().set_site_for_cookies( - isolation_info_.site_for_cookies()); - url_fetcher_->request().set_initiator(original_request_initiator_); - url_fetcher_->request().set_isolation_info(isolation_info_); + context_, well_known_url, referring_origin_, net_log_source_, + IsForRefreshRequest()); + ConfigureWellKnownRequest(url_fetcher_->request()); url_fetcher_->Start(base::BindOnce( &RegistrationFetcherImpl::OnRelyingPartyWellKnownRequestComplete, GetWeakPtr(), std::move(challenge), std::move(authorization))); @@ -624,9 +652,17 @@ request.set_method("POST"); request.SetLoadFlags(LOAD_DISABLE_CACHE); - request.set_site_for_cookies(site_for_cookies_); - request.set_initiator(original_request_initiator_); - request.set_isolation_info(isolation_info_); + // Apply baseline W3C Fetch-Metadata ('no-cors', 'empty', 'Sec-Fetch-Site') + // and isolation boundaries utilized across all DBSC request pipelines. + SetupCommonFetchMetadata(request); + + // The endpoint may be a different (same-site) origin from the response or + // session that configured it, so attach `Origin` and Fetch Metadata + // headers reflecting that relationship. These requests don't go through + // `network::URLLoader`, which would otherwise add them. + request.SetExtraRequestHeaderByName(HttpRequestHeaders::kOrigin, + referring_origin_.Serialize(), + /*overwrite=*/true); if (IsForRefreshRequest()) { request.SetExtraRequestHeaderByName( @@ -808,13 +844,9 @@ GURL well_known_url = fetcher_endpoint_.ReplaceComponents(std::move(replacements)); url_fetcher_ = std::make_unique<URLFetcher>( - context_, well_known_url, net_log_source_, /*is_refresh=*/false); - url_fetcher_->request().set_method("GET"); - url_fetcher_->request().set_disallow_credentials(); - url_fetcher_->request().set_site_for_cookies( - isolation_info_.site_for_cookies()); - url_fetcher_->request().set_initiator(original_request_initiator_); - url_fetcher_->request().set_isolation_info(isolation_info_); + context_, well_known_url, referring_origin_, net_log_source_, + /*is_refresh=*/false); + ConfigureWellKnownRequest(url_fetcher_->request()); url_fetcher_->Start(base::BindOnce( &RegistrationFetcherImpl:: OnSubdomainRegistrationWellKnownRequestComplete, @@ -927,6 +959,10 @@ // Refers to the endpoint this class will use when triggering a registration // or refresh request. GURL fetcher_endpoint_; + // The origin that configured `fetcher_endpoint_`: the origin of the response + // carrying the registration header, or the scope origin of the session being + // refreshed. + url::Origin referring_origin_; // Populated iff this is a refresh request (not a registration request). std::optional<std::string> session_identifier_;
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/net/device_bound_sessions/registration_fetcher_param_unittest.cc b/net/device_bound_sessions/registration_fetcher_param_unittest.cc
index 5e21cb3..ddc297c 100644
--- a/net/device_bound_sessions/registration_fetcher_param_unittest.cc
+++ b/net/device_bound_sessions/registration_fetcher_param_unittest.cc
@@ -64,6 +64,8 @@
const auto& param = params[0];
EXPECT_EQ(param.registration_endpoint(),
GURL("https://www.example.com/startsession"));
+ EXPECT_EQ(param.referring_origin(),
+ url::Origin::Create(registration_request));
EXPECT_THAT(param.supported_algos(),
UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
EXPECT_EQ(param.challenge(), "c1");
@@ -471,6 +473,8 @@
const auto& param = params[0];
EXPECT_EQ(param.registration_endpoint(),
GURL("https://accounts.example.com/startsession"));
+ EXPECT_EQ(param.referring_origin(),
+ url::Origin::Create(registration_request));
EXPECT_THAT(param.supported_algos(),
UnorderedElementsAre(ECDSA_SHA256, RSA_PKCS1_SHA256));
EXPECT_EQ(param.challenge(), "c1");
diff --git a/net/device_bound_sessions/registration_fetcher_unittest.cc b/net/device_bound_sessions/registration_fetcher_unittest.cc
index f053118..314ad00f 100644
--- a/net/device_bound_sessions/registration_fetcher_unittest.cc
+++ b/net/device_bound_sessions/registration_fetcher_unittest.cc
@@ -72,11 +72,13 @@
using ::base::test::ValueIs;
using ::testing::_;
using ::testing::AllOf;
+using ::testing::Contains;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Invoke;
using ::testing::Not;
using ::testing::Optional;
+using ::testing::Pair;
using ::testing::Property;
using ::testing::Return;
using ::testing::WithArg;
@@ -211,7 +213,6 @@
context_ = context_builder->Build();
}
-
unexportable_keys::UnexportableKeyService& unexportable_key_service() {
return unexportable_key_service_;
}
@@ -1941,6 +1942,123 @@
"auth_cookie", "Domain=.a.test; Path=/; Secure; SameSite=None")));
}
+std::unique_ptr<test_server::HttpResponse> CaptureFetchMetadataHeaders(
+ test_server::HttpRequest::HeaderMap* out_headers,
+ const test_server::HttpRequest& request) {
+ for (const char* name :
+ {"Origin", "Sec-Fetch-Site", "Sec-Fetch-Mode", "Sec-Fetch-Dest"}) {
+ auto it = request.headers.find(name);
+ if (it != request.headers.end()) {
+ (*out_headers)[name] = it->second;
+ }
+ }
+ return ReturnResponse(HTTP_OK, kBasicValidJson, request);
+}
+
+TEST_F(RegistrationTest, RefreshSendsOriginAndFetchMetadata) {
+ crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
+ test_server::HttpRequest::HeaderMap received_headers;
+ server_.RegisterRequestHandler(base::BindRepeating(
+ &CaptureFetchMetadataHeaders, base::Unretained(&received_headers)));
+ ASSERT_TRUE(server_.Start());
+
+ TestRegistrationCallback callback;
+ auto isolation_info = IsolationInfo::CreateTransient(/*nonce=*/std::nullopt);
+ auto request_param = RegistrationRequestParam::CreateForTesting(
+ GetBaseURL(), kSessionIdentifier, kChallenge,
+ /*authorization=*/std::nullopt);
+ UnexportableSigningKeyId key = CreateSigningKey();
+ std::unique_ptr<RegistrationFetcher> fetcher =
+ RegistrationFetcher::CreateFetcher(
+ request_param, session_service(),
+ std::ref(unexportable_key_service()), context_.get(),
+ std::ref(isolation_info), net::SiteForCookies(),
+ /*net_log_source=*/std::nullopt,
+ /*original_request_initiator=*/std::nullopt,
+ unexportable_keys::BackgroundTaskPriority::kBestEffort);
+ fetcher->StartFetchWithExistingKey(request_param, std::move(key),
+ callback.callback());
+ callback.WaitForCall();
+ callback.outcome().SessionForTesting();
+
+ EXPECT_THAT(
+ received_headers,
+ Contains(Pair("Origin", url::Origin::Create(GetBaseURL()).Serialize())));
+ EXPECT_THAT(received_headers,
+ Contains(Pair("Sec-Fetch-Site", "same-origin")));
+ EXPECT_THAT(received_headers, Contains(Pair("Sec-Fetch-Mode", "no-cors")));
+ EXPECT_THAT(received_headers, Contains(Pair("Sec-Fetch-Dest", "empty")));
+}
+
+TEST_F(RegistrationTest, RefreshSendsSameSiteFetchMetadataForCrossOrigin) {
+ crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
+ test_server::HttpRequest::HeaderMap received_headers;
+ server_.RegisterRequestHandler(base::BindRepeating(
+ &CaptureFetchMetadataHeaders, base::Unretained(&received_headers)));
+ ASSERT_TRUE(server_.Start());
+
+ // The session is scoped to a sibling origin within the same site as the
+ // refresh endpoint.
+ url::Origin scope_origin =
+ url::Origin::Create(server_.GetURL("other.a.test", "/"));
+
+ TestRegistrationCallback callback;
+ auto isolation_info = IsolationInfo::CreateTransient(/*nonce=*/std::nullopt);
+ auto request_param = RegistrationRequestParam::CreateForTesting(
+ GetBaseURL(), kSessionIdentifier, kChallenge,
+ /*authorization=*/std::nullopt, AttestationMode::kNone, scope_origin);
+ UnexportableSigningKeyId key = CreateSigningKey();
+ std::unique_ptr<RegistrationFetcher> fetcher =
+ RegistrationFetcher::CreateFetcher(
+ request_param, session_service(),
+ std::ref(unexportable_key_service()), context_.get(),
+ std::ref(isolation_info), net::SiteForCookies(),
+ /*net_log_source=*/std::nullopt,
+ /*original_request_initiator=*/std::nullopt,
+ unexportable_keys::BackgroundTaskPriority::kBestEffort);
+ fetcher->StartFetchWithExistingKey(request_param, std::move(key),
+ callback.callback());
+ callback.WaitForCall();
+ callback.outcome().SessionForTesting();
+
+ EXPECT_THAT(received_headers,
+ Contains(Pair("Origin", scope_origin.Serialize())));
+ EXPECT_THAT(received_headers, Contains(Pair("Sec-Fetch-Site", "same-site")));
+ EXPECT_THAT(received_headers, Contains(Pair("Sec-Fetch-Mode", "no-cors")));
+ EXPECT_THAT(received_headers, Contains(Pair("Sec-Fetch-Dest", "empty")));
+}
+
+TEST_F(RegistrationTest, RegistrationSendsOriginAndFetchMetadata) {
+ crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
+ test_server::HttpRequest::HeaderMap received_headers;
+ server_.RegisterRequestHandler(base::BindRepeating(
+ &CaptureFetchMetadataHeaders, base::Unretained(&received_headers)));
+ ASSERT_TRUE(server_.Start());
+
+ TestRegistrationCallback callback;
+ auto param = GetBasicParam();
+ std::unique_ptr<RegistrationFetcher> fetcher =
+ RegistrationFetcher::CreateFetcher(
+ param, session_service(), unexportable_key_service(), context_.get(),
+ IsolationInfo::CreateTransient(/*nonce=*/std::nullopt),
+ net::SiteForCookies(),
+ /*net_log_source=*/std::nullopt,
+ /*original_request_initiator=*/std::nullopt,
+ unexportable_keys::BackgroundTaskPriority::kBestEffort);
+ fetcher->StartCreateTokenAndFetch(param, CreateAlgArray(),
+ callback.callback());
+ callback.WaitForCall();
+ callback.outcome().SessionForTesting();
+
+ EXPECT_THAT(
+ received_headers,
+ Contains(Pair("Origin", url::Origin::Create(GetBaseURL()).Serialize())));
+ EXPECT_THAT(received_headers,
+ Contains(Pair("Sec-Fetch-Site", "same-origin")));
+ EXPECT_THAT(received_headers, Contains(Pair("Sec-Fetch-Mode", "no-cors")));
+ EXPECT_THAT(received_headers, Contains(Pair("Sec-Fetch-Dest", "empty")));
+}
+
TEST_F(RegistrationTest, FetchRegistrationAndChallengeRequired) {
crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
server_.RegisterRequestHandler(base::BindRepeating(&ReturnForbidden));
@@ -3038,6 +3156,93 @@
SessionError::kSubdomainRegistrationWellKnownUnavailable);
}
+TEST_F(RegistrationTest, FederatedWellKnownDiscoverySendsFetchMetadata) {
+ crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
+
+ test_server::HttpRequest::HeaderMap captured_headers;
+ bool well_known_fetched = false;
+
+ // 1. Initial Endpoint Response: Instruct the Fetcher to redirect onto a
+ // Subdomain scope, implicitly triggering the DBSC cross-origin .well-known
+ // verification pipeline.
+ server_.RegisterRequestHandler(base::BindLambdaForTesting(
+ [&](const test_server::HttpRequest& request)
+ -> std::unique_ptr<test_server::HttpResponse> {
+ if (request.relative_url != "/") {
+ return nullptr;
+ }
+ auto response = std::make_unique<test_server::BasicHttpResponse>();
+ response->set_code(HTTP_FOUND);
+ response->AddCustomHeader(
+ "Location", server_.GetURL("subdomain.a.test", "/dbsc").spec());
+ return response;
+ }));
+
+ // 2. Mock Config Delivery for the Subdomain path.
+ server_.RegisterRequestHandler(base::BindLambdaForTesting(
+ [&](const test_server::HttpRequest& request)
+ -> std::unique_ptr<test_server::HttpResponse> {
+ if (request.relative_url != "/dbsc") {
+ return nullptr;
+ }
+ return ReturnResponse(HTTP_OK, kBasicValidJson, request);
+ }));
+
+ // 3. .well-known Interceptor: Capture the outbound GET metadata for the
+ // cross-origin validation check.
+ server_.RegisterRequestHandler(base::BindLambdaForTesting(
+ [&](const test_server::HttpRequest& request)
+ -> std::unique_ptr<test_server::HttpResponse> {
+ if (request.relative_url != "/.well-known/device-bound-sessions") {
+ return nullptr;
+ }
+
+ for (const char* name :
+ {"Sec-Fetch-Site", "Sec-Fetch-Mode", "Sec-Fetch-Dest"}) {
+ auto it = request.headers.find(name);
+ if (it != request.headers.end()) {
+ captured_headers[name] = it->second;
+ }
+ }
+
+ well_known_fetched = true;
+ // Yield a 404 to cleanly isolate the test strictly to the pre-flight
+ // discovery dispatch.
+ return ReturnResponse(HTTP_NOT_FOUND, "", request);
+ }));
+
+ ASSERT_TRUE(server_.Start());
+
+ GURL registration_url = server_.GetURL("a.test", "/");
+ TestRegistrationCallback callback;
+
+ // Trigger Subdomain Cross-Origin Registration, implicitly firing the
+ // .well-known discovery step on the server-bound origin.
+ auto param = GetBasicParam(registration_url);
+ std::unique_ptr<RegistrationFetcher> fetcher =
+ RegistrationFetcher::CreateFetcher(
+ param, session_service(), unexportable_key_service(), context_.get(),
+ IsolationInfo::CreateTransient(/*nonce=*/std::nullopt),
+ net::SiteForCookies(),
+ /*net_log_source=*/std::nullopt,
+ /*original_request_initiator=*/std::nullopt,
+ unexportable_keys::BackgroundTaskPriority::kBestEffort);
+ fetcher->StartCreateTokenAndFetch(param, CreateAlgArray(),
+ callback.callback());
+ callback.WaitForCall();
+
+ // 1. Assert the .well-known validator was indeed engaged by the DBSC
+ // state-machine.
+ EXPECT_TRUE(well_known_fetched);
+
+ // 2. Validate that our ConfigureWellKnownRequest pipeline successfully
+ // computed and appended W3C 'no-cors', 'empty', and Origin-relative Metadata.
+ EXPECT_THAT(captured_headers, Contains(Pair("Sec-Fetch-Mode", "no-cors")));
+ EXPECT_THAT(captured_headers, Contains(Pair("Sec-Fetch-Dest", "empty")));
+ EXPECT_THAT(captured_headers,
+ Contains(Pair("Sec-Fetch-Site", "same-origin")));
+}
+
TEST_F(RegistrationTest, FederatedSuccess) {
crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
diff --git a/net/device_bound_sessions/session_binding_utils_unittest.cc b/net/device_bound_sessions/session_binding_utils_unittest.cc
index b2a982f..a88c193 100644
--- a/net/device_bound_sessions/session_binding_utils_unittest.cc
+++ b/net/device_bound_sessions/session_binding_utils_unittest.cc
@@ -22,6 +22,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace net::device_bound_sessions {
@@ -336,4 +337,37 @@
std::nullopt);
}
+TEST(SessionBindingUtilsTest, SecFetchSiteForReferringOrigin) {
+ // Validate that W3C Sec-Fetch-Site string-literal translation correctly
+ // resolves 'same-origin', 'same-site', and 'cross-site' origin relationships,
+ // including strictness against unencrypted/HTTP protocol-mismatches.
+ url::Origin referring_origin =
+ url::Origin::Create(GURL("https://www.example.com"));
+
+ // 1. Same-Origin: Matching cryptographic scheme, eTLD+1, and subdomain.
+ EXPECT_EQ(
+ SecFetchSiteForReferringOrigin(
+ referring_origin, GURL("https://www.example.com/path/to/resource")),
+ "same-origin");
+
+ // 2. Same-Site: Matching cryptographic scheme and eTLD+1, but differing
+ // subdomain boundaries.
+ EXPECT_EQ(
+ SecFetchSiteForReferringOrigin(
+ referring_origin, GURL("https://subdomain.example.com/endpoint")),
+ "same-site");
... (truncated)
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page