| Next revision | Previous revision |
| privacy:javascript [2026/08/06 22:23] – New page: Analysing and Classifying JavaScript. Systematisation of script-level analysis for web privacy measurement, backed by a 160-paper population from the 4,322-paper corpus (7 venues, 2010-2024): granularity ladder and mixed scripts, script identity karel.kubicek.claude | privacy:javascript [2026/09/03 22:34] (current) – Re-review fix: the resolvable-model figure moved to 19.4% of 175 after the buckets were restricted to papers that used an LLM rather than compared against one. Authored by Claude karel.kubicek.claude |
|---|
| |
| <WRAP important> | <WRAP important> |
| **The single most consequential decision on this page is the unit of analysis, and it is usually made by accident.** Domain, hostname, script URL, script content, function: each gives a different answer to "is this tracking", and the literature contains headline numbers at every level that are routinely compared as if they were the same measurement. A finding that 0.67% of scripts are obfuscated {[skolka2019_anything]} and a finding that 95.90% of domains load an obfuscated script {[sarker2020_hiding]} are both true, one year apart, on overlapping crawls. Fix your unit before you fix your method. | **The single most consequential decision on this page is the unit of analysis, and it is usually made by accident.** Domain, hostname, script URL, script content, function: each gives a different answer to "is this tracking", and the literature contains headline numbers at every level that are routinely compared as if they were the same measurement. A finding that 0.67% of //scripts// are obfuscated {[skolka2019_anything]} and a finding that 95.90% of //domains with script data// load at least one obfuscated script {[sarker2020_hiding]} are both true, one year apart, on overlapping crawls — different unit, different definition, no contradiction. Fix your unit before you fix your method. |
| </WRAP> | </WRAP> |
| |
| ==== Mixed scripts are the normal case, not the tail ==== | ==== Mixed scripts are the normal case, not the tail ==== |
| |
| Three independent measurements, three different denominators, one finding: | Three measurements, three different denominators, one finding. They are not independent — all three come from Shafiq's group with Amjad as first author — but nobody has contradicted them: |
| |
| ^ Study ^ Population ^ What is mixed ^ | ^ Study ^ Population ^ What is mixed ^ |
| | TrackerSift, IMC 2021 {[amjad2021_trackersift]} | 100K websites | 6% of **scripts**, 9% of **methods** | | | TrackerSift, IMC 2021 {[amjad2021_trackersift]} | 100K websites | 6% of **scripts**, 9% of **methods** | |
| | Amjad et al., PoPETs 2023 {[amjad2023_blocking]} | 100K sites sampled from Tranco top 1M | **14.6%** of 256K scripts in 2022, up 14% from 2021 | | | Amjad et al., PoPETs 2023 {[amjad2023_blocking]} | 100K sites sampled from Tranco top 1M | **14.6%** of 256K scripts in 2022, up from 12.8% of 220K in 2021 — and a **14% increase in the number of websites** carrying a mixed script over that year | |
| | NoT.js, CCS 2024 {[amjad2024_notjs]} | Tranco top 10K | **13.4%** of scripts; **62.3%** of websites carry at least one mixed script, and **70.6%** of those mixed scripts are third-party | | | NoT.js, CCS 2024 {[amjad2024_notjs]} | Tranco top 10K | **13.4%** of scripts; **62.3%** of websites carry at least one mixed script, and **70.6%** of those mixed scripts are third-party | |
| |
| The practical consequence is measured directly. Blocking every script on a page removes tracking effectively but **breaks legitimate functionality on roughly two-thirds (66%) of tested webpages**, and still leaves **76% of tracking requests in place**, because plenty of tracking requests are not script-initiated at all {[amjad2023_blocking]}. Selective blocking of a curated tracking-script set gives a 57% reduction in tracking requests for an 11% reduction in functional ones — a better trade, but the mixed scripts are exactly the ones it cannot touch. Dropping to method granularity **reduces major breakage by 3.8× at the same level of tracking prevention** {[amjad2023_blocking]}. | The practical consequence is measured directly on a crawl of 100K sites sampled from the Tranco top million {[amjad2023_blocking]}. Blocking **every** script cuts tracking requests from 1,175,033 to 265,101 — 22.6% remain — but leaves 75.9% of functional requests standing and **breaks legitimate functionality on roughly two-thirds (66%) of tested webpages**.((The paper's prose sentence reports this pair the other way round — //"22% of functional requests and 76% of tracking requests remain after blocking all JS scripts"// — which contradicts its own Table 2 (tracking 1,175,033 → 265,101; functional 4,279,844 → 3,248,767) and its parallel sentence for the selective configuration. The figures quoted here are read from Table 2. Checked against the published PDF on 2026-08-06.)) Blocking only a curated set of tracking scripts is the better trade: 95% of functional requests persist while 30% of tracking requests survive, or per webpage a 57% reduction in tracking requests for an 11% reduction in functional ones. But the mixed scripts are exactly the ones it cannot touch, and dropping to method granularity **reduces major breakage by 3.8× at the same level of tracking prevention**. |
| |
| NoT.js {[amjad2024_notjs]} is the current state of the art at that granularity. It builds a graph from the **dynamic execution context** of each function call — the call stack and calling context, obtained from PageGraph plus the DevTools Protocol's ''Runtime.CallFrame'' and ''Debugger.Scope'' — trains a random forest on it, and then generates surrogate scripts that neutralise the tracking functions while leaving the rest of the file intact. Surrogate generation is not new — SugarCoat {[smith2021_sugarcoat]} generated privacy-preserving replacements for 231 target scripts by hand-guided rewriting — but NoT.js derives the replacement from the classifier rather than from a curator. It reports 94% precision and 98% recall on function-level tracking detection over the top 10K, classifying 32.1% of the 2,088K JavaScript functions in its dataset as tracking, and 0% major / 8% minor breakage in a 50-site manual study against WebGraph's 6% / 10%.((Verified against the paper's own text and the arXiv preprint [[https://arxiv.org/abs/2405.18385|2405.18385]] on 2026-08-06. Artifact: [[https://github.com/hadiamjad/Not.js|github.com/hadiamjad/Not.js]] — MIT, **no commits since 2024-07-18**. Treat it as a frozen research artifact, not a maintained tool.)) | NoT.js {[amjad2024_notjs]} is the current state of the art at that granularity. It builds a graph from the **dynamic execution context** of each function call — the call stack and calling context, collected by its own Chrome extension over the DevTools Protocol's ''Runtime.CallFrame'' and ''Debugger.Scope'' — trains a random forest on it, and then generates surrogate scripts that neutralise the tracking functions while leaving the rest of the file intact. Surrogate generation is not new — SugarCoat {[smith2021_sugarcoat]} already patched scripts automatically, producing replacements for 231 unique in-the-wild scripts, and ships some of them in Brave — but its input set is whatever a filter-list author has already written an //exception// rule for. NoT.js picks the functions itself. It reports 94% precision and 98% recall on function-level tracking detection over the top 10K, classifying 32.1% of the 2,088K JavaScript functions in its dataset as tracking, and 0% major / 8% minor breakage in a 50-site manual study against WebGraph's 6% / 10%.((Verified against the paper's own text and the arXiv preprint [[https://arxiv.org/abs/2405.18385|2405.18385]] on 2026-08-06. Artifact: [[https://github.com/hadiamjad/Not.js|github.com/hadiamjad/Not.js]] — MIT, **no commits since 2024-07-18**. Treat it as a frozen research artifact, not a maintained tool.)) |
| |
| <WRAP info> | <WRAP info> |
| The convenient identity "one script = one URL" is wrong often enough to change results, and it is getting worse: | The convenient identity "one script = one URL" is wrong often enough to change results, and it is getting worse: |
| |
| | * **Inline scripts have no URL at all.** They are the ordinary case, not an edge case, and every URL-keyed pipeline silently drops them. Key them by content hash plus document URL plus position, or by the CDP ''scriptId'' with ''hasSourceURL'' recorded, and report how many you had. |
| * **Dynamic injection.** On the median page in HTTP Archive's 2024 crawl, **24% of scripts (desktop; 21% mobile) are injected** by ''createElement''/''innerHTML'' rather than present in the served HTML — at the 90th percentile it is 70–73%.((HTTP Archive Web Almanac 2024, [[https://almanac.httparchive.org/en/2024/javascript|JavaScript chapter]], Figure 1.14. Checked 2026-08-06. Note the 2025 edition has **no JavaScript chapter** at all, so this is currently the freshest public figure.)) Those have no static load-time URL. | * **Dynamic injection.** On the median page in HTTP Archive's 2024 crawl, **24% of scripts (desktop; 21% mobile) are injected** by ''createElement''/''innerHTML'' rather than present in the served HTML — at the 90th percentile it is 70–73%.((HTTP Archive Web Almanac 2024, [[https://almanac.httparchive.org/en/2024/javascript|JavaScript chapter]], Figure 1.14. Checked 2026-08-06. Note the 2025 edition has **no JavaScript chapter** at all, so this is currently the freshest public figure.)) Those have no static load-time URL. |
| * **Dynamic generation.** Lekies et al. {[lekies2015_dynamic]} found 81 of 150 studied domains serving scripts whose //content// differs per request — often because they embed a user identifier. The same URL is a different program each time. | * **Dynamic generation.** Lekies et al. {[lekies2015_dynamic]} studied the 150 Alexa top-500 domains offering free registration and found **81 of them** serving scripts whose //content// differs per request; on **49 domains (209 scripts)** the content depended on the user's session state, so the same URL is a different program per visitor. |
| * **Bundling.** Rack and Staicu {[rack2023_jackinthebox]} detected 1,086,368 bundles crawling the Tranco top 1M and found **at least one bundle on 40% of crawled websites**. A bundle is many libraries in one URL, which is precisely the mixed-script problem baked in at build time — and most of what it contains never runs: Muzeel {[kupoluyi2022_muzeel]} found that **half of the 300,000 JavaScript files** on 15,000 popular pages have at least 70% unused functions, accounting for about 55% of file size. | * **Bundling.** Rack and Staicu {[rack2023_jackinthebox]} detected 1,086,368 bundles crawling the Tranco top 1M and found **at least one bundle on 40% of crawled websites**. A bundle is many libraries in one URL, which is precisely the mixed-script problem baked in at build time — and most of what it contains never runs: Muzeel {[kupoluyi2022_muzeel]} found that **half of the 300,000 JavaScript files** on 15,000 popular pages have at least 70% unused functions, accounting for about 55% of file size. |
| * **Self-deletion.** Li et al. {[li2024_selfdeleting]} found script-deletion behaviour on **42.44% of 870,734 reachable websites**: a script removes its own ''<script>'' element after running. If you enumerate the DOM after load, those scripts are simply not there. | * **Self-deletion.** Li et al. {[li2024_selfdeleting]} found script-deletion behaviour on **42.44% of 870,734 reachable websites**: a script removes its own ''<script>'' element after running. If you enumerate the DOM after load, those scripts are simply not there. |
| ===== What This Literature Actually Is ===== | ===== What This Literature Actually Is ===== |
| |
| Everything in this section comes from a structured extraction over **4,322 full-text papers** from CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P, 2010–2024, one record per paper with a verbatim evidence quote per claim. The population here is **160 papers that analyse or classify JavaScript running in a browser** — how that population was built, and what it misses, is at [[#Reproducing These Figures]]. | Everything in this section comes from a structured extraction over **5,859 full-text papers** from CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P, 2010–2026, one record per paper with a verbatim evidence quote per claim. The 2025 and 2026 venue-years are provisional — CCS and IMC 2026 have not been held and two more 2026 venue-years are incompletely selected. The population here is **206 papers that analyse or classify JavaScript running in a browser** — how that population was built, and what it misses, is at [[#Reproducing These Figures]]. |
| |
| ==== Neither obvious search handle finds it ==== | ==== Neither obvious search handle finds it ==== |
| |
| ^ Handle ^ Papers ^ Of which measure the web ^ Share ^ | ^ Handle ^ Papers ^ Of which measure the web ^ Share ^ |
| | Used or produced a ''program-analysis'' tool | 959 | 215 | 22.4% | | | Used or produced a ''program-analysis'' tool | 1,385 | 299 | 21.6% | |
| | ''studyTypes'' includes ''code-or-binary-analysis'' | 1,063 | 249 | 23.4% | | | ''studyTypes'' includes ''code-or-binary-analysis'' | 1,484 | 347 | 23.4% | |
| |
| And the program-analysis tools these venues actually use are not JavaScript tools: LLVM (66 papers), Soot (61), IDA Pro (36), FlowDroid (34), angr (28), Ghidra (24), Androguard (23), Z3 (22), Apktool (21). **Esprima, at 15 papers, is the highest-ranked JavaScript parser in the whole corpus.** In a broad security corpus, "program analysis" means binaries, Android apps and smart contracts; web-script analysis is a small minority inside it, and shares almost no toolchain with the rest. | And the program-analysis tools these venues actually use are not JavaScript tools: LLVM (101 papers), Soot (81), IDA Pro (62), FlowDroid (48), angr (39), Z3 (38), Ghidra (38), CodeQL (34), Androguard (33), Apktool (30). **Esprima, at 23 papers, is the highest-ranked JavaScript parser in the whole corpus.** In a broad security corpus, "program analysis" means binaries, Android apps and smart contracts; web-script analysis is a small minority inside it, and shares almost no toolchain with the rest. |
| |
| ==== Where the 160 papers are ==== | ==== Where the 206 papers are ==== |
| |
| ^ Venue ^ Corpus papers ^ JS-analysis papers ^ Share of venue ^ | ^ Venue ^ Corpus papers ^ JS-analysis papers ^ Share of venue ^ |
| | USENIX Security | 1,117 | 39 | 3.5% | | | USENIX Security | 1,410 | 44 | 3.1% | |
| | TheWebConf | 713 | 34 | 4.8% | | | TheWebConf | 843 | 41 | 4.9% | |
| | CCS | 889 | 29 | 3.3% | | | CCS | 990 | 33 | 3.3% | |
| | IMC | 559 | 20 | 3.6% | | | IMC | 638 | 24 | 3.8% | |
| | PETS | 355 | 18 | 5.1% | | | IEEE S&P | 767 | 22 | 2.9% | |
| | NDSS | 419 | 15 | 3.6% | | | NDSS | 701 | 21 | 3.0% | |
| | IEEE S&P | 270 | 5 | 1.9% | | | PETS | 510 | 21 | 4.1% | |
| |
| ^ Period ^ Corpus papers ^ JS-analysis papers ^ Per 1,000 corpus papers ^ | ^ Period ^ Corpus papers ^ JS-analysis papers ^ Per 1,000 corpus papers ^ |
| | 2010–2013 | 468 | 11 | 23.5 | | | 2010–2013 | 511 | 14 | 27.4 | |
| | 2014–2017 | 711 | 32 | 45.0 | | | 2014–2017 | 769 | 34 | 44.2 | |
| | 2018–2021 | 1,403 | 58 | 41.3 | | | 2018–2021 | 1,439 | 61 | 42.4 | |
| | 2022–2024 | 1,740 | 59 | 33.9 | | | 2022–2024 | 1,955 | 68 | 34.8 | |
| | | 2025–2026 //(provisional)// | 1,185 | 29 | 24.5 | |
| |
| The field grew sharply into the mid-2010s and has been flat-to-declining as a share of these venues since. That is not a decline in importance — it is the topic being absorbed into tracking, fingerprinting and supply-chain papers that no longer describe themselves as JavaScript analysis. | The field grew sharply into the mid-2010s and has been declining as a share of these venues since. That is not a decline in importance — it is the topic being absorbed into tracking, fingerprinting and supply-chain papers that no longer describe themselves as JavaScript analysis. |
| |
| ==== What they are about ==== | ==== What they are about ==== |
| Ranked, not measured: ''detection.phenomenon'' is one of the least reproducible fields in the extraction (~20% exact-string agreement between independent runs), so this is a ranking with a printed residue, never a set of percentages. | Ranked, not measured: ''detection.phenomenon'' is one of the least reproducible fields in the extraction (~20% exact-string agreement between independent runs), so this is a ranking with a printed residue, never a set of percentages. |
| |
| ^ Research family ^ Papers ^ Share of 160 ^ | ^ Research family ^ Papers ^ Share of 206 ^ |
| | Tracking- and advertising-script classification | 25 | 15.6% | | | Tracking- and advertising-script classification | 29 | 14.1% | |
| | Malicious-script and cloaking detection | 21 | 13.1% | | | Fingerprinting-script detection | 24 | 11.7% | |
| | Third-party libraries, inclusion and supply chain((The oldest strand of this family and still the most-cited entry point: Lauinger et al. {[lauinger2017_thou]} found **87.7% of Alexa top-75K sites and 46.5% of .com sites** using at least one of 72 catalogued JavaScript libraries, very often an outdated version.)) | 20 | 12.5% | | | Malicious-script and cloaking detection | 24 | 11.7% | |
| | Fingerprinting-script detection | 19 | 11.9% | | | Third-party libraries, inclusion and supply chain((The oldest strand of this family and still the most-cited entry point: Lauinger et al. {[lauinger2017_thou]} found **87.7% of Alexa top-75K sites and 46.5% of .com sites** using at least one of 72 catalogued JavaScript libraries, and **37.8% of Alexa sites running at least one version with a known vulnerability** (9.7% two or more).)) | 24 | 11.7% | |
| | Web-API usage measurement | 16 | 10.0% | | | Web-API usage measurement | 22 | 10.7% | |
| | Client-side vulnerabilities (XSS, CSP, taint flows) | 12 | 7.5% | | | Client-side vulnerabilities (XSS, CSP, taint flows) | 18 | 8.7% | |
| | Browser-extension scripts | 7 | 4.4% | | | Browser-extension scripts | 8 | 3.9% | |
| | Data leakage by scripts | 6 | 3.8% | | | Data leakage by scripts | 8 | 3.9% | |
| | Script change and identity over time | 6 | 3.8% | | | Script performance, size and dead code | 8 | 3.9% | |
| | Cryptojacking | 5 | 3.1% | | | Script change and identity over time | 7 | 3.4% | |
| | WebAssembly (non-mining) | 4 | 2.5% | | | Cryptojacking | 5 | 2.4% | |
| | Script performance, size and dead code | 3 | 1.9% | | | WebAssembly (non-mining) | 5 | 2.4% | |
| |
| 45 detection tuples did not fold into any family and are printed by the report script rather than dropped. | 65 detection tuples did not fold into any family and are printed by the report script rather than dropped — a slightly larger share of a larger population than the 45 of the earlier corpus, so this fold has aged well where others have not. |
| |
| The shape to notice: **the privacy reader's own family is the largest but is barely a quarter of the field.** If you search these venues for "JavaScript detection" you will mostly get client-side vulnerability and malware papers, which use the same parsers and the same instrumented browsers on a different question. They are worth reading for method and misleading as related work. | The shape to notice: **the privacy reader's own two families — tracking/advertising classification and fingerprinting-script detection — lead the ranking, and together they are barely a quarter of the field (53 of 206).** If you search these venues for "JavaScript detection" you will mostly get client-side vulnerability and malware papers, which use the same parsers and the same instrumented browsers on a different question. They are worth reading for method and misleading as related work. |
| |
| ==== Anchor papers to read first ==== | ==== Anchor papers to read first ==== |
| |
| <WRAP important> | <WRAP important> |
| This corpus ends in 2024. A ranking of what the 2010–2024 literature //did// is a fact about the literature, not advice about what to do now. The table below dates each method and states its status as of **2026-08-06**; the rows marked //current// were checked against post-2024 work outside the corpus. | This corpus now reaches 2026, but its 2025 and 2026 venue-years are provisional and thin. A ranking of what the 2010–2026 literature //did// is a fact about the literature, not advice about what to do now. The table below dates each method and states its status as of **2026-08-06**; the rows marked //current// were checked against post-2024 work outside the corpus, and the tool table further down now gives partial corpus support for two of them. |
| </WRAP> | </WRAP> |
| |
| | 2015–2019 | Supervised classifiers on script URL + content features | Ikram et al., one-class learning {[ikram2017_seamless]} | **Superseded** by graph and behavioural methods | | | 2015–2019 | Supervised classifiers on script URL + content features | Ikram et al., one-class learning {[ikram2017_seamless]} | **Superseded** by graph and behavioural methods | |
| | 2016–2019 | Counting accesses to a hand-picked API set, with thresholds | Englehardt & Narayanan {[englehardt2016online]}; VisibleV8 {[jueckstock2019_visiblev8]} enables it at engine level | **Historical as a classifier**; still the right way to //collect// the signal | | | 2016–2019 | Counting accesses to a hand-picked API set, with thresholds | Englehardt & Narayanan {[englehardt2016online]}; VisibleV8 {[jueckstock2019_visiblev8]} enables it at engine level | **Historical as a classifier**; still the right way to //collect// the signal | |
| | 2020–2022 | Graph representations of page execution, ML-classified | AdGraph {[iqbal2020_adgraph]}, WebGraph {[siby2022_webgraph]}, Khaleesi {[iqbal2022_khaleesi]}, FP-Inspector {[iqbal2021_fingerprinting]} | **The reference baselines** — every new paper compares against them. But see the maintenance warning below | | | 2020–2022 | Graph representations of **page execution**, ML-classified | AdGraph {[iqbal2020_adgraph]}, WebGraph {[siby2022_webgraph]} | **The reference baselines** — every new paper compares against them. But see the maintenance warning below | |
| | | 2020–2022 | Sibling lineages on the same instrumentation: sequential ML over **request chains**; syntactic + dynamic **script** features | Khaleesi {[iqbal2022_khaleesi]}, FP-Inspector {[iqbal2021_fingerprinting]} | **Still cited baselines**, but neither is a page-execution graph — do not lump them in | |
| | 2023–2024 | Content-independent representations: V8 **bytecode** as text | Ghasemisharif & Polakis {[ghasemisharif2023_bytecode]} | **Current.** 97.08% accuracy on Tranco top-50K scripts; robust to URL and source-level obfuscation | | | 2023–2024 | Content-independent representations: V8 **bytecode** as text | Ghasemisharif & Polakis {[ghasemisharif2023_bytecode]} | **Current.** 97.08% accuracy on Tranco top-50K scripts; robust to URL and source-level obfuscation | |
| | 2023–2024 | **Function granularity** with dynamic calling context | TrackerSift {[amjad2021_trackersift]}, NoT.js {[amjad2024_notjs]} | **Current and where the field is going** | | | 2021 | **Method granularity** by attributing requests to the method that issued them | TrackerSift {[amjad2021_trackersift]} | The measurement that motivated the rest of this row-group | |
| | | 2024 | **Function granularity** with dynamic calling context, plus automatic surrogates | NoT.js {[amjad2024_notjs]} | **Current and where the field is going** | |
| | 2024 | Deployability as a first-class goal — small feature sets, low overhead | AdFlush {[lee2024_adflush]} | **Current.** 27 features selected from 883; F1 0.98 vs AdGraph 0.93 / WebGraph 0.90; 56% less CPU and 80% less memory than AdGraph; F1 stayed above 0.97 over six months without retraining | | | 2024 | Deployability as a first-class goal — small feature sets, low overhead | AdFlush {[lee2024_adflush]} | **Current.** 27 features selected from 883; F1 0.98 vs AdGraph 0.93 / WebGraph 0.90; 56% less CPU and 80% less memory than AdGraph; F1 stayed above 0.97 over six months without retraining | |
| | 2024 | Taint tracking plus entropy, rather than API counts | FP-Tracer {[boussaha2024_tracer]}, PanoptiChrome {[kanyal2024_panoptichrome]} | **Current** for the fingerprinting sub-problem | | | 2024 | Taint tracking plus entropy, rather than API counts | FP-Tracer {[boussaha2024_tracer]}, PanoptiChrome {[kanyal2024_panoptichrome]} | **Current** for the fingerprinting sub-problem | |
| ==== What the corpus cannot tell you, and what we found instead ==== | ==== What the corpus cannot tell you, and what we found instead ==== |
| |
| **LLM-based classification of web scripts is, as of 2026-08-06, essentially absent from the peer-reviewed literature.** A targeted search across PETS 2025/2026, USENIX Security 2025, NDSS 2025/2026, IMC 2025, TheWebConf 2025/2026, CCS 2025 and arXiv found no paper that classifies web scripts as trackers with a language model, or that uses one to summarise a script's privacy-relevant behaviour. The nearest work is adjacent rather than on-point: LLM-aided **deobfuscation** feeding a graph classifier for JavaScript //malware//,((//Breaking Obfuscation: Cluster-Aware Graph with LLM-Aided Recovery for Malicious JavaScript Detection//, [[https://arxiv.org/abs/2507.22447|arXiv:2507.22447]], 2025.)) LLM screening of malicious npm packages, and ''humanify'', which uses a model only to //suggest identifier names// during de-minification.(([[https://github.com/jehna/humanify|github.com/jehna/humanify]], v3.1.1, checked 2026-08-06. The AST rewrite is done by ''oxc''; the model only proposes names.)) | **LLM-based classification of web scripts is, as of 2026-09-03, still absent from the peer-reviewed literature in these seven venues — and this is now a measured zero rather than the result of a keyword search.** ''classification.method == "llm"'' fires on **177 of the 5,859 corpus papers**, but on **0 of the 44 papers that classify a ''javascript'' target and 0 of the 31 that classify a ''fingerprinting-script'' target**. A targeted search outside the corpus — PETS 2025/2026, USENIX Security 2025/2026, NDSS 2025/2026, IMC 2025, TheWebConf 2025/2026, CCS 2025 and arXiv — found no paper that classifies web scripts as trackers with a language model, or that uses one to summarise a script's privacy-relevant behaviour. |
| |
| <wrap todo>Treat this as an opportunity, not a settled answer. If you are planning an LLM-based script classifier, you are not late — but you also have no baseline to cite, so budget for building one, and for the reviewer question about cost, reproducibility and prompt/version drift that this page cannot yet answer for you.</wrap> | **Read that against the corpus-wide curve before concluding the field is not interested.** LLM classification went from 2 papers in 2023 to 71 in the partial 2026 (17.1% of that year), at all seven venues, so the zero above is specific to this target rather than a statement about the method. The per-target table on [[design:website_classification#Where LLMs actually appear]] gives the full ranking; ''javascript'' and ''fingerprinting-script'' are **zero rows** in it, alongside ''malware'', ''sdk-or-library'' and ''website-popularity''. The lowest //non-zero// rows are ''ip-address'' (1 of 295) and ''web-request'' (1 of 258). |
| | |
| | **The nearest peer-reviewed work is one layer down, at the request.** TGNN {[xiong2026_tgnn]} (TheWebConf 2026) uses Qwen3 to label HTTP request/response quadruples as tracking or not, and reports an annotation F1 of **98.17%** against expert labels where filter lists reach **55.14%** on the same ground truth.((The paper reports this figure twice as **98.17%** — in §4.1.3 //LLM-based Labeling// ("𝑀𝜆 performs well (𝐹1-score of 98.17%)") and again beside Figure 5 — and once as **98.19%**, in the contributions paragraph of its Introduction. Its abstract states no F1 for the annotation component at all. The discrepancy is the paper's, not ours; the body figure is quoted here and on [[privacy:requests]], so the two pages agree. The 55.14% filter-list comparison appears only in the Introduction. Located in ''paper.cols.txt'' on 2026-09-03; note that this file contains NUL bytes, so shell ''grep'' reports nothing without ''-a''.)) It is not a script classifier — it explicitly contrasts its approach with prior methods that do "single-domain analysis-such as string matching against domain lists or scrutinizing JavaScript execution within a page" — but it is the closest thing to a citable precedent for using a model to //manufacture tracker labels//, which is this page's weakest link. [[privacy:requests]] treats it in full. Beyond it the adjacent work is not peer-reviewed and not on-point: LLM-aided **deobfuscation** feeding a graph classifier for JavaScript //malware//,((//Breaking Obfuscation: Cluster-Aware Graph with LLM-Aided Recovery for Malicious JavaScript Detection//, [[https://arxiv.org/abs/2507.22447|arXiv:2507.22447]], 2025.)) LLM screening of malicious npm packages, and ''humanify'', which uses a model only to //suggest identifier names// during de-minification.(([[https://github.com/jehna/humanify|github.com/jehna/humanify]], v3.1.1, checked 2026-08-06. The AST rewrite is done by ''oxc''; the model only proposes names.)) |
| | |
| | <WRAP todo>Treat this as an opportunity, not a settled answer. If you are planning an LLM-based script classifier, you are not late — but you also have no baseline to cite, so budget for building one, and for the reviewer question about cost, reproducibility and prompt/version drift that this page cannot yet answer for you. Two things you can borrow rather than invent: TGNN's annotation-versus-filter-list comparison {[xiong2026_tgnn]} is the experimental design a reviewer will expect, and the model-reporting figures on [[design:website_classification#And almost nobody names a model you could resolve]] show that only **19.4%** of the 175 corpus papers that actually use an LLM name a model resolvable to an actual artefact — so naming yours to the checkpoint is cheap novelty.</WRAP> |
| |
| ==== Two 2025 results that change how you design a crawl ==== | ==== Two 2025 results that change how you design a crawl ==== |
| ===== Ground Truth, Which Is This Field's Weakest Link ===== | ===== Ground Truth, Which Is This Field's Weakest Link ===== |
| |
| Of the 160 papers, **153 record at least one classification task**. What they classify //with//: | Of the 206 papers, **198 record at least one classification task**. What they classify //with//: |
| | |
| | ^ ''classification.method'' ^ Papers ^ Share of 198 ^ |
| | | heuristic-rules | 108 | 54.5% | |
| | | manual-labelling | 70 | 35.4% | |
| | | third-party-service | 53 | 26.8% | |
| | | blocklist | 52 | 26.3% | |
| | | curated-database | 40 | 20.2% | |
| | | dynamic-analysis | 33 | 16.7% | |
| | | supervised-ml | 31 | 15.7% | |
| | | regex-or-signature | 27 | 13.6% | |
| | | static-analysis | 25 | 12.6% | |
| | | graph-analysis | 13 | 6.6% | |
| | | other | 11 | 5.6% | |
| | | unsupervised-ml | 11 | 5.6% | |
| | | **llm** | **2** | **1.0%** | |
| |
| ^ ''classification.method'' ^ Papers ^ Share of 153 ^ | **The ''llm'' row does not mean what it looks like it means, and it is worth being precise because two other pages depend on the same field.** The enum is per //paper//, not per JavaScript task: these are two papers in this page's population that used an LLM for //some// classification, and neither classified a script. {[chen2025_semantics]} (TheWebConf 2025) fine-tunes GPT-3.5 to label **cookie** purposes, and PhishLang (NDSS 2026) queried GPT-4 once to pick which **HTML tags** matter for phishing detection. Restricted to script targets the count is **zero** — 0 of the 44 papers classifying ''javascript'' and 0 of the 31 classifying ''fingerprinting-script'' — which is the figure quoted above and the one to cite. On the 4,322-paper corpus this row was empty for either reading. |
| | heuristic-rules | 80 | 52.3% | | |
| | manual-labelling | 54 | 35.3% | | |
| | third-party-service | 47 | 30.7% | | |
| | blocklist | 38 | 24.8% | | |
| | curated-database | 31 | 20.3% | | |
| | supervised-ml | 26 | 17.0% | | |
| | regex-or-signature | 24 | 15.7% | | |
| | dynamic-analysis | 21 | 13.7% | | |
| | static-analysis | 16 | 10.5% | | |
| | unsupervised-ml | 11 | 7.2% | | |
| | graph-analysis | 9 | 5.9% | | |
| | other | 9 | 5.9% | | |
| |
| And what they treat as truth. These 153 papers produce **278 distinct free-text ground-truth strings**, folded here into families; 52 tuples did not fold and are printed by the report script. | And what they treat as truth. These 198 papers produce **351 distinct free-text ground-truth strings**, folded here into families; 80 tuples did not fold and are printed by the report script. |
| |
| ^ Ground-truth family ^ Papers ^ Share of 153 ^ | ^ Ground-truth family ^ Papers ^ Share of 198 ^ |
| | **Authors' own manual inspection** | 84 | **54.9%** | | | **Authors' own manual inspection** | 102 | **51.5%** | |
| | Filter list or tracker database | 36 | 23.5% | | | Filter list or tracker database | 44 | 22.2% | |
| | Malware / phishing blacklist service | 11 | 7.2% | | | Malware / phishing blacklist service | 13 | 6.6% | |
| | Vulnerability database | 7 | 4.6% | | | Synthetic or seeded ground truth | 9 | 4.5% | |
| | Synthetic or seeded ground truth | 5 | 3.3% | | | Vulnerability database | 9 | 4.5% | |
| | Prior published dataset or labels | 4 | 2.6% | | | Spec or documentation | 5 | 2.5% | |
| | Spec or documentation | 3 | 2.0% | | | Prior published dataset or labels | 4 | 2.0% | |
| | Library signature catalogue | 1 | 0.7% | | | Library signature catalogue | 1 | 0.5% | |
| | Recruited or external annotators | 1 | 0.7% | | | Recruited or external annotators | 1 | 0.5% | |
| |
| <WRAP important> | <WRAP important> |
| **The most common ground truth for "is this script a tracker" is the authors reading the script.** That is a defensible choice at small scale and it is what most of this field does — but it means the labels are unpublished, unaudited and, in most cases, produced by the same people who built the classifier. Only 36 of 153 papers anchor to a filter list or tracker database, and exactly one used annotators from outside the author team. | **The most common ground truth for "is this script a tracker" is the authors reading the script.** That is a defensible choice at small scale and it is what most of this field does — but it means the labels are unpublished, unaudited and, in most cases, produced by the same people who built the classifier. Only 44 of 198 papers anchor to a filter list or tracker database, and exactly one used annotators from outside the author team. |
| </WRAP> | </WRAP> |
| |
| Validation, counted per paper rather than per tuple: **115 of 153 (75.2%) report some validation** for at least one classification, and **38 (24.8%) report none anywhere**. Where validation exists it is overwhelmingly more manual inspection (102 papers, 66.7%); comparison to another method 22 (14.4%), cross-validation 14 (9.2%), a held-out test set 9 (5.9%). | Validation, counted per paper rather than per tuple: **146 of 198 (73.7%) report some validation** for at least one classification, and **52 (26.3%) report none anywhere**. Where validation exists it is overwhelmingly more manual inspection (129 papers, 65.2%); comparison to another method 33 (16.7%), cross-validation 16 (8.1%), a held-out test set 12 (6.1%). |
| |
| ==== If you use a filter list as ground truth ==== | ==== If you use a filter list as ground truth ==== |
| | Static AST / bytecode | what the code //could// do, on code you never executed | what it actually did, and anything behind ''eval'' | | | Static AST / bytecode | what the code //could// do, on code you never executed | what it actually did, and anything behind ''eval'' | |
| |
| Which of these the 160 papers actually name: | Which of these the 206 papers actually name: |
| |
| ^ Tool family ^ Papers ^ Share of 160 ^ | ^ Tool family ^ Papers ^ Share of 206 ^ |
| | OpenWPM | 17 | 10.6% | | | Esprima | 21 | 10.2% | |
| | Esprima | 16 | 10.0% | | | OpenWPM | 19 | 9.2% | |
| | VisibleV8 | 8 | 5.0% | | | PageGraph | 8 | 3.9% | |
| | js-beautify | 7 | 4.4% | | | Project Foxhound (taint tracking) | 8 | 3.9% | |
| | V8 (as an analysis substrate) | 5 | 3.1% | | | VisibleV8 | 8 | 3.9% | |
| | Closure Compiler | 4 | 2.5% | | | js-beautify | 7 | 3.4% | |
| | FP-Inspector | 4 | 2.5% | | | V8 (as an analysis substrate) | 7 | 3.4% | |
| | PageGraph | 4 | 2.5% | | | Closure Compiler | 5 | 2.4% | |
| | WABT | 3 | 1.9% | | | Babel, FP-Inspector, Jalangi, WABT | 4 each | 1.9% | |
| | Babel, jsdom, JStap, Project Foxhound | 2 each | 1.3% | | | JStap | 3 | 1.5% | |
| | Acorn, AdGraph, Emscripten, Jalangi, JSgraph, JSNice, Khaleesi, Rhino, SpiderMonkey, TAJS, UglifyJS, unnamed deobfuscator | 1 each | 0.6% | | | jsdom | 2 | 1.0% | |
| | | Acorn, AdGraph, Emscripten, JSgraph, JSNice, Khaleesi, Rhino, SpiderMonkey, TAJS, UglifyJS, unnamed deobfuscator | 1 each | 0.5% | |
| |
| **91 of 160 papers (56.9%) name no JavaScript-analysis tool at all** — they wrote their own parser, regexes or instrumentation and did not name it. That is the field's reproducibility problem in one number. | Two rows moved enough to matter. **Esprima has overtaken OpenWPM** as the most-named tool, and **Project Foxhound went from 2 papers to 8 and PageGraph from 4 to 8** — the taint-tracking and page-graph instruments the //Methods// table above calls current are the ones the 2025–2026 papers actually picked up. That is the rare case where the corpus confirms a currency judgement instead of only dating it. |
| | |
| | **120 of 206 papers (58.3%) name no JavaScript-analysis tool at all** — they wrote their own parser, regexes or instrumentation and did not name it. That is the field's reproducibility problem in one number. |
| |
| ==== Maintenance status, because half of these are frozen ==== | ==== Maintenance status, because half of these are frozen ==== |
| |
| - **Minification** is near-universal and destroys the identifier names your features probably depend on. Skolka et al. {[skolka2019_anything]} found **38.5% of all crawled scripts** had gone through some transformation. | - **Minification** is near-universal and destroys the identifier names your features probably depend on. Skolka et al. {[skolka2019_anything]} found **38.5% of all crawled scripts** had gone through some transformation. |
| - **Obfuscation proper is rare but definitionally contested.** The same study puts deliberate obfuscation at **0.67% of scripts (2,842)**; Sarker et al. {[sarker2020_hiding]} — defining it as invoking APIs that static analysis cannot resolve — put it at **95.90% of Alexa top-100K domains loading at least one obfuscated script**, with 5,028 distinct obfuscated scripts calling ''eval''. Both are correct. Report your definition and your unit or the number means nothing. | - **Obfuscation proper is rare but definitionally contested.** The same study puts deliberate obfuscation at **0.67% of scripts (2,842)**; Sarker et al. {[sarker2020_hiding]} — defining it as invoking APIs that static analysis cannot resolve — put it at **95.90% of domains loading at least one obfuscated script** — where the denominator is the 77,423 Alexa top-100K domains for which they obtained script data at all, so ~74% of the top 100K rather than 95.9% of it, with 5,028 distinct obfuscated scripts calling ''eval''. Both are correct. Report your definition and your unit or the number means nothing. |
| - **Bundling** merges unrelated code into one artifact — 40% of sites {[rack2023_jackinthebox]}. | - **Bundling** merges unrelated code into one artifact — 40% of sites {[rack2023_jackinthebox]}. |
| - **Dynamic code** defeats it outright. Forced-execution engines exist precisely for this: J-Force, and more recently FV8 {[pantelaios2024_fv8]}, which forcibly executes conditional branches to reveal evasive behaviour and surfaced 28 evasion categories across npm packages and browser extensions. | - **Dynamic code** defeats it outright. Forced-execution engines exist precisely for this: J-Force, and more recently FV8 {[pantelaios2024_fv8]}, which selectively forces execution of the APIs that conditionally inject dynamic code (''eval'', ''setTimeout'' and friends) to reveal evasive behaviour and surfaced 28 evasion categories across npm packages and browser extensions. |
| |
| If you must analyse statically, the current toolchain is Acorn or ''@babel/parser'' for the AST, ''swc''/''meriyah'' when speed matters, and one of the live deobfuscators (''webcrack'', ''synchrony'', ''restringer'') as a preprocessing step — all four checked active in 2026. Bytecode {[ghasemisharif2023_bytecode]}{[bahrami2025_bytedefender]} is the interesting alternative: it survives source-level obfuscation because it is what the engine actually compiled. | If you must analyse statically, the current toolchain is Acorn or ''@babel/parser'' for the AST, ''swc''/''meriyah'' when speed matters, and one of the live deobfuscators (''webcrack'', ''synchrony'', ''restringer'') as a preprocessing step — all four checked active in 2026. Bytecode {[ghasemisharif2023_bytecode]}{[bahrami2025_bytedefender]} is the interesting alternative: it survives source-level obfuscation because it is what the engine actually compiled. |
| ===== Crawl Methodology, Against the Corpus ===== | ===== Crawl Methodology, Against the Corpus ===== |
| |
| Of the 160 papers, 128 (80.0%) ran a crawl and 126 recorded a configuration. They report better than the corpus average on every axis — and still leave the two axes that matter most for this topic largely unstated. | Of the 206 papers, 165 (80.1%) ran a crawl and 163 recorded a configuration. They report better than the corpus average on every axis — and still leave the two axes that matter most for this topic largely unstated. |
| |
| ^ ''crawlConfig'' field ^ States a value ^ Share of 126 ^ All 829 crawling papers ^ | ^ ''crawlConfig'' field ^ States a value ^ Share of 163 ^ All 1,080 papers with a crawl configuration ^ |
| | Statefulness | 36 | 28.6% | 19.9% | | | Statefulness | 45 | 27.6% | 20.3% | |
| | Interaction depth | 112 | 88.9% | 78.6% | | | Interaction depth | 147 | 90.2% | 77.9% | |
| | Consent action | 65 | 51.6% | 32.6% | | | Consent action | 79 | 48.5% | 32.3% | |
| | Headless or headful | 28 | 22.2% | 13.4% | | | Headless or headful | 31 | 19.0% | 13.0% | |
| | Authentication | 104 | 82.5% | 71.5% | | | Authentication | 134 | 82.2% | 72.1% | |
| | Browser named | 101 | 80.2% | 47.6% | | | Browser named | 132 | 81.0% | 49.0% | |
| |
| <WRAP important> | <WRAP important> |
| **22.2% state headless-or-headful, and for this topic that is not a formality.** Two measurements in the corpus quantify the cost: | **19.0% state headless-or-headful, and for this topic that is not a formality.** Two measurements in the corpus quantify the cost: |
| |
| * Jueckstock et al. {[jueckstock2021_realistic]} found about **10% of script families show consistent browser-configuration bias**, and traced one concretely: Crazyegg's script invoked **fewer than 15 browser APIs under a naive crawl but nearly 60 under a stealth crawl**, because a function named ''uaBot'' short-circuits on bot detection. A naive crawl does not under-count that script — it observes a **different program**. | * Jueckstock et al. {[jueckstock2021_realistic]} found about **10% of script families show consistent browser-configuration bias**, and traced one concretely: Crazyegg's script invoked **fewer than 15 browser APIs under a naive crawl but nearly 60 under a stealth crawl**, because a function named ''uaBot'' short-circuits on bot detection. A naive crawl does not under-count that script — it observes a **different program**. |
| * FP-Fed {[annamalai2024_fpfed]} found manual browsing captured **3.07× more fingerprinting scripts** than automated crawlers on the same sites. | * FP-Fed {[annamalai2024_fpfed]} found that a real user logging in and completing an **authentication flow** encountered **3.07× more fingerprinting scripts** than its automated crawlers did. |
| |
| Add Zafar et al.'s 20.6% platform-divergent scripts {[zafar2025_samescript]} and the conclusion is unavoidable: **the scripts you most want to classify are the ones deciding what to show you.** See [[Programming:Crawler]] on detectability and [[Design:Crawling location]] on the vantage-point half of the same problem. | Add Zafar et al.'s 20.6% platform-divergent scripts {[zafar2025_samescript]} and the conclusion is unavoidable: **the scripts you most want to classify are the ones deciding what to show you.** See [[Programming:Crawler]] on detectability and [[Design:Crawling location]] on the vantage-point half of the same problem. |
| </WRAP> | </WRAP> |
| |
| Artifact release is a bright spot: **46 of the 59 papers from 2022–2024 (78.0%) released an artifact link, against 64.7% for the corpus over the same years.** Only 13 of 160 (8.1%) assess a law — GDPR in 11 — against 6.1% corpus-wide, and 19 (11.9%) recruited participants. | **The consent row deserves its own sentence.** On EU-facing sites a large part of the advertising and analytics stack is loaded by the consent management platform //after// a consent click, so a crawl that never interacts with the banner measures a different script population from one that accepts — and a third one from one that rejects. Half these papers do not say which they did. Decide deliberately, state it, and see [[Privacy:Consent]] for how to drive the interaction; the same choice is what makes [[Privacy:Cookies]] figures comparable or not. |
| | |
| | Artifact release is a bright spot: **53 of the 68 papers from 2022–2024 (77.9%) released an artifact link, against 65.0% for the corpus over the same years**, and 27 of 29 (93.1%) in the provisional 2025–2026 window against 76.5%. Only 19 of 206 (9.2%) assess a law — GDPR in 17 — against 6.9% corpus-wide (402 of 5,859), and 24 (11.7%) recruited participants. |
| |
| ===== What to Report ===== | ===== What to Report ===== |
| - **The crawl.** Browser and version, headless or headful, stateful or stateless, consent action, interaction depth, vantage point, and — because of the results above — whether you checked for divergent behaviour under a stealth or headful configuration. | - **The crawl.** Browser and version, headless or headful, stateful or stateless, consent action, interaction depth, vantage point, and — because of the results above — whether you checked for divergent behaviour under a stealth or headful configuration. |
| - **Handling of what you could not analyse.** Inline scripts, ''eval''-generated code, workers, WebAssembly, ''blob:''/''data:'' sources, and scripts that deleted themselves. Report the count you dropped rather than letting it vanish into the denominator. | - **Handling of what you could not analyse.** Inline scripts, ''eval''-generated code, workers, WebAssembly, ''blob:''/''data:'' sources, and scripts that deleted themselves. Report the count you dropped rather than letting it vanish into the denominator. |
| - **Reproducibility.** The script corpus if licensing allows, the feature extractor, and the trained model. This subfield is good at this — 78% since 2022 — so a paper without it stands out. | - **Reproducibility.** The script corpus if licensing allows, the feature extractor, and the trained model. This subfield is good at this — 78% for 2022–2024 and higher since — so a paper without it stands out. |
| |
| ===== Reproducing These Figures ===== | ===== Reproducing These Figures ===== |
| Three families are in the tool table but deliberately excluded from the //membership// rule, because their non-analysis use is large and it was measured rather than assumed: OpenWPM alone dragged in an IPv6-scanning study, a QUIC website-fingerprinting paper and an HSTS study that used it as a plain crawler; Emscripten dragged in two papers that //compiled to// WebAssembly; SpiderMonkey dragged in RIDL, where the engine is the victim of a CPU attack. Three further papers — Spectre, Fallout and RIDL — were removed by hand after reading, with the reason recorded inline in the script: JavaScript is their exploit vector, not their object of study. | Three families are in the tool table but deliberately excluded from the //membership// rule, because their non-analysis use is large and it was measured rather than assumed: OpenWPM alone dragged in an IPv6-scanning study, a QUIC website-fingerprinting paper and an HSTS study that used it as a plain crawler; Emscripten dragged in two papers that //compiled to// WebAssembly; SpiderMonkey dragged in RIDL, where the engine is the victim of a CPU attack. Three further papers — Spectre, Fallout and RIDL — were removed by hand after reading, with the reason recorded inline in the script: JavaScript is their exploit vector, not their object of study. |
| |
| ^ Signal combination ^ Papers ^ Share of 160 ^ | ^ Signal combination ^ Papers ^ Share of 206 ^ |
| | classification only | 43 | 26.9% | | | classification only | 57 | 27.7% | |
| | detection only | 42 | 26.3% | | | detection only | 53 | 25.7% | |
| | detection + classification | 23 | 14.4% | | | detection + classification | 30 | 14.6% | |
| | tool only | 21 | 13.1% | | | tool only | 26 | 12.6% | |
| | tool + detection + classification | 12 | 7.5% | | | tool + detection + classification | 19 | 9.2% | |
| | tool + detection | 11 | 6.9% | | | tool + detection | 13 | 6.3% | |
| | tool + classification | 8 | 5.0% | | | tool + classification | 8 | 3.9% | |
| |
| The whole rule, including every fold and the reason for each hand exclusion, is below. It needs only ''extractions.jsonl'' and the shared ''lib.mjs'' helper; the companion ''report_javascript.mjs'' prints every figure on this page with its denominator, the residue of each fold, and the full 160-paper list. | The whole rule, including every fold and the reason for each hand exclusion, is below. It needs only ''extractions.jsonl'' and the shared ''lib.mjs'' helper; the companion ''report_javascript.mjs'' prints every figure on this page with its denominator, the residue of each fold, and the full 206-paper list. Every query behind this section is on [[provenance:privacy:javascript]]; corpus-level caveats are on [[literature:corpus]]. |
| |
| <file javascript js_fold.mjs> | <file javascript js_fold.mjs> |
| // JavaScript a page runs". Neither of the obvious schema handles answers it: | // JavaScript a page runs". Neither of the obvious schema handles answers it: |
| // | // |
| // * `tools[].category == "program-analysis"` fires on 974 papers, but that | // * `tools[].category == "program-analysis"` fires on 1,385 papers (used or |
| // category is dominated by binary, Android and smart-contract analysis | // produced), but that category is dominated by binary, Android and |
| // (LLVM 66, Soot 62, FlowDroid 40, IDA Pro 39, angr 32). Esprima, the | // smart-contract analysis (LLVM 101, Soot 81, IDA Pro 62, FlowDroid 48, |
| // highest-ranked JavaScript parser, is 16. | // angr 39). Esprima, the highest-ranked JavaScript parser, is 23. |
| // * `studyTypes` includes `code-or-binary-analysis` on 1,063 papers, same | // * `studyTypes` includes `code-or-binary-analysis` on 1,484 papers, same |
| // problem, and it is the least reproducible field in the schema (57%). | // problem, and it is the least reproducible field in the schema (57%). |
| // | // |
| |
| // --------------------------------------------------------------------------- | // --------------------------------------------------------------------------- |
| // Ground-truth sources for a script-classification task. 278 distinct strings | // Ground-truth sources for a script-classification task. 351 distinct strings |
| // across the population, so again a RANKING. Ordered; first match wins, with | // across the population, so again a RANKING. Ordered; first match wins, with |
| // the named external resources ahead of the generic "manual" phrasings, | // the named external resources ahead of the generic "manual" phrasings, |
| ==== Methodology and limitations of these figures ==== | ==== Methodology and limitations of these figures ==== |
| |
| * **Seven venues only.** CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf, IEEE S&P, 2010–2024. IEEE S&P is only 43% retrieved, and **EuroS&P, ACSAC, RAID, AsiaCCS, CHI and SOUPS are absent entirely** — for this topic ACSAC and EuroS&P are a real hole, since a good deal of web-script security work lands there. Every claim here is a claim about those seven venues. | * **Seven venues only**, 2010–2026, with 2025 and 2026 provisional. Which venues, which years, what each stage of the selection funnel costs and which venue-years are empty are on [[literature:corpus]] and are not restated here. For //this// topic ACSAC and EuroS&P are a real hole, since a good deal of web-script security work lands there. Every claim here is a claim about those seven venues. |
| * **160 is a floor, and it has a false-positive tail.** Papers whose extraction never names a script as the object of detection are missing; conversely a handful of papers in the population (an e-voting client audit, a router-attack paper, a PHP injection-sink study) analyse JavaScript incidentally. The report script prints the full list so you can judge. | * **206 is a floor, and it has a false-positive tail.** Papers whose extraction never names a script as the object of detection are missing; conversely a handful of papers in the population (an e-voting client audit, a router-attack paper, a PHP injection-sink study) analyse JavaScript incidentally. The report script prints the full list so you can judge. |
| * **Enums carry percentages; free text carries rankings.** ''classification.method'', ''crawlConfig.*'', ''legal.law'' and ''platforms'' reproduce to within a few points on a repeat extraction. ''detection.phenomenon'', ''classification.resourceName'' and ''groundTruthSource'' agree on roughly 20% of exact strings between runs — which is what the folding is for, and why the family and ground-truth tables print their residue. | * **Not every field can carry a percentage.** ''crawlConfig.*'', ''legal.law'' and ''platforms'' reproduce to within a few points on a repeat extraction and carry the figures here. ''classification.method'' agrees on only **58%** of papers between two runs of the same schema over the same text, so its table above is a **rough share, not a precise figure** — a repeat extraction moves those rows. ''detection.phenomenon'', ''classification.resourceName'' and ''groundTruthSource'' agree on roughly 20% of exact strings, which is what the folding is for and why the family and ground-truth tables print their residue. |
| * **Silence is not absence.** "Does not state whether it ran headless" means the paper did not say. These are reporting figures, not practice figures. | * **Silence is not absence.** "Does not state whether it ran headless" means the paper did not say. These are reporting figures, not practice figures. |
| * **Every quoted figure was checked against the paper's own text.** The prevalence values in the extraction are model summaries, so each number reproduced on this page was re-located in ''paper.cols.txt'' after whitespace normalisation. 0.9% of quotes in the dataset cannot be located in their source at all. | * **Every quoted figure was checked against the paper's own text.** The prevalence values in the extraction are model summaries, so each number reproduced on this page was re-located in ''paper.cols.txt'' after whitespace normalisation. The dataset's own "0.9% of quotes cannot be located" figure was measured on the earlier 4,322-paper run and has not been re-measured. |
| | * **Every query behind this section, the report script and its unedited output** are on [[provenance:privacy:javascript]]; corpus-level caveats are on [[literature:corpus]]. |
| |
| ===== Open Questions ===== | ===== Open Questions ===== |
| |
| * <wrap todo>**No public, hand-labelled corpus of tracking scripts exists.** Every current method builds its own labels from filter lists plus manual inspection, which is why cross-paper comparison is impossible. A shared benchmark would do for this field what EasyList did for request blocking.</wrap> | <WRAP todo> |
| * <wrap todo>**LLM-based script classification is unmeasured.** No peer-reviewed paper found as of 2026-08-06. The obvious study — LLM against WebGraph, AdFlush and NoT.js on a fixed script corpus, reporting cost and version drift as well as F1 — has no baseline yet.</wrap> | * **No public, hand-labelled corpus of tracking scripts exists.** Every current method builds its own labels from filter lists plus manual inspection, which is why cross-paper comparison is impossible. A shared benchmark would do for this field what EasyList did for request blocking. |
| * <wrap todo>**Nobody has measured how much a headless or containerised crawler under-counts //script// classification specifically.** {[jueckstock2021_realistic]} and {[annamalai2024_fpfed]} show the gap exists for API traces and fingerprinting scripts; its size for tracking-script prevalence at scale is unknown.</wrap> | * **LLM-based script classification is unmeasured.** Zero of the 44 corpus papers that classify a ''javascript'' target and zero of the 31 that classify a ''fingerprinting-script'' target use one, re-derived 2026-09-03, and no peer-reviewed paper outside the corpus was found either. The obvious study — LLM against WebGraph, AdFlush and NoT.js on a fixed script corpus, reporting cost and version drift as well as F1 — still has no baseline. The nearest template is TGNN's request-level annotation experiment {[xiong2026_tgnn]}, which beat filter lists 98.17% to 55.14% F1 on expert-labelled ground truth; the same comparison at script granularity has not been run. |
| * <wrap todo>**Function-granularity blocking has no successor paper.** NoT.js {[amjad2024_notjs]} and ByteDefender {[bahrami2025_bytedefender]} both stop at detection plus surrogate generation; nobody has measured what happens when either is deployed to real users at scale, or whether trackers adapt.</wrap> | * **Nobody has measured how much a headless or containerised crawler under-counts //script// classification specifically.** {[jueckstock2021_realistic]} and {[annamalai2024_fpfed]} show the gap exists for API traces and fingerprinting scripts; its size for tracking-script prevalence at scale is unknown. |
| * <wrap todo>**Cross-platform divergence is a confound in every older result.** If 20.6% of scripts execute differently by platform {[zafar2025_samescript]}, every desktop-only prevalence figure in this page's tables is a measurement of the desktop path only. Re-running any of them on mobile is a well-defined study.</wrap> | * **Function-granularity blocking has no successor paper.** NoT.js {[amjad2024_notjs]} and ByteDefender {[bahrami2025_bytedefender]} both stop at detection plus surrogate generation; nobody has measured what happens when either is deployed to real users at scale, or whether trackers adapt. |
| | * **Cross-platform divergence is a confound in every older result.** If 20.6% of scripts execute differently by platform {[zafar2025_samescript]}, every desktop-only prevalence figure in this page's tables is a measurement of the desktop path only. Re-running any of them on mobile is a well-defined study. |
| | </WRAP> |
| |
| ===== Related Pages ===== | ===== Related Pages ===== |
| * [[Privacy:Requests]] — classifying at the request/URL layer, where filter lists live, and why they cap this page's ground truth. | * [[Privacy:Requests]] — classifying at the request/URL layer, where filter lists live, and why they cap this page's ground truth. |
| * [[Privacy:Cookies]] — what the scripts write; the provenance argument (a cookie set by a blocked resource) is the same idea one layer down. | * [[Privacy:Cookies]] — what the scripts write; the provenance argument (a cookie set by a blocked resource) is the same idea one layer down. |
| * [[Privacy:Fingerprinting]] — 42.4% of browser-fingerprinting papers are really detecting //scripts//, so that page and this one share a method. | * [[Privacy:Fingerprinting]] — 39.8% of browser-fingerprinting papers are really detecting //scripts//, so that page and this one share a method. |
| * [[Programming:Crawler]] — the instrumentation this page assumes you already have, compared in detail, including [[Programming:Crawler:OpenWPM]], [[Programming:Crawler:PageGraph]] and [[Programming:Crawler:Foxhound]]. | * [[Programming:Crawler]] — the instrumentation this page assumes you already have, compared in detail. Its per-tool pages [[Programming:Crawler:OpenWPM]] and [[Programming:Crawler:PageGraph]] are written; [[Programming:Crawler:Foxhound]] is still promised. |
| * [[Programming:Stateful stateless]] — only 28.6% of these papers state it, and a stateless crawl sees first-visit script behaviour only. | * [[Programming:Stateful stateless]] — only 27.6% of these papers state it, and a stateless crawl sees first-visit script behaviour only. |
| * [[Design:Website classification]] — where script classification sits in the wider taxonomy. | * [[Design:Website classification]] — where script classification sits in the wider taxonomy. |
| * [[Design:Crawling location]] — the vantage-point half of the "the site served you different code" problem. | * [[Design:Crawling location]] — the vantage-point half of the "the site served you different code" problem. |