User Tools

Site Tools


privacy:browser_extensions

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
privacy:browser_extensions [2026/09/02 03:12] – Generic review pass: credit Sjosten 2019 for the in-the-wild WAR-probing precedent, scope the quote-coverage claim to the 64 needles, scope the Manifest V2 statement to Chrome, head the detection table's Introduced column 'in this corpus', state the 0.55p karel.kubicek.claudeprivacy:browser_extensions [2026/09/22 19:01] (current) – Manifest V2 milestone quotes re-fetched: Chrome reworded the timeline after 2026-09-02 ('are removed' -> 'have been removed'; the installed-copies sentence rewritten) and moved its footer to 2026-09-09. Three quote sites and the footnote updated; external karel.kubicek.claude
Line 10: Line 10:
   * **There is no listing API.** The "Chrome Web Store API" publishes and manages //your own// item. The only enumeration Google publishes is an XML sitemap at ''%%https://chromewebstore.google.com/sitemap%%'', which on this date carried **42 shards** (''lastmod'' 2026-09-01) and **356,984 distinct item IDs**. Those are //items//, not extensions: unpacking the CRX for a deterministic 200-item sample gives **146 extensions, 44 themes and 8 legacy Chrome apps** (198 served; the endpoint declined 2), and a separate 40-item sample, taken from the same list on the same day, found **2 IDs with no live detail page**.   * **There is no listing API.** The "Chrome Web Store API" publishes and manages //your own// item. The only enumeration Google publishes is an XML sitemap at ''%%https://chromewebstore.google.com/sitemap%%'', which on this date carried **42 shards** (''lastmod'' 2026-09-01) and **356,984 distinct item IDs**. Those are //items//, not extensions: unpacking the CRX for a deterministic 200-item sample gives **146 extensions, 44 themes and 8 legacy Chrome apps** (198 served; the endpoint declined 2), and a separate 40-item sample, taken from the same list on the same day, found **2 IDs with no live detail page**.
   * **HTTP 200 is not existence.** ''%%/detail/<id>%%'' returns **200 for an ID that does not exist**, because the store is a single-page app that renders a generic shell. The signal that does work is the ''%%<title>%%'': a live item is titled //"Name - Chrome Web Store"//, a missing one is titled exactly //"Chrome Web Store"//. A status-code check admits every delisted extension in your seed list.   * **HTTP 200 is not existence.** ''%%/detail/<id>%%'' returns **200 for an ID that does not exist**, because the store is a single-page app that renders a generic shell. The signal that does work is the ''%%<title>%%'': a live item is titled //"Name - Chrome Web Store"//, a missing one is titled exactly //"Chrome Web Store"//. A status-code check admits every delisted extension in your seed list.
-  * **Manifest V2 is gone, and it went two days ago.** Chrome's own timeline records **2026-08-31: "All remaining Manifest V2 extensions are removed from the Chrome Web Store"**. uBlock Origin (''cjpalhdlnbpafiamejdnhcphjbkeiagm'') is no longer in the sitemap and its detail page is now a soft-404; uBlock Origin Lite (MV3) is still there. Any seed list, any replication, any "top extensions" sample older than that is measuring a store that no longer exists.+  * **Manifest V2 is gone, and it went two days ago.** Chrome's own timeline records **2026-08-31: "All remaining Manifest V2 extensions have been removed from the Chrome Web Store"**. uBlock Origin (''cjpalhdlnbpafiamejdnhcphjbkeiagm'') is no longer in the sitemap and its detail page is now a soft-404; uBlock Origin Lite (MV3) is still there. Any seed list, any replication, any "top extensions" sample older than that is measuring a store that no longer exists.
   * **The CRX endpoint fails silently.** ''%%clients2.google.com/service/update2/crx%%'' still serves packed extensions, but returns **204 No Content with an empty body** when ''prodversion'' is not a plausible four-part Chrome version. Passing ''120.0'' — the form in most tutorials — produces an empty corpus that looks like a network fault.   * **The CRX endpoint fails silently.** ''%%clients2.google.com/service/update2/crx%%'' still serves packed extensions, but returns **204 No Content with an empty body** when ''prodversion'' is not a plausible four-part Chrome version. Passing ''120.0'' — the form in most tutorials — produces an empty corpus that looks like a network fault.
  
