CVE-2026-0905
Overview
Background
- NetLog
- Chrome’s network event log, captured through
chrome://net-exportor the--log-net-logswitch. It is often shared with developers or support for debugging, and itscapture_modedecides whether sensitive data such as cookies and credentials is included. - `net::NetLogCaptureMode`
- the capture level that logging helpers check to decide whether to strip privacy- or security-sensitive values. The default mode is meant to exclude them.
- `HttpRequestHeaders::NetLogParams`
- the standard helper for logging request headers. It takes a request line and the
capture_modeand elides sensitive header values (for example, authentication and cookie headers) unless the capture mode allows them. - `CorsURLLoader`
- the Network Service loader in
services/network/cors/cors_url_loader.ccthat enforces CORS and emits NetLog events describing the request, including preflight-related parameters.
Root Cause Analysis
In services/network/cors/cors_url_loader.cc, a NetLog parameter builder logged the request’s headers with net::NetLogStringValue(request.headers.ToString()). The builder is the function that ends just before NetLogPreflightRequiredParams; its name is not shown in the hunk. That serialises every header verbatim regardless of capture_mode, while the URL in the same dictionary was already passed through SanitizeUrlForNetLog(request.url, capture_mode). This broke the rule that NetLog output in a non-sensitive capture mode must not contain secrets, so header values that other request-header logging elides, such as credentials or cookies, were written into the log in plain text. The commit message says the purpose is “to have the same eliding as other request headers logging”.
The fix removes the raw headers and method fields. When request.url.is_valid(), it builds a request line with net::HttpUtil::GenerateRequestLine and logs request.headers.NetLogParams(request_line, capture_mode) under request_headers, which applies the capture-mode-dependent eliding. This tightens what gets logged; CORS enforcement itself does not change.
ToString() and bypassed the capture_mode-aware eliding used everywhere else for request headers. Switching to HttpRequestHeaders::NetLogParams brings the CORS path into line with the standard sensitive-header stripping.Attack Path
- Sensitive headers on a CORS-mode request
A request goes through
CorsURLLoadercarrying sensitive headers, such as anAuthorizationheader set by a page (inferred: the diff does not name specific headers). - NetLog capture is active
The user (or an administrator or support flow) records a NetLog with a default, non-sensitive capture mode, for example through
chrome://net-export. - Headers logged verbatim
Before the fix, the CORS loader’s NetLog params included
request.headers.ToString()in full, without the eliding thatcapture_modewould otherwise apply. - Log is shared The user sends the log file, which they believe has secrets stripped, to a third party, who can then read the credentials or session tokens in it (inferred).
Impact Assessment
chrome://net-export or a command-line flag. Exposure also requires the resulting log to reach someone else. Ordinary web content alone cannot read the log. Any account takeover from leaked credentials is (inferred). The vendor rates it medium severity (“Insufficient policy enforcement in Network”). The advisory text given here says nothing about in-the-wild exploitation.Files Changed
services/network/cors/cors_url_loader.cc
Audit Directions
- Raw header serialisation into logsSearch for
NetLogStringValue(...ToString()),HttpRequestHeaders::ToString()andHttpResponseHeadersraw dumps passed to NetLog or other diagnostics, and check that they go throughNetLogParamsorElideHeaderValueForNetLogwith the activecapture_mode. - Partially sanitised log dictionariesLook for NetLog params that sanitise one field (such as the URL through
SanitizeUrlForNetLog) but not others in the same dictionary, especially in Network Service components like CORS, preflight, Private Network Access and trust-token loaders. - Other diagnostic sinksReview DevTools protocol events, crash keys and
chrome://debugging pages that echo request or response headers, and confirm they apply the same sensitive-header policy as NetLog.
Patch
From 0f08f8e435a81e6d3e8442715a195d5efbe00ac5 Mon Sep 17 00:00:00 2001
From: Kenichi Ishibashi <bashi@chromium.org>
Date: Wed, 03 Dec 2025 23:52:59 -0800
Subject: [PATCH] Use HttpRequestHeaders::NetLogParams() for CORS preflight request netlog
To have the same eliding as other request headers logging.
Bug: 465466773
Change-Id: I1476d57902c3430c8698b68af849c8d52b1fb8ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7226493
Reviewed-by: mmenke <mmenke@chromium.org>
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1553835}
---
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index 119edf0..6bc7eff 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -23,7 +23,9 @@
#include "net/cookies/cookie_partition_key.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/cookies/cookie_util.h"
+#include "net/http/http_log_util.h"
#include "net/http/http_status_code.h"
+#include "net/http/http_util.h"
#include "net/log/net_log_util.h"
#include "net/log/net_log_values.h"
#include "net/shared_dictionary/shared_dictionary.h"
@@ -113,12 +115,18 @@
break;
}
- return base::Value::Dict()
- .Set("url", SanitizeUrlForNetLog(request.url, capture_mode))
- .Set("method", request.method)
- .Set("headers", net::NetLogStringValue(request.headers.ToString()))
- .Set("is_revalidating", request.is_revalidating)
- .Set("cors_preflight_policy", cors_preflight_policy);
+ auto params = base::Value::Dict()
+ .Set("url", SanitizeUrlForNetLog(request.url, capture_mode))
+ .Set("is_revalidating", request.is_revalidating)
+ .Set("cors_preflight_policy", cors_preflight_policy);
+
+ if (request.url.is_valid()) {
+ std::string request_line = net::HttpUtil::GenerateRequestLine(
+ request.method, request.url, /*is_for_get_to_http_proxy=*/false);
+ params.Set("request_headers",
+ request.headers.NetLogParams(request_line, capture_mode));
+ }
+ return params;
}
base::Value::Dict NetLogPreflightRequiredParams(
Original Bug Report
NetLog: Unredacted sensitive credential in CORS Preflight Request Header
Security Bug
In chrome://net-export -> "Strip private information" mode, I found that the header of CORS Preflight requests contain credentials, e.g., Chrome Sync OAuth token:
https://screenshot.googleplex.com/C6zW7g32E4bHuE4
Related code:
I imagine this information should be stripped away with NetLogRequestHeaders.
VERSION
- Chrome Version:
- Linux: 142.0.7444.175 stable
- MacOS arm64: 142.0.7444.177 stable
- Operating System: Tested on
- gLinux: Linux 6.16.12-1rodete1-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.16.12-1rodete1 (2025-10-16) x86_64 GNU/Linux
- MacOS: Darwin 24.6.0 Darwin Kernel Version 24.6.0: Wed Oct 15 21:09:41 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T8122 arm64
REPRODUCTION CASE
Go to chrome://net-export and record network traffic with the “Strip private information” option.
- https://screenshot.googleplex.com/C6zW7g32E4bHuE4
- https://source.corp.google.com/h/chromium/chromium/src/+/main:net/http/http_log_util.cc;l=92;drc=06357132454006fec1dcd78fdcf39b7984054969
- https://source.corp.google.com/h/chromium/chromium/src/+/main:net/log/net_log_event_type_list.h;l=4756-4770;drc=b2e15604bc4b83b055200f1fd0b3105adf2c9929
- https://source.corp.google.com/h/chromium/chromium/src/+/main:services/network/cors/cors_url_loader.cc;l=103;drc=06357132454006fec1dcd78fdcf39b7984054969
- https://source.corp.google.com/h/chromium/chromium/src/+/main:services/network/cors/cors_url_loader.cc;l=119;drc=06357132454006fec1dcd78fdcf39b7984054969