-
Notifications
You must be signed in to change notification settings - Fork 23
Description
Hello!
I've identified a critical deviation from real browser behavior regarding how the Sec-Fetch-User header is generated. This discrepancy can signal to sophisticated bot detection systems that a request is automated.
The Problem: Incorrect Sec-Fetch-User Generation
The core of the issue is that impit unconditionally adds the Sec-Fetch-User: ?1 header to navigation-style requests. However, according to web standards, this header has a very specific meaning and should be omitted in most cases.
As stated in the MDN documentation, which reflects the Fetch standard:
The value will always be
?1. When a request is triggered by something other than a user activation, the spec requires browsers to omit the header completely.— MDN Web Docs on
Sec-Fetch-User
This means the header should only be present for navigations directly initiated by a user, such as clicking a link or typing a URL in the address bar. For all other requests, including loading subresources like iframes, images, scripts, or stylesheets, this header must be absent.
How to Reproduce
The issue can be easily observed by simulating a request for an iframe, which is not a direct user activation.
import { Impit } from 'impit';
const impit = new Impit({ browser: 'chrome' });
const response = await impit.fetch('https://httpbin.org/headers', {
headers: {
// Headers indicating a cross-site iframe navigation
"Sec-Fetch-Dest": "iframe",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "cross-site",
"Referer": "https://an-example-site.com/",
},
});
const data = await response.json();
console.log('Sec-Fetch-User:', data.headers['Sec-Fetch-User']); Actual Result
The Sec-Fetch-User header is present with the value ?1.
{
"headers": {
"Sec-Fetch-Dest": "iframe",
"Sec-Fetch-User": "?1", // <-- This is incorrect and violates the spec
"..."
}
}Expected Result
The Sec-Fetch-User header should be completely absent from the request.
Scope of the Issue: A Comprehensive Rule
The problem is not limited to iframe. It applies to any request that is not a user-activated, top-level navigation. The Sec-Fetch-Dest header provides the necessary context to make the correct decision.
Here is a clear rule based on browser behavior:
-
Sec-Fetch-User: ?1SHOULD be sent only whenSec-Fetch-Destisdocument,frame, orfencedframe, as these represent top-level document navigations that are typically user-initiated. -
Sec-Fetch-UserSHOULD BE OMITTED for all other destinations. This includes, but is not limited to:- Embedded content:
iframe,embed,object - Subresources:
script,style,image,font,video,audio,track - Workers & Worklets:
worker,sharedworker,serviceworker,audioworklet - API calls:
empty(forfetch()) - Other:
manifest,report,xslt, etc.
- Embedded content:
By default, impit adds the header for many of these, creating an easily detectable fingerprinting flaw.
Why This Is a Critical Issue
- Violation of Web Standards: The current behavior directly contradicts the Fetch specification, making the generated requests non-compliant.
- Bot Detection: Advanced WAFs and bot detection systems (Cloudflare, Akamai, etc.) analyze the logical consistency of Fetch Metadata. A request for an image (
Sec-Fetch-Dest: image) with aSec-Fetch-User: ?1header is an impossible combination for a real browser and a strong, definitive signal of automation. - Inability to Correct: This behavior cannot be fixed by the user. Setting
"Sec-Fetch-User": undefinedcauses a crash, and setting it to another value is still incorrect. The library must handle the omission of the header correctly.
Proposed Solution
The library's internal header generation logic should be updated to respect the context provided by Sec-Fetch-Dest.
Suggested Logic:
Before sending a request, the logic for adding default headers should be as follows:
- Check the user-provided
Sec-Fetch-Destheader (or the one inferred byimpit). - Only if
Sec-Fetch-Destis one ofdocument,frame, orfencedframe, should the library addSec-Fetch-User: ?1(if it wasn't already provided by the user). - For all other values of
Sec-Fetch-Dest, theSec-Fetch-Userheader must not be added.
This change would align impit's behavior with web standards, drastically improving its stealth and the authenticity of the browser fingerprints it generates.
Thank you for your time and for maintaining this valuable project.