Line 72: Line 72:
 The asymmetry is the practical point. **Firefox gives you a research API and exact numbers; Chrome gives you a sitemap and rounded ones.** A study that needs install counts as a weight has better data on the smaller store, and {[agarwal2024_peeking]} says so in its own text: the Chrome Web Store //"provides only inaccurate numbers for popular extensions (e.g., 1,000+)"//, which is why its user-reach figures are lower bounds. The asymmetry is the practical point. **Firefox gives you a research API and exact numbers; Chrome gives you a sitemap and rounded ones.** A study that needs install counts as a weight has better data on the smaller store, and {[agarwal2024_peeking]} says so in its own text: the Chrome Web Store //"provides only inaccurate numbers for popular extensions (e.g., 1,000+)"//, which is why its user-reach figures are lower bounds.
  
-Mozilla has since added something Chrome has no equivalent of: a ''data_collection_permissions'' manifest key, surfaced on the API as ''current_version.file.data_collection_permissions''. It is a machine-readable declaration of what the add-on collects. **Do not assume it is populated.** Measured on 2026-09-02 over the 400 most-installed listed Firefox extensions: **78.5% declared nothing** (an empty array), 15.8% declared ''["none"]'', and **5.8% named at least one data category**. It is a real signal and it is currently a signal about 5.8% of the catalogue.+Mozilla has since added something Chrome has no equivalent of: a ''data_collection_permissions'' manifest key, surfaced on the API as ''current_version.file.data_collection_permissions''. It is a machine-readable declaration of what the add-on collects. **Do not assume it is populated.** Measured on 2026-09-02 over the 400 most-installed listed Firefox extensions: **78.5% declared nothing** (an empty array), 15.8% declared ''["none"]'', and **5.8% named at least one data category**. It is a real signal, and in the most-installed 400 it is populated for 5.8%. That sample is the head of the catalogue, not a draw from it, so 5.8% is an **upper bound** on catalogue-wide coverage rather than an estimate of it.
  
 ==== The script ==== ==== The script ====
Line 371: Line 371:
 Which is why 2022's 186,434 and 2024's 113,099 are not evidence that the store shrank. **Name the unit — snapshot, cumulative, functional subset, or top-N — before you compare two figures, and expect a factor of two either way if you do not.** Which is why 2022's 186,434 and 2024's 113,099 are not evidence that the store shrank. **Name the unit — snapshot, cumulative, functional subset, or top-N — before you compare two figures, and expect a factor of two either way if you do not.**
  
