If you have any questions or feedback, pleasefill out this form
This post is translated by ChatGPT and originally written in Mandarin, so there may be some inaccuracies or mistakes.
One day while developing a page, I opened the developer tools to check if the request headers were correct, and I noticed a few suspicious headers that were added to the request:
Did you notice anything suspicious? Upon closer inspection, I found three headers starting with Sec-Fetch-*
. This caught my attention since I hadn’t set these headers or applied any other functions. I guessed that the browser might be responsible for adding them.
After doing some research on Google, I discovered that this is part of a new draft called Fetch Metadata Request Headers. Currently, only Chrome adds these headers, while Firefox and Safari do not.
A Closer Look at Same-Origin Policy (CORS)
As we know, browsers restrict access based on certain origins to prevent malicious actors from stealing your data through strange methods. For instance, when making cross-origin requests, headers like Access-Control-Allow-Origin
or Preflight requests are required. For more details, you can refer to my previous article on “Dealing with CORS and Cookies”.
Despite these measures, there are still some vulnerabilities, such as <img/>
tags being able to send cross-origin requests, allowing potential attackers to bypass CORS restrictions. However, if the server has implemented basic protective measures, it can still block most unsafe requests.
If we can include some extra header information (metadata) indicating where the request originates, the server can respond appropriately based on these headers, which led to the creation of this draft.
Header Specifications:
Currently, there are four main headers in the draft:
1. Sec-Fetch-Dest
This indicates the destination of the request.
Possible values include audio, document, font, image, object, serviceworker, and more. The advantage of having these headers is that the server can immediately determine whether the request source is legitimate. For example, if a request comes from an <img>
tag but is not requesting an image from the server, it’s likely a hacker, and we can respond with an error.
2. Sec-Fetch-Mode
This indicates the mode of the request. The main values include cors, navigate, nested-navigate, no-cors, etc., helping to determine the request's mode, similar to the mode in fetch
.
With Sec-Fetch-User
, we can also determine whether the user triggered the request through an action (like clicking or keyboard input).
3. Sec-Fetch-Site
This indicates whether the request is same-origin or cross-origin.
4. Sec-Fetch-User
This header's value is a boolean and is only true for navigation requests (where the request destination is a document) when there is user interaction (like pressing a button or using the keyboard). The server can use this header to determine if the way the user triggered the request is legitimate.
For instance, when a form is submitted via a click, since the request comes from a document and there is user interaction (clicking the submit button), Sec-Fetch-User
would be ?T
.
Is it Possible to Remove These Headers?
If this becomes part of the specifications, it might not be possible to remove them. Additionally, you cannot manually set or rewrite the values of these headers, as they belong to the forbidden headers.
Conclusion
In the past, similar objectives were achieved by using custom headers for protection, which could still be spoofed. Moreover, adding custom headers requires Preflight checks, adding extra overhead. The benefit of adhering to specifications is that these headers cannot be easily rewritten and provide a unified standard. With these headers in place, the backend can make more informed decisions upon receiving requests, thereby enhancing security.
If you found this article helpful, please consider buying me a coffee ☕ It'll make my ordinary day shine ✨
☕Buy me a coffee