#49226: fix: webRequest.onBeforeSendHeaders not being able to modify reserved headers
Fix webRequest.onBeforeSendHeaders not being able to modify headers like Proxy-Authorization for requests made via the net module.
When using webRequest.onBeforeSendHeaders to inject headers like Proxy-Authorization into requests made via net.request or net.fetch, the request fails with net::ERR_INVALID_ARGUMENT. However, the same webRequest listener works correctly for renderer-initiated requests (e.g., fetch() from a BrowserWindow). The network service validates headers and headers starting with Proxy- are rejected by AreRequestHeadersSafe() in CorsURLLoaderFactory::IsValidRequest().
For renderer requests, this isn't a problem because:
- The initial request passes validation (no
Proxy-Authorizationheader yet) - Header modifications via webRequest happen through the
TrustedHeaderClientcallback, which occurs after validation - Modified headers are passed directly to the network layer, bypassing re-validation
For net module requests, the TrustedHeaderClient path was not being used because network_service_request_id was always 0. This caused header modifications to go through the FollowRedirect() path instead, which re-validates headers with AreRequestHeadersSafe() and rejects Proxy-* headers.
The condition that gates TrustedHeaderClient usage (in proxying_url_loader_factory.cc):
current_request_uses_header_client_ =
factory_->url_loader_header_client_receiver_.is_bound() &&
(for_cors_preflight_ || network_service_request_id_ != 0) &&
has_any_extra_headers_listeners_;Solution
Set a non-zero request ID for net module requests using Chromium's GlobalRequestID::MakeBrowserInitiated(). This generates unique negative request IDs (-2, -3, -4, ...) that are distinct from renderer request IDs (positive numbers). This is the same mechanism Chromium uses internally for other browser-initiated requests.
Setting Proxy-Authorization directly in the net.fetch options will still fail, as the header would be present in the initial request before validation. The header must be injected via webRequest.onBeforeSendHeaders to use the TrustedHeaderClient path.
Notes: Requests sent via net are now capable of having their headers modified to use reserved headers via webRequest
Backports
Semver Impact
Semantic Versioning helps users understand the impact of updates:
- Major (X.y.z): Breaking changes that may require code modifications
- Minor (x.Y.z): New features that maintain backward compatibility
- Patch (x.y.Z): Bug fixes that don't change the API
- None: Changes that don't affect using facing parts of Electron