[HN Gopher] LinkedIn checks for 2953 browser extensions
___________________________________________________________________
LinkedIn checks for 2953 browser extensions
Author : mdp
Score : 202 points
Date : 2026-02-05 20:00 UTC (2 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| lapcat wrote:
| [removed]
| ronsor wrote:
| This is a security vulnerability and should be patched. Sorry,
| LinkedIn.
|
| (Alternatively extension developers can modify their extensions
| to block these requests!)
| 0cf8612b2e1e wrote:
| No kidding. I am shocked this works.
|
| Does Firefox have a similar weakness?
| burkaman wrote:
| I don't see any evidence of this happening in Firefox.
| Either it's more difficult or they just didn't bother,
| either way I'm happy.
|
| Edit: Can't find much documentation on exactly how the
| anti-fingerprinting works, but this page implies that the
| browser blocks extension detection:
| https://support.mozilla.org/en-US/kb/trackers-and-scripts-
| fi...
| cxr wrote:
| It doesn't work. The person who posted the comment you're
| responding to has absolutely no idea what he's talking
| about. He confabulated the entire explanation based on a
| single misunderstood block of code that contains the
| comment << _Remove " - Chrome Web Store" suffix if
| present_>> in the (local, NodeJS-powered) scraper that the
| person who's publishing this data themselves used to fetch
| extension names.
| tech234a wrote:
| No. Firefox always randomizes the extension ID used for
| URLs to web accessible resources on each restart [1].
| Apparently, manifest v3 extensions on Chromium can now opt
| into similar behavior [2].
|
| [1]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-
| ons/Web...
|
| [2]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-
| ons/Web...
| tech234a wrote:
| An additional improvement added in manifest v3 in both
| Chromium and Firefox is that extensions can choose to
| expose web accessible resources to only certain websites.
| Previously, exposing a web accessible resource always
| made that resource accessible to all websites.
| toomuchtodo wrote:
| Is there no browser setting to defend against this attack? If
| not, there should be, versus relying on extension authors to
| configure or enable such a setting.
| zahlman wrote:
| I imagine that it would require browsers to treat web
| requests from JS differently from those initiated by the
| user, specifically pretending the JS-originating requests
| are by logged-out or "incognito" users (by, I suppose,
| simply not forwarding any local credentials along, but
| maybe there's more to it than that).
|
| Which would probably wreak havoc with a lot of web apps, at
| least requiring some kind of same-origin policy. And maybe
| it messes with OAuth or something. But it does seem at
| least feasible.
| circuit10 wrote:
| As people have said it's not making requests to web
| store, that's just part of this repository looking for
| what extensions it's blocking via nodejs
|
| Browsers already have strong protections against that
| sort of thing, look up the same-origin policy and CORS
| zahlman wrote:
| I see, I was too credulous.
| MrGilbert wrote:
| I'm not sure how you'd patch that. Any request that's made
| from the current open tab / window is made on behalf of the
| user. From my point of view, it's impossible for the browser
| to know, if the request is legit or not.
| ronsor wrote:
| An ideal implementation of the same origin policy would
| make it impossible for a site (through a _fetch_ call or
| otherwise) to determine whether an extension resource
| exists /is installed or the site simply lacks permission to
| access it.
| cobertos wrote:
| Wouldn't that mean 2900 requests from fingerprint.js??
| halapro wrote:
| If this is true, it's insane that this would work:
|
| - why does CWS respond to cross-site requests?
|
| - why is chrome sending the credentials (or equivalent) in
| these requests?
|
| - why is the button enabled server-side and not via JS? Google
| must be confident in knowing the exact and latest state of your
| installed extensions enough to store it on their servers, I
| guess
| cxr wrote:
| It's not true. The person you're responding to has a habit of
| posting implausible-but-plausibly-plausible nonsense, and
| it's not how this works at all.
| lapcat wrote:
| I made the mistake of trying to skim the code hastily
| before I had to leave to run an errand, and yes it turns
| out I was wrong, but please refrain from the personal
| comments, and no, I don't have any such "habit."
| cxr wrote:
| Wrong again. (PS: The fact that you have now replied--
| which automatically disables comment deletion--is the
| only thing that prevented my removing it just now. So
| great job.)
| lapcat wrote:
| > The fact that you have now replied--which automatically
| disables comment deletion--is the only thing that
| prevented my removing it just now. So great job.
|
| How was I supposed to know that you intended to delete
| it?
|
| In any case, you may still have time to edit your
| comment, as I did with my erroneous root-level comment,
| since I can't delete that either, for the same reason.
| cxr wrote:
| Not interested. You also shouldn't have done that. You
| broke the thread--exactly what HN's no-deleting-comments-
| that-have-replies check was created to prevent.
|
| Consider this: just stop being reckless.
| usefulposter wrote:
| Isn't it enumerating web_accessible_resources? Below _static
| collectFeatures(e, t)_ there is a mapping of extension IDs to
| files in the _const r_ (Minified JS, obviously.)
|
| Edit: Confirmed. It's not pinging the Chrome Web Store.
| https://blog.castle.io/detecting-browser-extensions-for-bot-...
| jsheard wrote:
| Looks to me like LinkedIn is fetching chrome-
| extension://{extension id}/{known filename} and seeing if it
| succeeds, not pinging the web store.
|
| Should be patched nonetheless though, that's a pretty obscene
| fingerprinting vector.
| what wrote:
| How do you patch it? The extensions themselves (presumably)
| need to access the same web accessible resources from their
| content scripts. How do you differentiate between some
| extension's content script requesting the resource and
| LinkedIn requesting it?
| jsheard wrote:
| Firefox already mitigates this by randomizing the extension
| path: https://developer.mozilla.org/en-US/docs/Mozilla/Add-
| ons/Web... The file is then available
| using a URL like: moz-extension://<extension-
| UUID>/images/my-image.png" <extension-UUID> is not
| your extension's ID. This ID is randomly generated for
| every browser instance. This prevents websites from
| fingerprinting a browser by examining the extensions it has
| installed.
| zahlman wrote:
| Doesn't the browser know which script it's running?
|
| Why can't it just deny access to the specified path,
| except to the extension itself?
| cxr wrote:
| It does by default, except for the files from the
| extension that the extension author has explicitly
| designated as content-accessible. It's explained ("Using
| web_accessible_resources") at the other end of the link.
| chocolatkey wrote:
| That's incorrect, it's trying to load an asset (hardcoded
| unique per-extension path) for each extension, there is a huge
| list of these in the source code:
| https://raw.githubusercontent.com/mdp/linkedin-extension-fin...
| minkeymaniac wrote:
| I can confirm.. open up linkedIn.. hit F12 and watch the error
| count keep going up and up and up
|
| Screenshots found here
| https://x.com/DenisGobo/status/2018334684879438150
| 9021007 wrote:
| xcancel link:
| https://xcancel.com/DenisGobo/status/2018334684879438150
| mongrelion wrote:
| Curious question: why would they check for installed extensions
| on one's browser?
| jppope wrote:
| most automations for sales and marketing use browser
| extensions... linkedIn wants you using their tools not 3rd
| party
| Nextgrid wrote:
| Their own tools suck, that's the issue.
| HPsquared wrote:
| An attempt at fingerprinting, I suppose?
| staticshock wrote:
| For a social network, more information about their users =
| better ad targeting. It likely gets plumbed into models to
| inform user profiles.
| Aurornis wrote:
| Look at the actual list. It's primarily questionable AI
| tools, scrapers, lead generation tools, and other plugins in
| that vein.
|
| I would guess this is for rate limiting and abuse detection.
| CobrastanJorji wrote:
| Fingerprinting. There are a few reasons you'd do it:
|
| 1. Bot prevention. If the bots don't know that you're doing
| this, you might have a reliable bot detector for a while. The
| bots will quite possibly have no extensions at all, or even
| better specific exact combination they always use. Noticing
| bots means you can block them from scraping your site or
| spamming your users. If you wanna be very fancy, you could
| provide fake data or quietly ignore the stuff they create on
| the site.
|
| 2. Spamming/misuse evasion. Imagine an extension called "Send
| Messages to everybody with a given job role at this company."
| LinkedIn would prefer not to allow that, probably because
| they'd want to sell that feature.
|
| 3. User tracking.
| xz18r wrote:
| I wrote some automation scripts that are not triggered via
| browser extensions (e.g., open all my sales colleagues'
| profiles and like their 4 most recent unliked posts to boost
| their SSI[1], which is probably the most 'innocent' of my
| use-cases). It has random sleep intervals. I've done this for
| years and never faced a ban hammer.
|
| Wonder if with things like Moltbot taking the scene, a form
| of "undetectable LinkedIn automation" will start to manifest.
| At some point they won't be able to distinguish between a
| chronically online seller adding 100 people per day with
| personalized messages, or an AI doing it with the same
| mannerisms.
|
| [1] https://business.linkedin.com/sales-solutions/social-
| selling...
| rdoherty wrote:
| Skimming the list, looks like most extensions are for scraping or
| automating LinkedIn usage. Not surprising as there's money to be
| made with LinkedIn data. Scraping was a problem when I worked
| there, the abuse teams built some reasonably sophisticated
| detection & prevention, and it was a constant battle.
| hsbauauvhabzb wrote:
| Wont someone think of poor little LinkedIn, a subsidiary of one
| of the largest data brokers in the world?
| charcircuit wrote:
| Why frame what you are trying to say like that? Businesses of
| all sizes deserve the ability to protect their businesses
| from abuse.
| ronsor wrote:
| I think they framed it this way because they don't consider
| scraping abuse (to be fair, neither do I, as long as it
| doesn't overload the site). Botting accounts for spam is
| clear abuse, however, so that's fair game.
| hsbauauvhabzb wrote:
| No, I consider all data collection and scraping
| egregious. From that perspective, LinkedIn is
| hypocritical when Microsoft discloses every filesystem
| search I do locally to bing.
| dylan604 wrote:
| Are you not scraping a site with your eyeballs when you
| view a site?
| schmidtleonard wrote:
| The big social media businesses deserve a Teddy Roosevelt
| character swooping in and busting their trusts, forcing
| them to play ball with others even if it destroys their
| moats. Boo hoo! Good riddance. World's tiniest violin.
|
| This is a popular position across the aisle. Here's hoping
| the next guy can't be bought, or at least asks for more
| than a $400M tacky gold ballroom!
| sellmesoap wrote:
| We enjoy the fruits of an LLM or two from time to time,
| derived from hoards of ill gotten data. Linkedin has the
| resourses to attempt to block scraping, but even at the
| resource scale of LI I doubt the effort is effective.
| charcircuit wrote:
| I am not denying that scraping is useful. If it wasn't
| people wouldn't do it. But if the site rules say you
| aren't allowed to scrape, then I don't think people
| should be hostile towards the people enforcing the rules.
| ronsor wrote:
| Well, they can try to enforce the rules; that's perfectly
| fair. At the same time, there are many methods of
| "trying" which I would not consider valid or acceptable
| ones. "Enforcing the rules" does not give a carte blanche
| right to snoop and do "whatever's necessary." Sony tried
| that with their CD rootkits and got multiple lawsuits.
| jmward01 wrote:
| Do they respect my data? Why do they get to track me across
| sites when I clearly don't want them to but someone can't
| scrape their data when they don't want them to. Why should
| big companies get the pass but individuals not? They
| clearly consider internet traffic fair game and are
| invasive and abusive about it so it is not only fair to be
| invasive and abusive back, it is self defense at this
| point.
| hsbauauvhabzb wrote:
| They don't need to track your web browser when they're
| owned by Microsoft, because they track every action at a
| lower level.
| missingdays wrote:
| What lower level? Microsoft owns internet?
| zelphirkalt wrote:
| The operating system. For example see the Windows 11
| screenshot debacle/scandal.
| nitwit005 wrote:
| I'm sure there are issues with fake accounts for scraping,
| but the core issue is that LinkedIn considers the data
| valuable. LinkedIn wants to be able to sell the data, or
| access to it at least, and the scrapers undermine that.
|
| They could stop all the scraping by providing a
| downloadable data bundle like Wikipedia.
| compiler-guy wrote:
| LLMs scrape Wikipedia all the time, or at least attempt
| to.
|
| The data bundle doesn't help that at all.
| b112 wrote:
| Yes, until it becomes abusive and malignly affects
| innocents.
| xp84 wrote:
| I mean, regardless of who they are or even if you don't like
| what LinkedIn does themselves with the data people have given
| them, the random third parties with the extensions don't
| additionally deserve to just grab all that data too, do they?
| mathfailure wrote:
| Surely they do! The data is in the public internets, aren't
| they?
| ronsor wrote:
| They'd put Widevine or PlayReady DRM on the website if
| they could, I'm sure.
| bigfishrunning wrote:
| why can't they?
| josephg wrote:
| Eh. I worked at a company which made an extension which
| scraped LinkedIn. We provided a service to recruiters, who
| would start a hiring process by putting candidates into our
| system.
|
| The recruiters all had LinkedIn paid accounts, and could
| access all of this data on the web. We made a browser
| extension so they wouldn't need to do any manual data
| entry. Recruiters loved the extension because it saved them
| time.
|
| I think it was a legitimate use. We were making LinkedIn
| more useful to some of their actual customers (recruiters)
| by adding a somewhat cursed api integration via a chrome
| extension. Forcing recruiters to copy and paste did't help
| anyone. Our extension only grabbed content on the page the
| recruiter had open. It was purely read only and scoped by
| the user.
| hsbauauvhabzb wrote:
| I say the same thing about my start menu sending every
| action I perform to bing.
| bryanrasmussen wrote:
| from the code doesn't look like they do anything if they have a
| match, they just save all the results to a csv for
| fingerprinting?
| cxr wrote:
| "The code" here you're referring to
| (fetch_extension_names.js[1]) isn't and doesn't claim to be
| LinkedIn's fingerprinting code. It's a scraper that the
| researcher behind this repo wrote in order to themselves
| create the CSV of the data that they're publishing.
|
| LinkedIn's fingerprinting code, as the README explains, is
| found in fingerprint.js[2], which embeds a big JSON literal
| with the IDs of the extensions it probes for. (Sickeningly
| enough, this data starts about two-thirds of the way through
| the file* and _isn 't_ the culprit behind the bulk of its
| 2.15 MB size...)
|
| * On line 34394; the one starting: const r
| = [{ id:
| "aacbpggdjcblgnmgjgpkpddliddineni", file:
| "sidebar.html"
|
| 1. <https://github.com/mdp/linkedin-extension-
| fingerprinting/blo...>
|
| 2. <https://github.com/mdp/linkedin-extension-
| fingerprinting/blo...>
| cxr wrote:
| In order to create the data source that LinkedIn's extension-
| fingerprinting relies on to work, someone (at LinkedIn*?)
| almost certainly violated the Chrome Web Store TOS--by
| (perversely*) scraping it.
|
| * if LinkedIn didn't get it from an existing data source
| winddude wrote:
| a problem for linkedin != "a problem". The real problem for
| people is the back room data brokering linkedin and others do.
| zahlman wrote:
| > This repository documents every extension LinkedIn checks for
| and provides tools to identify them.
|
| I get that the CSV lists the extensions, and the tools are
| provided in order to show work (mapping IDs to actual software).
| But how was it determined that LinkedIn checks for extensions
| with these IDs?
|
| And is this relevant for non-Chrome users?
| usefulposter wrote:
| Technical writeup from a few weeks ago by a vendor that
| explains how LinkedIn does it, then boasts that their approach
| is "quieter, harder to notice, and easier to run at scale":
|
| https://blog.castle.io/detecting-browser-extensions-for-bot-...
| Aurornis wrote:
| I suggest everyone take a look at the list of extensions and
| their names for some very important context:
| https://github.com/mdp/linkedin-extension-fingerprinting/blo...
|
| I didn't find popular extensions like uBlock or other ad
| blockers.
|
| The list is full of scammy looking data collection and AI tools,
| though. Some random names from scrolling through the list:
|
| - LinkedGPT: ChatGPT for LinkedIn
|
| - Apollo Scraper - Extract & Export Apollo B2B Leads
|
| - AI Social Media Assistant
|
| - LinkedIn Engagement Assistant
|
| - LinkedIn Lead Magnet
|
| - LinkedIn Extraction Tool - OutreachSheet
|
| - Highperformr AI - Phone Number and Email Finder
|
| - AI Agent For Jobs
|
| These look like the kind of tools scummy recruiters and sales
| people use to identify targets for mass spamming. I see several
| AI auto-application tools in there too.
| NicuCalcea wrote:
| LinkedIn itself provides tools for scummy recruiters to mass
| spam, so this is just them protecting their business.
|
| Also, not all of them are data collection tools. There are ad
| blockers listed (Hide LinkedIn Ads, SBlock - Super Ad Blocker)
| and just general extensions (Ground News - Bias Checker, Jigit
| Studio - Screen Recorder, RealEyes.ai -- Detect Deepfakes
| Across Online Platforms, Airtable Clipper).
| cbsks wrote:
| Looks like Firefox is immune.
|
| This works by looking for web accessible resources that are
| provided by the extensions. For Chrome, these are are available
| in a webpage via the URL chrome-extension://[PACKAGE ID]/[PATH]
| https://developer.chrome.com/docs/extensions/reference/manif...
|
| On Firefox, web accessible resources are available at "moz-
| extension://<extension-UUID>/myfile.png" <extension-UUID> is not
| your extension's ID. This ID is randomly generated for every
| browser instance. This prevents websites from fingerprinting a
| browser by examining the extensions it has installed.
| https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/Web...
| awesome_dude wrote:
| This is probably a naive question, but...
|
| Doesn't the idea of swapping extension specific IDs to your
| browser specific extension IDs mean that instead of your
| browser being identifiable, you become identifiable?
|
| I mean, it goes from "Oh they have X, Y , and Z installed" to
| "Oh, it's jim bob, only he has that unique set of IDs for
| extensions"
| triceratops wrote:
| It's not a naive question. This comment says it's not
| possible to do that:
| https://news.ycombinator.com/item?id=46905213
| awesome_dude wrote:
| Oh, it's (re)randomised upon each restart, whew, thanks for
| the heads up
|
| edit: er, I think that that also suggests that I need to
| restart firefox more often...
| tech234a wrote:
| The webpage would have to scan the entire UUID space to
| create this fingerprint, which seems unlikely.
| throwaway808081 wrote:
| Just have a database of UUIDs. Seems pretty trivial to
| generate and sort as it's only 16 bytes each.
| b112 wrote:
| Maybe, but how long are the extension ids? And if they are
| random, how long to scan a trillion random alphanumeric ids,
| to find matches?
|
| I presume the extension knows when it wants to access
| resources of its own. But random javascript, doesn't.
| maples37 wrote:
| The extension IDs are UUIDs/GUIDs, so 128 bits of entropy.
| No site is going to be able to successfully scan that full
| range.
| b112 wrote:
| ChatGPT told me it can be done though.
|
| It won't disclose how, as it says it has had several
| users report it. And that it expects 50% of the bounty,
| and will use it for GPU upgrades.
| rchaud wrote:
| And they said that using a browser with sub-5% market share
| would cause us to miss out on the latest and greatest in web
| technology!
| dana321 wrote:
| chrome was made by ex-firefox devs, chrome is still not as
| good!
| hasperdi wrote:
| Another thing... they alter the localStorage & sessionStorage
| prototype, by wrapping the native ones with a wrapper that
| prevent keys that not in their whitelist from being set.
|
| You can try this by opening devtools and setting
| localStorage.setItem('hi', 123)
| tech234a wrote:
| See also: a demo page for the same technique that can enumerate
| many extensions installed in your browser:
| https://browserleaks.com/chrome
| xnx wrote:
| Yuck. Disgusting that extension detection is possible.
| shouldnt_be wrote:
| I wrote an article about it a couple of months ago. I also
| explain why, how and a way to prevent it.
|
| https://javascript.plainenglish.io/the-extensions-you-use-ar...
| jmholla wrote:
| To clarify, you talk about why it's possible, not why LinkedIn
| is doing it, right? Or did I miss something in your article.
| DrStartup wrote:
| Setup a quick CDP connection. Have Claude Code attach and inject
| JS into Page.addScriptToEvaluateOnNewDocument. Loads before the
| page.
|
| Typical early hooks: * fetch wrapper *
| XMLHttpRequest.prototype.open/send wrapper * WebSocket
| constructor wrapper * history.pushState/replaceState wrapper *
| EventTarget.addEventListener wrapper (optional, heavy) *
| MutationObserver for DOM diffs * Error + unhandledrejection
| capture
| shj2105 wrote:
| what would this do?
| HumanOstrich wrote:
| This is irrelevant to the article and discussions here. Weird
| copypasta bullet points too.
| input_sh wrote:
| cut -d',' -f2 chrome_extensions_with_names_all.csv | grep -c "AI"
| 474
|
| Only 16%!?
| unstatusthequo wrote:
| I'm probably on the list. I made a LinkedIn Redactor that allowed
| you to add keywords and remove posts from your thread that
| included such words. It's the X feature but for LinkedIn. Anyway,
| got a cease and desist from those lame fucks at LI. So I removed
| from the chrome store but it's still available on GitHub.
| avastel wrote:
| I wrote a blog post recently about the technique used by LinkedIn
| to do extension probing, as well as other ways to do it with less
| side effects
|
| https://blog.castle.io/detecting-browser-extensions-for-bot-...
| bastard_op wrote:
| Chrome is the new IE6. Google set themselves up to be the next
| Microsoft and is "ad friendly" in all the creepy ways because
| that's what Google IS an ad company. All they've contributed to
| security is diminishing the capability of adblockers and letting
| malware to do bad things to you as consumers.
| 0xbadcafebee wrote:
| He who controls the Ads, controls the Internet.
| themafia wrote:
| > Google set themselves up to be the next Microsoft
|
| Google became a monopoly. All monopolies do this.
| dwedge wrote:
| I wonder if this is why the linkedin feed blocker I installed in
| Firefox 2 weeks ago stopped working for me within 24 hours
| ta988 wrote:
| So it really is espionage at all levels.
| mrkramer wrote:
| LinkedIn is the worst walled garden of all of them.
| DOM100 wrote:
| const nameA = getName(a).toLowerCase(); const nameB =
| getName(b).toLowerCase(); return nameA.localeCompare(nameB);
|
| const msg = createDoneMessage(); msg.style.opacity = '1';
| console.log("Extensions sorted alphabetically!");
| console.table(sortedCards.map(c => ({ name:
| getName(c), id: c.id || '--'
| bitbasher wrote:
| Looks like this has been known since 2019.
|
| https://www.nymeria.io/blog/linkedins-war-on-email-finder-ex...
___________________________________________________________________
(page generated 2026-02-05 23:00 UTC)