Updates
- July 7, 2022: Updated current status and added IP address space definition.
- April 27, 2022: Updated timeline announcement.
- March 7, 2022: Announced rollback after issues were discovered in Chrome 98.
Introduction
Chrome is deprecating direct access to private network endpoints from public websites as part of the Private Network Access (PNA) specification.
Chrome will start sending a CORS preflight request ahead of any private network request for a subresource, which asks
for explicit permission from the target server. This preflight request will
carry a new header, Access-Control-Request-Private-Network: true
, and the
response to it must carry a corresponding header,
Access-Control-Allow-Private-Network: true
.
The aim is to protect users from cross-site request forgery (CSRF) attacks targeting routers and other devices on private networks. These attacks have affected hundreds of thousands of users, allowing attackers to redirect them to malicious servers.
Rollout plan
Chrome will roll this change out in two phases to give websites time to notice the change and adjust accordingly.
In Chrome 104:
- Chrome experiments by sending preflight requests ahead of private network subresource requests.
- Preflight failures only display warnings in DevTools, without otherwise affecting the private network requests.
- Chrome gathers compatibility data and reaches out to the largest affected websites.
- We expect this to be broadly compatible with existing websites.
In Chrome 113 at the earliest:
- This will begin only if and when compatibility data indicates that the change is safe enough and we've outreached directly when necessary.
- Chrome enforces that preflight requests must succeed, otherwise failing the requests.
- A deprecation trial starts at the same time to allow for websites affected by this phase to request a time extension. The trial will last for at least 6 months.
What is Private Network Access (PNA)
Private Network Access (formerly known as CORS-RFC1918) restricts the ability of websites to send requests to servers on private networks.
Chrome has already implemented part of the specification: as of Chrome 96, only secure contexts are allowed to make private network requests. Refer to our previous blog post for details.
The specification also extends the Cross-Origin Resource Sharing (CORS) protocol so that websites must now explicitly request a grant from servers on private networks before being allowed to send arbitrary requests.
How does PNA classify IP addresses and identify a private network
The IP addresses are classified into three IP address spaces:
- public
- private
- local
Local IP address space contains IP addresses that are either IPv4
loopback addresses (127.0.0.0/8
) defined in section 3.2.1.3 of RFC1122
or IPv6 loopback addresses (::1/128
) defined in section 2.5.3 of RFC4291.
Private IP address space contains IP addresses that have meaning only
within the current network, including 10.0.0.0/8
, 172.16.0.0/12
and
192.168.0.0/16
defined in RFC1918,
link-local addresses 169.254.0.0/16
defined in RFC3927,
unique local IPv6 unicast addresses fc00::/7
defined in RFC4193,
link-local IPv6 unicast addresses fe80::/10
defined in section 2.5.6 of RFC4291
and IPv4-mapped IPv6 addresses where the mapped IPv4 address is itself private.
Public IP Address space contains all other addresses not mentioned previously.
A local IP address is considered more private than a private IP address which is considered more private than a public IP address.
Learn more at Feedback wanted: CORS for private networks (RFC1918).
Preflight requests
Background
Preflight requests are a mechanism introduced by the Cross-Origin Resource Sharing (CORS) standard used to request permission from a target website before sending it an HTTP request that might have side effects. This ensures that the target server understands the CORS protocol and significantly reduces the risk of CSRF attacks.
The permission request is sent as an OPTIONS
HTTP request with specific CORS request headers
describing the upcoming HTTP request. The response must carry specific CORS response headers
explicitly agreeing to the upcoming request.
What's new in Private Network Access
A new pair of request and response headers is introduced to preflight requests:
Access-Control-Request-Private-Network: true
is set on all PNA preflight requestsAccess-Control-Allow-Private-Network: true
must be set on all PNA preflight responses
Preflight requests for PNA are sent for all private network requests,
regardless of request method and
mode. They are sent
ahead of requests in cors
mode as well as no-cors
and all other modes. This
is because all private network requests can be used for CSRF attacks,
regardless of request mode and whether or not the response contents are made
available to the initiator.
Preflight requests for PNA are also sent for same-origin requests, if the target IP address is more private than the initiator. This is unlike regular CORS, where preflight requests are only for cross-origin requests. Preflight requests for same-origin requests guard against DNS rebinding attacks.
Examples
Observable behavior depends on the request's mode.
No-CORS mode
Say https://foo.example/index.html
embeds
<img src="https://bar.example/cat.gif" alt="dancing cat"/>
, and
bar.example
resolves to 192.168.1.1
, a private IP address according to
RFC 1918.
Chrome first sends a preflight request:
HTTP/1.1 OPTIONS /cat.gif
Origin: https://foo.example
Access-Control-Request-Private-Network: true
For this request to succeed, the server must respond with:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Private-Network: true
Then Chrome will send the actual request:
HTTP/1.1 GET /cat.gif
...
To which the server can respond normally.
CORS mode
Say https://foo.example/index.html
runs the following code:
await fetch('https://bar.example/delete-everything', {
method: 'PUT',
credentials: 'include',
})
Again, say bar.example
resolves to 192.168.1.1
.
Chrome first sends a preflight request:
HTTP/1.1 OPTIONS /delete-everything
Origin: https://foo.example
Access-Control-Request-Method: PUT
Access-Control-Request-Credentials: true
Access-Control-Request-Private-Network: true
For this request to succeed, the server must respond with:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Credentials: true
Access-Control-Allow-Private-Network: true
Then Chrome will send the actual request:
HTTP/1.1 PUT /delete-everything
Origin: https://foo.example
To which the server can respond per usual CORS rules:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://foo.example
How to know if your website is affected
Starting in Chrome 104, if a private network request is detected, a preflight request will be sent ahead of it. If this preflight request fails, the final request will still be sent, but a warning will be surfaced in the DevTools issues panel.
Affected preflight requests can also be viewed and diagnosed in the network panel:
If your request would have triggered a regular CORS preflight without Private Network Access rules, then two preflights may appear in the network panel, with the first one always appearing to have failed. This is a known bug, and you can safely ignore it.
To review what happens if preflight success was enforced, you can pass the following command-line argument, starting in Chrome 98:
--enable-features=PrivateNetworkAccessRespectPreflightResults
Any failed preflight request will result in a failed fetch. This can allow you to test whether your website would work after the second phase of our rollout plan. Errors can be diagnosed in the same way as warnings using the DevTools panels mentioned above.
What to do if your website is affected
When this change rolls out in Chrome 104, it is not expected to break any website. However, we strongly encourage you to update affected request paths to ensure your website keeps running as expected.
There are two solutions available to you:
- Handle preflight requests on the server side
- Disable PNA checks with enterprise policies
Handle preflight requests server-side
Update the target server of any affected fetches to handle PNA preflight requests. First, implement support for standard CORS preflight requests on affected routes. Then add support for the two new response headers.
When your server receives a preflight request (an OPTIONS
request with CORS
headers), the server should check for the presence of an
Access-Control-Request-Private-Network: true
header. If this header is
present on the request, the server should examine the Origin
header and the
request path along with any other relevant information (such as
Access-Control-Request-Headers
) to ensure the request is safe to allow.
Typically, you should allow access to a single origin under your control.
Once your server has decided to allow the request, it should respond
204 No Content
(or 200 OK
) with the necessary CORS headers and the new PNA
header. These headers include Access-Control-Allow-Origin
and
Access-Control-Allow-Private-Network: true
, as well as others as needed.
Refer to the examples for concrete scenarios.
Disable Private Network Access checks using enterprise policies
If you have administrative control over your users, you can disable Private Network Access checks using either of the following policies:
For more information, refer to Understand Chrome policy management.
Give us feedback
If you are hosting a website within a private network that expects requests from
public networks, the Chrome team is interested in your feedback and use cases.
Let us know by filing an issue with Chromium at crbug.com and set
the component to Blink>SecurityFeature>CORS>PrivateNetworkAccess
.
What's next
Next up, Chrome will extend Private Network Access checks to cover web workers: dedicated workers, shared workers and service workers. We're tentatively aiming for Chrome 107 to begin showing warnings.
Then, Chrome will extend Private Network Access checks to cover navigations, including iframes and popups. We're tentatively aiming for Chrome 108 to start showing warnings.
In both cases, we will be proceeding cautiously with a similar phased rollout, in order to give web developers time to adjust and estimate compatibility risk.
Acknowledgements
Cover photo by Mark Olsen on Unsplash.