CVE-2026-6313
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
forservices/network/cors/cors_url_loader_unittest.cc |
modified |
Files Changed
services/network/cors/cors_url_loader_factory.ccservices/network/cors/cors_url_loader_unittest.cc
Patch
From d513cd2fe6684b38bc02c3df59bfc5183bf4e1fd Mon Sep 17 00:00:00 2001
From: Kenichi Ishibashi <bashi@chromium.org>
Date: Fri, 10 Apr 2026 17:14:24 -0700
Subject: [PATCH] [CORS] Block forbidden methods for no-cors requests
Previously, forbidden methods like TRACE and TRACK were allowed when
the request mode was no-cors, and only CONNECT was unconditionally
blocked.
This CL updates CorsURLLoaderFactory::IsValidRequest to block all
forbidden methods regardless of the request mode. The unit test is
also updated to reflect this new restriction.
Bug: 498765210
Change-Id: Ie451a3c2b8fa7aafdebade8b3ba517be3ce255f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7743444
Reviewed-by: mmenke <mmenke@chromium.org>
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1613186}
---
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
index 6a1eb07..bf02d66 100644
--- a/services/network/cors/cors_url_loader_factory.cc
+++ b/services/network/cors/cors_url_loader_factory.cc
@@ -910,13 +910,8 @@
return false;
}
- // Don't allow forbidden methods for any requests except RequestMode::kNoCors.
- // Don't allow CONNECT method for any request.
- if ((request.mode != mojom::RequestMode::kNoCors &&
- cors::IsForbiddenMethod(request.method)) ||
- (request.mode == mojom::RequestMode::kNoCors &&
- base::EqualsCaseInsensitiveASCII(
- request.method, net::HttpRequestHeaders::kConnectMethod))) {
+ // Don't allow forbidden methods.
+ if (cors::IsForbiddenMethod(request.method)) {
mojo::ReportBadMessage("CorsURLLoaderFactory: Forbidden method");
return false;
}
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index e9bbbc2..23a9e809 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -109,11 +109,10 @@
std::string forbidden_method;
bool expect_allowed_for_no_cors;
} kTestCases[] = {
- // CONNECT is never allowed, while TRACE and TRACK are allowed only with
- // RequestMode::kNoCors.
+ // CONNECT, TRACE and TRACK are not allowed for any mode.
{"CONNECT", false},
- {"TRACE", true},
- {"TRACK", true},
+ {"TRACE", false},
+ {"TRACK", false},
};
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(test_case.forbidden_method);
Regression Test / PoC
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index e9bbbc2..23a9e809 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -109,11 +109,10 @@
std::string forbidden_method;
bool expect_allowed_for_no_cors;
} kTestCases[] = {
- // CONNECT is never allowed, while TRACE and TRACK are allowed only with
- // RequestMode::kNoCors.
+ // CONNECT, TRACE and TRACK are not allowed for any mode.
{"CONNECT", false},
- {"TRACE", true},
- {"TRACK", true},
+ {"TRACE", false},
+ {"TRACK", false},
};
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(test_case.forbidden_method);
Original Bug Report
Bypass of Site Isolation via TRACE method in kNoCors mode
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the security team.
Overview: A logic flaw in the Network Service allows a compromised renderer to bypass forbidden HTTP method checks by sending a TRACE request in kNoCors mode. This causes cross-origin SameSite=None cookies to be reflected back in the response body, which is not blocked by Opaque Response Blocking (ORB), leading to cross-origin data exfiltration.
Affected files:
services/network/cors/cors_url_loader_factory.ccservices/network/orb/orb_impl.ccservices/network/public/cpp/cors/cors.ccservices/network/orb/orb_mimetypes.cc
Estimated timestamp from git blame: 2022-02-08
Summary
A compromised renderer process can potentially exfiltrate cross-origin SameSite=None and HttpOnly cookies from any target origin that has the HTTP TRACE method enabled. This is possible due to a gap between CORS validation and Opaque Response Blocking (ORB) in the Network Service. Specifically, CorsURLLoaderFactory allows the TRACE method for requests marked with kNoCors mode, and ORB defaults to failing-open for the resulting message/http reflected response.
Vulnerability Details
1. CORS Method Validation Bypass
In Blink, the Fetch API explicitly forbids methods like TRACE (third_party/blink/renderer/core/fetch/request.cc). However, a compromised renderer can bypass Blink’s checks by directly constructing and sending a network::ResourceRequest via the network::mojom::URLLoaderFactory Mojo interface.
When the Network Service receives this request, CorsURLLoaderFactory::IsValidRequest validates it. While it normally blocks forbidden methods, there is an exception for kNoCors mode:
// services/network/cors/cors_url_loader_factory.cc:913
if ((request.mode != mojom::RequestMode::kNoCors &&
cors::IsForbiddenMethod(request.method)) ||
(request.mode == mojom::RequestMode::kNoCors &&
base::EqualsCaseInsensitiveASCII(
request.method, net::HttpRequestHeaders::kConnectMethod))) {
mojo::ReportBadMessage("CorsURLLoaderFactory: Forbidden method");
return false;
}
By setting request.mode = kNoCors, the attacker bypasses the IsForbiddenMethod check. TRACE is allowed through, and because it is kNoCors, no CORS preflight is required.
2. Credential Attachment and TRACE Reflection
If the attacker also sets request.credentials_mode = kInclude, the network stack attaches the target cross-origin server’s SameSite=None cookies to the outgoing TRACE request. (Note: SameSite=Lax/Strict cookies are protected because the request is cross-site).
The HTTP TRACE method specification requires the server to echo the received request back to the client, typically with a Content-Type: message/http. This means the SameSite=None cookies are reflected in the response body.
3. ORB Fail-Open for message/http
Because the request is a cross-origin kNoCors request, the response is routed through Opaque Response Blocking (ORB).
- MIME Type: ORB categorizes
message/httpasMimeType::kOthers. - Sniffing: The response body starts with the reflected request line (e.g.,
"TRACE / HTTP/1.1"). This does not match the blocklisted signatures for HTML, XML, or JSON, causingSniffto returnDecision::kSniffMore. - Fail-Open Decision: Once sniffing concludes,
OpaqueResponseBlockingAnalyzer::HandleEndOfSniffableResponseBodydefaults to a fail-open state, returningDecision::kAllow.
Because ORB allows the response, the original Mojo data pipe containing the full response body (with the reflected cookies) is forwarded back to the compromised renderer, allowing the attacker to read them.
Potential Reproduction Steps
Note: These are suggested steps for a proof-of-concept, as our analysis is based on static code review.
- From a compromised renderer process, obtain a
network::mojom::URLLoaderFactoryremote (e.g., the default subresource loader factory). - Call
CreateLoaderAndStartwith anetwork::ResourceRequestconfigured as follows:url:https://target-with-trace-enabled.com/method:TRACEmode:kNoCorscredentials_mode:kInclude
- Capture the response using a
network::mojom::URLLoaderClient. - Read the raw response data pipe to extract the reflected request headers, including the victim’s cross-origin cookies.
Recommended Fix
Update CorsURLLoaderFactory::IsValidRequest to block all forbidden methods regardless of the RequestMode. The exception for kNoCors is unnecessary since the web platform (Fetch/XHR) does not allow TRACE or TRACK to be used even in no-cors mode.
if (cors::IsForbiddenMethod(request.method) ||
base::EqualsCaseInsensitiveASCII(
request.method, net::HttpRequestHeaders::kConnectMethod)) {
mojo::ReportBadMessage("CorsURLLoaderFactory: Forbidden method");
return false;
}
Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.