BrowserGate claims LinkedIn secretly fingerprints users via extensions and device data, sending encrypted results to third parties for tracking.
BrowserGate is an investigation conducted by Fairlinked (https://browsergate.eu/), an association of commercial LinkedIn users, which documents what it describes as one of the largest data breach and corporate espionage scandals in digital history. The central thesis: every time one of the billions of users visits linkedin.com, hidden code scans the computer for installed software, collects the results, and transmits them to LinkedIn servers and third-party companies, including a US-Israeli cybersecurity firm.
The user is never informed nor asked for consent. LinkedIn’s privacy policy makes no mention of it.
Technical Architecture of the Attack
The system consists of three cooperating modules within a single JavaScript bundle (Webpack chunk.905, ~2.7 MB, Ember.js framework):
| System | Internal Name | Function |
| APFC / DNA | triggerApfc, triggerDnaApfcEvent | Device fingerprinting: 48 browser characteristics |
| AED | AedEvent, fetchExtensions | Active extension scanning via fetch() |
| Spectroscopy | SpectroscopyEvent, scanDOMForPrefix | Passive DOM scanning |
Stage 1 — Active Extension Detection (AED)
Inside Webpack module 75023, there is a hardcoded array with entries in the form {id: “…”, file: “…”} where id is the Chrome Web Store extension ID and file is a path to an internal extension resource declared as web-accessible.
The probing mechanism:
Chrome extensions can expose internal files to web pages through the web_accessible_resources field in their manifest.json. When an extension is installed and has exposed a resource, a fetch() request to chrome-extension://{id}/{file} will succeed. When it is not installed, Chrome blocks the request and the promise is rejected.
Method 1 — Parallel batch scan: All fetch() requests are launched simultaneously via Promise.allSettled(). Each request that resolves as “fulfilled” indicates that extension is installed.
Method 2 — Staggered sequential scan: An alternative that probes one extension at a time with a configurable delay (staggerDetectionMs) between each request. This allows LinkedIn to throttle the scan, reducing its visibility in network monitoring tools and its CPU impact.
Scale of the list: In December 2025 the array contained 5,459 entries. By February 2026 it had grown to 6,167. The array alone occupies approximately 409,000 characters of source code. LinkedIn added 708 extensions between December 2025 and February 2026 — roughly 12 new extensions per day.
Stage 2 — Passive DOM Scanning (Spectroscopy)
Independently from AED, LinkedIn runs a second system that traverses the entire DOM tree looking for evidence of extension activity. Many Chrome extensions inject elements into web pages; when they do, the injected content often contains references to the internal URL scheme of extensions (chrome-extension://). Spectroscopy finds these references.
The function recursively inspects every node: for text nodes it checks whether the text contains chrome-extension://; for element nodes it checks every attribute value. When a match is found, it extracts the 32-character extension ID from the URL.
The complementarity of the two methods is by design:
| Method | Technique | What it detects |
| AED | fetch() on known resource paths | Installed extensions, even if they inject nothing into the page |
| Spectroscopy | DOM tree walk | Extensions that actively modify the page, even if not in the list |
Device Fingerprinting — APFC/DNA
The APFC (Anti-fraud Platform Features Collection) system, also internally referred to as DNA (Device Network Analysis), collects 48 distinct browser characteristics, including: local IP address via WebRTC, connected devices (cameras, microphones, speakers) via enumerateDevices, number of CPU cores, device RAM, canvas fingerprint, WebGL fingerprint with 65+ parameters, AudioContext fingerprint, installed system fonts, battery status, network information, and detection of incognito mode, automation, and Do Not Track.
Feature #23 deserves attention: LinkedIn collects the user’s Do Not Track preference, then excludes it from the fingerprint hash. They record that you asked not to be tracked. Then they track you.
Transmission and Encryption
The fingerprint payload is serialized to JSON, encrypted with an RSA public key identified as apfcDfPK, and transmitted to two endpoints: /platformtelemetry/li/apfcDf and /apfc/collect. The encrypted fingerprint is also injected as an HTTP header in all subsequent API requests made during the user’s session: it is not sent just once, but accompanies every API call for the entire duration of the visit.
Third Parties Involved
HUMAN Security (formerly PerimeterX): LinkedIn loads a hidden 0×0 pixel iframe from li.protechts.net, positioned at left: -9999px and marked aria-hidden=”true”, which reads and sets PerimeterX cookies (_px3, _pxhd, _pxvid, _pxcts) via cross-origin postMessage.
Merchant Pool: a separate device fingerprinting script is loaded from merchantpool1.linkedin.com, passing the user’s session cookie and a hardcoded instance ID.
Google reCAPTCHA v3 Enterprise: loaded on every page load with action “onPageLoad”.
Anti-Detection Design
Several implementation choices reveal that the system was designed to avoid detection: idle execution via requestIdleCallback (no visible performance impact), staggered probing to distribute thousands of requests over time, a 0×0px hidden iframe for HUMAN Security, silent error handling with empty catch blocks that log nothing to the console, and RSA encryption of the payload that makes the content unreadable even to those inspecting network traffic.
Legal and Regulatory Implications
The scan reveals religious beliefs, political opinions, disabilities, and job-seeking activity of identified individuals. LinkedIn scans extensions that identify practicing Muslims, political orientation, tools for neurodivergent users, and 509 job search tools that expose who is secretly looking for work on the very same platform where their current employer can see their profile. Furthermore, LinkedIn scans over 200 products that directly compete with its own sales tools. Knowing each user’s employer, it can map which companies use which competing products — effectively extracting the customer lists of thousands of software companies from users’ browsers. On the DMA front: the scan list has grown from approximately 461 products in 2024 to over 6,000 by February 2026. The EU ordered LinkedIn to open its platform to third-party tools; LinkedIn built a surveillance system to find and punish every user of those tools.
Overall Technical Assessment
This case demonstrates exemplarily how JavaScript in the browser is a first-class attack surface, not only for malicious actors but for legitimate commercial platforms. The technical vectors exploited — fetch() on chrome-extension://, DOM traversal, WebRTC IP leak, canvas/WebGL/audio fingerprinting, cross-origin iframe — are all legitimate browser APIs, not exploits. No CVE is required to conduct mass intelligence gathering on a billion users.
Vulnerable Browsers and Defense Strategies
Which browsers are vulnerable? The primary vector — AED scanning via fetch() on chrome-extension:// — is architecturally Chromium-specific. The code performs an explicit check: if the browser does not report “Chrome” in the user agent string, the scan does not start. However, as is often the case with cyber topics of this kind, the real picture is more nuanced.
| Browser | Engine | Vulnerable AED | Vulnerable Spectroscopy | Vulnerable APFC Fingerprint | Notes |
| Chrome | Chromium/Blink | Yes | Yes | Yes | Primary attack vector |
| Edge | Chromium/Blink | Yes | Yes | Yes | Identical to Chrome for this vector |
| Brave | Chromium/Blink | Partial* | Yes | Partial* | Shield anti-fingerprint degrades APFC |
| Opera / Arc | Chromium/Blink | Yes | Yes | Yes | |
| Vivaldi | Chromium/Blink | Yes | Yes | Yes | |
| Firefox | Gecko | No** | Partial*** | Partial | moz-extension:// incompatible with LinkedIn list |
| LibreWolf | Gecko | No | Reduced | Many blocked by default | RFP active by default, recommended choice |
| Tor Browser | Gecko | No | Very reduced | Fingerprint resistant | Maximum APFC protection |
| Firefox ESR | Gecko | No | Partial*** | Partial | Manual hardening required |
| Apple Safari | WebKit | No**** | No***** | Partial (ITP) | macOS/iOS only — closed source |
| Safari on iOS | WebKit (mandatory) | No | No | Very reduced | All iOS browsers use WebKit per App Store policy |
| lynx / w3m | None | No | No | No | No JS — no active vector |
Table Notes
* Brave: blocks some cross-origin requests and has anti-fingerprinting shields that degrade APFC, but extensions still use chrome-extension:// — AED works unless shields are at maximum.
** Firefox — AED: uses moz-extension:// instead of chrome-extension://. LinkedIn’s hardcoded list (6,167 entries with Chrome Web Store IDs) is structurally incompatible. The userAgent.indexOf(“Chrome”) check fails as a second exclusion layer.
*** Firefox — Spectroscopy: if an extension injects elements into the DOM with references to moz-extension://, Spectroscopy does not find them because it only searches for the string chrome-extension://. De facto protection.
**** Safari — AED: double protection: user agent does not contain “Chrome” → module is not executed; the Safari extension URI scheme is safari-web-extension:// → incompatible with the list.
***** Safari — Spectroscopy: Safari extensions do not inject URLs with the chrome-extension:// scheme into the DOM → no possible match.
Residual APFC Vectors on Safari (detail)
| APFC Feature | Safari | Reason |
| WebRTC IP leak (#1) | Partial | Safari limits WebRTC but does not disable it |
| Canvas fingerprint (#36) | ITP adds noise | Not eliminated, degraded |
| WebGL (#37) | Vulnerable | Available and fingerprintable |
| AudioContext (#42) | Partial | Noise added by Safari 17+ |
| Battery API (#41) | Immune | Apple never implemented the Battery Status API |
| enumerateDevices (#2) | Partial | Requires explicit permission |
| Font enumeration (#46-47) | Partial | ITP limits, does not eliminate |
| HUMAN Security iframe | Vulnerable | Cookie partitioned by ITP, but iframe loaded |
| reCAPTCHA v3 | Vulnerable | Loaded on any browser |
Safari deserves a separate analysis because it has a completely different extension architecture.
Safari — BrowserGate Vulnerability Analysis
Safari Extension URI Scheme
Safari does not use chrome-extension:// or moz-extension://. It uses a completely different scheme: safari-web-extension://
Up to Safari 13 (and earlier versions), extensions used yet another different scheme (safari-extension://). This means that LinkedIn’s hardcoded list — built entirely on 32-character Chrome Web Store IDs — is structurally incompatible with Safari.
The explicit check in the LinkedIn code confirms this:
function s() {
return window?.navigator?.userAgent?.indexOf(“Chrome”) > -1;
}
if (!a() || !s()) return; // exits if not Chrome
On Safari, navigator.userAgent does not contain the string “Chrome” — it contains “Safari” and “WebKit”. The check fails and the entire AED module is not executed.
Residual Vulnerabilities on Safari
| Vector | Safari vulnerable? | Notes |
| AED (fetch() on chrome-extension://) | No | User agent check fails + different scheme |
| Spectroscopy (DOM walk for chrome-extension://) | No | Safari extensions do not inject URLs with that scheme |
| WebRTC IP leak (APFC #1) | Partial | Safari limits WebRTC, but does not disable it |
| Canvas fingerprint (APFC #36) | Yes with limits | ITP adds noise, but does not eliminate the vector |
| WebGL fingerprint (APFC #37) | Yes | WebGL available and fingerprintable |
| AudioContext (APFC #42) | Partial | Safari adds noise to AudioContext from Safari 17 |
| enumerateDevices (APFC #2) | Partial | Requires explicit permission |
| Font enumeration (APFC #46-47) | Partial | ITP limits, does not eliminate |
| Battery API (APFC #41) | No | Apple never implemented Battery Status API |
| HUMAN Security iframe | Yes | Loadable on any browser |
| Google reCAPTCHA v3 | Yes | Loadable on any browser |
| Merchant Pool script | Yes | Loadable on any browser |
The Role of ITP — Intelligent Tracking Prevention
Safari has a structural defense that other browsers lack by default: ITP (Intelligent Tracking Prevention), developed by Apple’s WebKit team. ITP operates at the engine level, not the extension level:
- Partitions third-party cookie storage by first-party domain
- Blocks cross-site tracking based on redirects
- Limits document.cookie access for third-party scripts
- Since 2023: also partitions the HTTP cache to prevent cache-timing attacks
This does not directly block APFC, but significantly degrades the effectiveness of cross-session tracking. The HUMAN Security iframe (li.protechts.net) is loaded but its cookies are partitioned — it cannot correlate your identity across different sessions on different sites.
Safari on iOS/iPadOS
On iOS and iPadOS the situation is even more privacy-friendly:
- All browsers on iOS are required to use WebKit (App Store policy) — so even Chrome on iOS uses WebKit, not Blink, and does not support chrome-extension:// in the Chromium sense
- Browser extensions on iOS have far more limited capabilities
- WebRTC is more restricted
- Battery API not available
On iPhone/iPad, BrowserGate is essentially inoperative on any browser.
Safari’s Limitations as a Security Choice
Despite its advantages, Safari is not the optimal choice for all contexts:
| ✓ Pros | ✗ Cons |
| • ITP is the best built-in anti-tracking system in a mainstream browser • No AED vulnerability by design • Battery API not implemented • Updated via OS updates — no patching delay | • Available only on macOS and iOS — irrelevant for Linux/OpenBSD • Closed source — cannot be independently verified • Extensions very limited compared to Firefox • WebGL and canvas fingerprinting remain active vectors • ITP is not a substitute for Firefox’s privacy.resistFingerprinting |
Safari is immune to BrowserGate’s primary vector (AED extension scanning) for solid architectural reasons: a different URI scheme and a user agent check that explicitly excludes non-Chromium browsers. ITP further reduces the effectiveness of cross-session fingerprinting.
And for LinkedIn in particular: any Firefox with a clean profile and RFP enabled beats Safari on APFC fingerprinting, because privacy.resistFingerprinting is more aggressive than ITP.
About the author: Pietro Cornelio
IT professional with 25+ years’ experience in electronics and CS, expert in system design, R&D, telecoms, and open-source.
Follow me on Twitter: @securityaffairs and Facebook and Mastodon
(SecurityAffairs – hacking, BrowserGate)
