One day, while developing a web page, I opened the developer tools to check if the request headers were correct. To my surprise, I noticed a few suspicious headers:
Did you notice anything suspicious? Upon closer inspection, I found three headers starting with Sec-Fetch-*
. This caught my attention because I didn't set these headers or use any other functions. I wondered why these headers were automatically added, and my guess was that it was the browser's doing.
After searching on Google, I discovered that this is a new draft called Fetch Metadata Request Headers. Currently, only Chrome adds these headers, while Firefox and Safari do not.
Discussing Cross-Origin Resource Sharing (CORS)
As we know, browsers have restrictions in place to prevent malicious individuals from accessing your data through unusual methods. For example, cross-origin requests require the addition of Access-Control-Allow-Origin
or Preflight requests. You can find more details in my previous article, "Dealing with CORS and Cookies."
Despite these measures, there are still some flaws. For instance, <img/>
tags can still make cross-origin requests, allowing malicious actors to bypass CORS restrictions. Of course, if the server has implemented basic protective measures, it can block most insecure requests.
By adding additional header information (metadata) when sending requests, servers can respond accordingly based on these headers. This gave rise to the aforementioned draft.
Header Specifications:
Currently, there are four main headers in the draft:
1. Sec-Fetch-Dest
This header indicates the destination of the request.
Possible values include audio, document, font, image, object, serviceworker, and more. With these headers, the server can quickly determine if the request source is legitimate. For example, if the source is an <img>
tag but not requesting an image from the server, it's highly likely to be a hacker, and we can respond with an error message.
2. Sec-Fetch-Mode
This header represents the mode of the request. Possible values are cors, navigate, nested-navigate, no-cors, and more, similar to the fetch
mode.
We can also determine if the request was initiated by user interaction, such as a click or keyboard input, using Set-Fetch-User
.
3. Sec-Fetch-Site
This header indicates whether the request source is same-origin or cross-origin.
4. Sec-Fetch-User
This header's value is a boolean. It is only true for navigation requests (requests that target a document) with user interaction, such as button clicks or keyboard inputs. Servers can use this header to determine the legitimacy of the user-triggered request.
For example, when submitting a form by clicking a button, since the request is sent by the document and there is user interaction (button click), Set-Fetch-User
will be ?T
.
Can the headers be removed?
If this becomes a standard, it may not be possible to remove them. Additionally, you cannot manually modify the header values as they are part of the forbidden headers.
Conclusion
In the past, similar tasks were achieved using custom headers for prevention. However, these headers could still be forged, and using custom headers required preflight checks, adding extra work. Starting from a specification has the advantage that these headers cannot be easily tampered with, and it provides a standardized approach. With these headers, the backend can make additional checks upon receiving requests, thereby enhancing security.