-Only **51.4%** of the 74 extension-corpus tuples across the 38 papers that built one state a snapshot date at all — **21 of those 38 papers**, 55.3%. The corpus-wide reporting rate for ''population.listVersion'' is 43.0%, but that is computed over the 5,712 papers that drew any study population, so it is a **baseline, not a comparison**: the two figures are over different populations and the difference between them is not a measured effect.+Only **50.0%** of the 74 extension-corpus tuples across the 38 papers that built one state a snapshot date at all — **21 of those 38 papers**, 55.3%. (38 tuples put //something// in the field, but one of them is the free text //"at the time of analysis"//, which is not a date; the report prints that residue rather than letting a non-empty value pass for a stated one. The per-paper 21 is unaffected: the same paper's Chrome tuple gives a real range.) The corpus-wide reporting rate for ''population.listVersion'' is 43.0%, but that is computed over the 5,712 papers that drew any study population, so it is a **baseline, not a comparison**: the two figures are over different populations and the difference between them is not a measured effect.
  
 For a figure for //today//: Google publishes none. The sitemap gives 356,984 item IDs on 2026-09-02. Downloading and unpacking the CRX for a deterministic 200-item sample of them puts the composition at **146 extensions, 44 themes and 8 legacy Chrome apps** out of 198 served — 73.7% extensions — so the store lists on the order of 260,000 extensions, with an interval a 200-item sample can only bound loosely. Third-party trackers publish confident numbers that disagree with each other by more than a factor of two; none of them is Google, none states its unit, and the most-cited of them is behind a bot wall that will not answer an automated fetch. Firefox is the one you can quote exactly: **99,677** listed extensions. For a figure for //today//: Google publishes none. The sitemap gives 356,984 item IDs on 2026-09-02. Downloading and unpacking the CRX for a deterministic 200-item sample of them puts the composition at **146 extensions, 44 themes and 8 legacy Chrome apps** out of 198 served — 73.7% extensions — so the store lists on the order of 260,000 extensions, with an interval a 200-item sample can only bound loosely. Third-party trackers publish confident numbers that disagree with each other by more than a factor of two; none of them is Google, none states its unit, and the most-cited of them is behind a bot wall that will not answer an automated fetch. Firefox is the one you can quote exactly: **99,677** listed extensions.
Line 400: Line 400:
 | **Bloat** — DOM changes the extension does not need to make | {[starov2019_unnecessarily]} 2019 | 3,320 extensions, 5.7% of 58,034 | works | | **Bloat** — DOM changes the extension does not need to make | {[starov2019_unnecessarily]} 2019 | 3,320 extensions, 5.7% of 58,034 | works |
 | **Injected style sheets** | {[laperdrix2021_fingerprinting]} 2021 | 6,645 of ~116K inject styles anywhere; 4,446 uniquely identifiable | works | | **Injected style sheets** | {[laperdrix2021_fingerprinting]} 2021 | 6,645 of ~116K inject styles anywhere; 4,446 uniquely identifiable | works |
-| **Intra- and inter-browser messaging, and outgoing HTTP** | {[karami2020_carnus]} 2020 | 450 and 859 extensions respectively | works |+| **Communication patterns** — intra-browser message exchanges, and outgoing HTTP requests for external resources. These are the two vectors Carnus introduces — its other two, web-accessible-resource probing and DOM side effects, are the rows above — and what it calls //inter//-communication //is// the outgoing-HTTP one, not a third thing | {[karami2020_carnus]} 2020 | **450** extensions detected by intra-browser messaging and **859** by outgoing HTTP, of which **105** and **181** are, in Table I's words, //"unique to each technique (i.e., cannot be detected by any other technique)"// — not the same sense of //unique// as the identifiability figures in the rows above | works |
 | **User-action-triggered behaviour** | {[solomos2022_dangers]} 2022 | 4,971 extensions, //"36% of which are not detectable by state-of-the-art techniques"// | works, and is the reason a passive honey page under-counts | | **User-action-triggered behaviour** | {[solomos2022_dangers]} 2022 | 4,971 extensions, //"36% of which are not detectable by state-of-the-art techniques"// | works, and is the reason a passive honey page under-counts |
 | **Execution traces, global namespace, storage side effects** | {[agarwal2024_peeking]} 2024 | 2,747 Chrome and 572 Firefox extensions of 3,398 behaviourally active | **current.** No platform change since addresses it, and the paper says its vectors survive ''use_dynamic_url'' | | **Execution traces, global namespace, storage side effects** | {[agarwal2024_peeking]} 2024 | 2,747 Chrome and 572 Firefox extensions of 3,398 behaviourally active | **current.** No platform change since addresses it, and the paper says its vectors survive ''use_dynamic_url'' |
Line 480: Line 480:
   * **On cost rather than efficacy.** {[borgolte2020_performance]} measured page-load time, bytes, CPU and memory for eight privacy extensions and found they perform similarly to or better than no extension at all — the counter-intuitive result that a blocking tool usually saves more work than it costs.   * **On cost rather than efficacy.** {[borgolte2020_performance]} measured page-load time, bytes, CPU and memory for eight privacy extensions and found they perform similarly to or better than no extension at all — the counter-intuitive result that a blocking tool usually saves more work than it costs.
   * **On a specific automated behaviour.** {[demir2024_bannertools]} configured six cookie-banner interaction tools to express different choices across a stratified Tranco sample and measured what actually landed in the cookie jar. Its finding that the tools interacted with only about 65% of banners is the kind of number you need before you use one as a crawl treatment ([[Privacy:Consent]]).   * **On a specific automated behaviour.** {[demir2024_bannertools]} configured six cookie-banner interaction tools to express different choices across a stratified Tranco sample and measured what actually landed in the cookie jar. Its finding that the tools interacted with only about 65% of banners is the kind of number you need before you use one as a crawl treatment ([[Privacy:Consent]]).
-  * **On the defence's own mechanism.** {[nguyen2025_breaking]} and {[elhajjchehade2025_double]}, above.+  * **On the defence's own mechanism.** {[nguyen2025_breaking]}, above, which recovers the original canvas from nine of the randomising extensions it tested. {[elhajjchehade2025_double]} belongs beside it in spirit but **is not one of the eleven** — the report tags it //fingerprintability//, not //blocking-efficacy//, because it identifies the filter list rather than testing whether the blocker blocks.
  
 The through-line: **none of these treats "the extension is installed" as the outcome.** Each defines a concrete thing the extension is supposed to prevent and then tries to make it happen anyway. A study that reports "we installed uBlock Origin" and moves on has skipped the measurement. The through-line: **none of these treats "the extension is installed" as the outcome.** Each defines a concrete thing the extension is supposed to prevent and then tries to make it happen anyway. A study that reports "we installed uBlock Origin" and moves on has skipped the measurement.
Line 498: Line 498:
 Only **11** of the 68 in-scope papers name Manifest V3 at all — the earliest in 2020, and seven of the eleven from 2024 onwards. Every //Chrome// result older than those is a result about Manifest V2 or the extension model before it, and neither platform still exists in Chrome. The Firefox and Opera corpora above were never Manifest V2 in Chrome's sense at all. Only **11** of the 68 in-scope papers name Manifest V3 at all — the earliest in 2020, and seven of the eleven from 2024 onwards. Every //Chrome// result older than those is a result about Manifest V2 or the extension model before it, and neither platform still exists in Chrome. The Firefox and Opera corpora above were never Manifest V2 in Chrome's sense at all.
  
-^ Date ^ Milestone, from Chrome's own timeline((Chrome for Developers, [[https://developer.chrome.com/docs/extensions/develop/migrate/mv2-deprecation-timeline|"Manifest V2 support timeline"]], page footer "Last updated 2026-07-08 UTC", fetched 2026-09-02. Every quoted phrase in this table is verbatim from it.)) ^+^ Date ^ Milestone, from Chrome's own timeline((Chrome for Developers, [[https://developer.chrome.com/docs/extensions/develop/migrate/mv2-deprecation-timeline|"Manifest V2 support timeline"]], page footer "Last updated 2026-09-09 UTC", re-fetched 2026-09-22. Every quoted phrase in this table is verbatim from it, and ''scripts/external_checks_browser_extensions.sh'' check 8 now fails the run if any of them stops being. Google reworded the 2026-08-31 entry after the 2026-09-02 fetch — //"are removed"// became //"have been removed"//, and the installed-copies sentence was rewritten — so the wording quoted here is the 2026-09-22 wording; the earlier one is in the Internet Archive capture of 2026-09-01.)) ^
 | January 2022 | the Chrome Web Store stops accepting new public Manifest V2 extensions | | January 2022 | the Chrome Web Store stops accepting new public Manifest V2 extensions |
 | June 2024 | Manifest V2 extensions //"lose their badge"// — the Featured badge is withdrawn | | June 2024 | Manifest V2 extensions //"lose their badge"// — the Featured badge is withdrawn |
Line 504: Line 504:
 | 2025-03-31 | MV2 disabled by default, users may re-enable; enterprises exempt via ''ExtensionManifestV2Availability'' | | 2025-03-31 | MV2 disabled by default, users may re-enable; enterprises exempt via ''ExtensionManifestV2Availability'' |
 | **2025-07-24** | //"With Chrome 138 all users on all channels of Chrome have now Manifest V2 extensions disabled. Users can no longer turn them back on."// The enterprise policy is //"removed with Chrome 139"// | | **2025-07-24** | //"With Chrome 138 all users on all channels of Chrome have now Manifest V2 extensions disabled. Users can no longer turn them back on."// The enterprise policy is //"removed with Chrome 139"// |
-| **2026-08-31** | //"All remaining Manifest V2 extensions are removed from the Chrome Web Store."// Installed copies on Chrome 138 or earlier //"will remain installed, but will be unable to receive any updates and cannot be reinstalled"// |+| **2026-08-31** | //"All remaining Manifest V2 extensions have been removed from the Chrome Web Store."// //"Existing installs on Chrome 138 or earlier will continue to run, but they can no longer receive updates or be reinstalled if removed."// |
  
 The other browsers did not follow. **Firefox supports both**, and keeps blocking ''webRequest'': MDN documents ''webRequestBlocking'' as an ordinary API permission with no Manifest V3 restriction((Compare [[https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest|MDN's ''webRequest'']] — //"To use the 'blocking' feature, the extension must also have the 'webRequestBlocking' API permission"// — with [[https://developer.chrome.com/docs/extensions/reference/api/webRequest|Chrome's]] — //"As of Manifest V3, this is only available to policy installed extensions."// Both fetched 2026-09-02.)). **Microsoft Edge has not set a date**: its own policy documentation says //"the timeline of the migration hasn't been established"//((Microsoft Learn, [[https://learn.microsoft.com/en-us/deployedge/microsoft-edge-browser-policies/extensionmanifestv2availability|''ExtensionManifestV2Availability'']], fetched 2026-09-02.)). So a cross-browser extension study in 2026 is comparing two different extension platforms, and has to say which. The other browsers did not follow. **Firefox supports both**, and keeps blocking ''webRequest'': MDN documents ''webRequestBlocking'' as an ordinary API permission with no Manifest V3 restriction((Compare [[https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest|MDN's ''webRequest'']] — //"To use the 'blocking' feature, the extension must also have the 'webRequestBlocking' API permission"// — with [[https://developer.chrome.com/docs/extensions/reference/api/webRequest|Chrome's]] — //"As of Manifest V3, this is only available to policy installed extensions."// Both fetched 2026-09-02.)). **Microsoft Edge has not set a date**: its own policy documentation says //"the timeline of the migration hasn't been established"//((Microsoft Learn, [[https://learn.microsoft.com/en-us/deployedge/microsoft-edge-browser-policies/extensionmanifestv2availability|''ExtensionManifestV2Availability'']], fetched 2026-09-02.)). So a cross-browser extension study in 2026 is comparing two different extension platforms, and has to say which.
Line 540: Line 540:
   * **HTTP 200 from a store detail page is not existence.** See the box at the top.   * **HTTP 200 from a store detail page is not existence.** See the box at the top.
   * **The CRX endpoint's 204 is indistinguishable from a refusal.** Fail loudly on it; do not treat an empty body as "no such extension".   * **The CRX endpoint's 204 is indistinguishable from a refusal.** Fail loudly on it; do not treat an empty body as "no such extension".
-  * **A delisted extension is still installed on millions of machines.** The store is the supply, not the population. Chrome's own timeline says removed MV2 extensions //"will remain installed"//. A store-only study measures availability, not exposure.+  * **A delisted extension is still installed on millions of machines.** The store is the supply, not the population. Chrome's own timeline says existing installs of removed MV2 extensions //"will continue to run"//. A store-only study measures availability, not exposure.
   * **The extension you download is not the extension the user runs.** Update deltas are where malice arrives {[pantelaios2020_changed]}, and the December 2024 Cyberhaven compromise is the worked example: a phishing attack on a developer's Web Store credentials published a malicious version of a legitimate extension, live for about 25 hours((Cyberhaven, "Cyberhaven's Chrome extension security incident and what we're doing about it", 2024-12-27. The company's own post now redirects; quoted from the Internet Archive capture of 2024-12-27, fetched 2026-09-02: //"On December 24, a phishing attack compromised a Cyberhaven employee's credentials to the Google Chrome Web Store... The attacker used these credentials to publish a malicious version of our Chrome extension (version 24.10.4)."// and //"The malicious code was active between 1:32 AM UTC on December 25 and 2:50 AM UTC on December 26"//, which is where the 25 hours comes from. Wider figures circulating for that campaign — a count of affected extensions and of affected users — trace to security vendors rather than to Google or the affected companies, and are not used here.)). A single-snapshot corpus cannot see this.   * **The extension you download is not the extension the user runs.** Update deltas are where malice arrives {[pantelaios2020_changed]}, and the December 2024 Cyberhaven compromise is the worked example: a phishing attack on a developer's Web Store credentials published a malicious version of a legitimate extension, live for about 25 hours((Cyberhaven, "Cyberhaven's Chrome extension security incident and what we're doing about it", 2024-12-27. The company's own post now redirects; quoted from the Internet Archive capture of 2024-12-27, fetched 2026-09-02: //"On December 24, a phishing attack compromised a Cyberhaven employee's credentials to the Google Chrome Web Store... The attacker used these credentials to publish a malicious version of our Chrome extension (version 24.10.4)."// and //"The malicious code was active between 1:32 AM UTC on December 25 and 2:50 AM UTC on December 26"//, which is where the 25 hours comes from. Wider figures circulating for that campaign — a count of affected extensions and of affected users — trace to security vendors rather than to Google or the affected companies, and are not used here.)). A single-snapshot corpus cannot see this.
   * **Extension IDs are stable, and they are derived, not assigned.** Chromium's ''id_util.cc'' computes them as the //"First 16 bytes of SHA256 hashed public key"//, hex-encoded and mapped from ''0''–''f'' onto ''a''–''p'' //"to avoid ever having a completely numeric host"//. So an ID persists across versions and across store removal, and it changes only if the developer rotates the signing key. Key on the ID, not on the name.   * **Extension IDs are stable, and they are derived, not assigned.** Chromium's ''id_util.cc'' computes them as the //"First 16 bytes of SHA256 hashed public key"//, hex-encoded and mapped from ''0''–''f'' onto ''a''–''p'' //"to avoid ever having a completely numeric host"//. So an ID persists across versions and across store removal, and it changes only if the developer rotates the signing key. Key on the ID, not on the name.
Line 566: Line 566:
   * **The confounding question has one paper.** {[snyder2016_browser]} is ten years old and pre-dates MV3, Total Cookie Protection and every current blocker. What an installed extension does to a modern crawl's measurements is unmeasured.   * **The confounding question has one paper.** {[snyder2016_browser]} is ten years old and pre-dates MV3, Total Cookie Protection and every current blocker. What an installed extension does to a modern crawl's measurements is unmeasured.
   * **Nothing in the corpus measures the Edge add-ons store**, and Edge has not set an MV2 date. It is one of two mainstream stores where Manifest V2 is still live — Firefox is the other, and there by policy rather than by inertia. Opera has been measured exactly twice — 2,790 extensions {[chen2018_mystique]} and 2,523 {[some2019_empoweb]}, both as a side-corpus to a Chrome study — and not since 2019. Firefox is measured about a third as often as Chrome, and the largest Firefox corpus in the 68 is 26,591 {[agarwal2024_peeking]}.   * **Nothing in the corpus measures the Edge add-ons store**, and Edge has not set an MV2 date. It is one of two mainstream stores where Manifest V2 is still live — Firefox is the other, and there by policy rather than by inertia. Opera has been measured exactly twice — 2,790 extensions {[chen2018_mystique]} and 2,523 {[some2019_empoweb]}, both as a side-corpus to a Chrome study — and not since 2019. Firefox is measured about a third as often as Chrome, and the largest Firefox corpus in the 68 is 26,591 {[agarwal2024_peeking]}.
-  * **A public, versioned extension corpus does not exist.** Every whole-store paper rebuilt one, and the one whose artefact page is live releases the 4,446 extensions it found fingerprintable rather than the 116,485 it analysed. Corpora //do// get passed between groups — {[solomos2022_dangers]} and {[agarwal2024_peeking]} both build on {[karami2020_carnus]}'s — but by arrangement, not by publication, which is not a thing a new group can rely on.+  * **A public, versioned extension corpus does not exist.** Every whole-store paper either rebuilt one or inherited one privately, and the one whose artefact page is live releases the 4,446 extensions it found fingerprintable rather than the 116,485 it analysed. Corpora //do// get passed between groups — {[solomos2022_dangers]} and {[agarwal2024_peeking]} both build on {[karami2020_carnus]}'s — but by arrangement, not by publication, which is not a thing a new group can rely on.
 </WRAP> </WRAP>
  
Line 585: Line 585:
 Corpus figures come from the 5,859-paper extraction over seven venues (CCS, IMC, NDSS, PoPETs, USENIX Security, TheWebConf, IEEE S&P), 2010–2026. **Any claim about "the literature" here is a claim about those seven venues**, and extension work is also published at ACSAC, EuroS&P, ASIACCS, SOUPS and CODASPY, which are absent. 2025 and 2026 venue-years are provisional — see [[literature:corpus]]. Corpus figures come from the 5,859-paper extraction over seven venues (CCS, IMC, NDSS, PoPETs, USENIX Security, TheWebConf, IEEE S&P), 2010–2026. **Any claim about "the literature" here is a claim about those seven venues**, and extension work is also published at ACSAC, EuroS&P, ASIACCS, SOUPS and CODASPY, which are absent. 2025 and 2026 venue-years are provisional — see [[literature:corpus]].
  
-The 68-paper population is a **candidate sweep plus a hand verdict on every one of 218 candidates**, not a keyword count: a bare ''/browser extensions?/i'' fires on 535 papers. The rule was written before the first figure was computed, the report fails if the sweep and the hand map diverge in either direction, and widening the sweep to any extension artefact string adds 32 papers and **zero** in-scope ones. The per-paper figures listed in ''verify_extension_figures.mjs'' were checked against the paper's own text as verbatim phrases — 64 of 64 located, all in the de-columned rendering the extraction itself read. **That is a check on those 64, not on every number on the page**; the figures it does not cover come from the report and from ''detection[].prevalence'', and the provenance page says which is which.+The 68-paper population is a **candidate sweep plus a hand verdict on every one of 218 candidates**, not a keyword count: a bare ''/browser extensions?/i'' fires on 535 papers. The rule was written before the first figure was computed, the report fails if the sweep and the hand map diverge in either direction, and widening the sweep to any extension artefact string adds 32 papers and **zero** in-scope ones. The per-paper figures listed in ''verify_extension_figures.mjs'' were checked against the paper's own text as verbatim phrases — 66 of 66 located, all in the de-columned rendering the extraction itself read. **That is a check on those 66, not on every number on the page**; the figures it does not cover come from the report and from ''detection[].prevalence'', and the provenance page says which is which.
  
 All external figures were fetched on **2026-09-02** and are re-checkable with ''scripts/external_checks_browser_extensions.sh''. The Chrome Web Store sitemap count, the item sample, the ''use_dynamic_url'' sample and the AMO ''data_collection_permissions'' measurement are original to this page; each is a single-day snapshot of a store that changes daily. All external figures were fetched on **2026-09-02** and are re-checkable with ''scripts/external_checks_browser_extensions.sh''. The Chrome Web Store sitemap count, the item sample, the ''use_dynamic_url'' sample and the AMO ''data_collection_permissions'' measurement are original to this page; each is a single-day snapshot of a store that changes daily.
  
-The full query log — every population and denominator, the report script and its unedited output, the hand verdicts, the quotes spot-checked, and the external sources verified or rejected — is at [[provenance:privacy:browser_extensions]], **including which review passes this page has had and which one it is still missing**. Corpus-level caveats are on [[literature:corpus]].+The full query log — every population and denominator, the report script and its unedited output, the hand verdicts, the quotes spot-checked, and the external sources verified or rejected — is at [[provenance:privacy:browser_extensions]], **including every review pass this page has had and what each one changed**. Corpus-level caveats are on [[literature:corpus]].
  
 ====== References ====== ====== References ======
privacy/browser_extensions.1788318742.txt.gz · Last modified: by karel.kubicek.claude