| Next revision | Previous revision |
| provenance:privacy:javascript [2026/08/12 09:35] – Create provenance page for privacy:javascript: the three-signal population rule and how it scaled, why js_fold aged well where fp_fold did not, two report-script bugs, quote verification, and the 4,322 -> 5,859 refresh diff. Partly reconstructed; marked a karel.kubicek.claude | provenance:privacy:javascript [2026/09/21 14:32] (current) – Foxhound count errata 2026-09-21: Foxhound 8 -> 9 (4.4%), no-tool 120 -> 119, the js_fold.mjs override that produced it. Authored by Claude karel.kubicek.claude |
|---|
| ^ Item ^ Value ^ | ^ Item ^ Value ^ |
| | Content page | [[privacy:javascript]] | | | Content page | [[privacy:javascript]] | |
| | Report script | ''scripts/report_javascript.mjs'' (''--wiki'' for DokuWiki tables, ''--list'' for the full paper list) | | | Report script | ''scripts/report_javascript.mjs'' (''%%--wiki%%'' for DokuWiki tables, ''%%--list%%'' for the full paper list) | |
| | Population rule and folds | ''scripts/js_fold.mjs'' | | | Population rule and folds | ''scripts/js_fold.mjs'' | |
| | Quote verification | ''scripts/quote_check.mjs --classification javascript'' | | | Quote verification | ''scripts/quote_check.mjs %%--classification%% javascript'' | |
| | Data | ''data/extract/run1/extractions.jsonl'', 5,859 papers, 7 venues, 2010–2026 | | | Data | ''data/extract/run1/extractions.jsonl'', 5,859 papers, 7 venues, 2010–2026 | |
| | Refreshed | 2026-08-12 | | | Refreshed | 2026-08-12 | |
| | Esprima (tool, in population) | 16 (10.0%) | 21 (10.2%) | | | Esprima (tool, in population) | 16 (10.0%) | 21 (10.2%) | |
| | OpenWPM (tool, in population) | 17 (10.6%) | 19 (9.2%) | | | OpenWPM (tool, in population) | 17 (10.6%) | 19 (9.2%) | |
| | **Project Foxhound** | **2 (1.3%)** | **8 (3.9%)** | | | **Project Foxhound** | **2 (1.3%)** | **9 (4.4%)**((Published as 8 (3.9%) until the Foxhound count errata of 2026-09-21, at the foot of this page.)) | |
| | **PageGraph** | **4 (2.5%)** | **8 (3.9%)** | | | **PageGraph** | **4 (2.5%)** | **8 (3.9%)** | |
| | Jalangi | 1 | 4 | | | Jalangi | 1 | 4 | |
| | Names no JS-analysis tool at all | 91 of 160 (56.9%) | 120 of 206 (58.3%) | | | Names no JS-analysis tool at all | 91 of 160 (56.9%) | 119 of 206 (57.8%)((Same errata: published as 120 of 206 (58.3%) until 2026-09-21.)) | |
| | ''heuristic-rules'' | 80 (52.3%) | 108 (54.5%) | | | ''heuristic-rules'' | 80 (52.3%) | 108 (54.5%) | |
| | ''dynamic-analysis'' | 21 (13.7%) | 33 (16.7%) | | | ''dynamic-analysis'' | 21 (13.7%) | 33 (16.7%) | |
| **Moved by more than a rounding step:** | **Moved by more than a rounding step:** |
| |
| * **Project Foxhound 2 → 8 and PageGraph 4 → 8.** This is the substantive finding of the refresh for this page, and it is unusual: the //Methods// table calls taint tracking and page-execution graphs "current" on the basis of work //outside// the corpus, and the extended corpus now independently shows those two instruments growing fastest inside it. A currency judgement that was an editorial call in August 2026 now has partial corpus support. The page says so. | * **Project Foxhound 2 → 9 and PageGraph 4 → 8.**((The Foxhound figure read 8 when this section was written; see the errata of 2026-09-21 below. The 2 is the pre-extension corpus and is unaffected — the paper the errata adds is from NDSS 2025, which that corpus did not reach.)) This is the substantive finding of the refresh for this page, and it is unusual: the //Methods// table calls taint tracking and page-execution graphs "current" on the basis of work //outside// the corpus, and the extended corpus now independently shows those two instruments growing fastest inside it. A currency judgement that was an editorial call in August 2026 now has partial corpus support. The page says so. |
| * **Esprima overtook OpenWPM** as the most-named tool in the population, 21 to 19. Small numbers; reported as a ranking. | * **Esprima overtook OpenWPM** as the most-named tool in the population, 21 to 19. Small numbers; reported as a ranking. |
| * **The ''llm'' classification method fired for the first time, twice.** Recorded on the page next to the existing, still-accurate finding that no peer-reviewed paper classifies web scripts //as trackers// with a language model. Two papers using an LLM for some script-classification task is not the same claim. | * **The ''llm'' classification method fired for the first time, twice.** Recorded on the page next to the existing, still-accurate finding that no peer-reviewed paper classifies web scripts //as trackers// with a language model. Two papers using an LLM for some script-classification task is not the same claim. |
| ===== 6. Quotes checked ===== | ===== 6. Quotes checked ===== |
| |
| //Recorded, 2026-08-12.// | //Recorded, 2026-08-12. Re-run 2026-09-21 with the PDF fallback — see //Quote-check refresh, 2026-09-21// at the foot of this page.// |
| |
| <code> | <code> |
| $ node scripts/quote_check.mjs --classification javascript | $ node scripts/quote_check.mjs --classification javascript --show 400 |
| 66 quotes checked: 34 exact, 19 partial (>=60% of 5-word windows), | 66 quotes checked: 34 exact, 19 partial (>=60% of 5-word windows), 12 rescued from the PDF, 1 below threshold in both renderings, 0 with no full text on disk. |
| 13 below threshold, 0 with no full text on disk. | |
| </code> | </code> |
| |
| Five of the 13 below-threshold quotes were read by hand against ''paper.cols.txt'' — ''2013/USENIX/revolver'', ''2017/IMC/the-ad-wars'', ''2017/PETS/towards-seamless-tracking-free-web'', ''2011/CCS/fortifying-web-based-applications'', ''2012/USENIX/privilege-separation-in-html5-applications'' — and **all five are present**. The last is a good example of why the automated test cannot be trusted alone; the source reads: | **The old figure was 13 below threshold. Twelve of the 13 are a defect in the stored text, not in the extraction** — they are located in an independent ''pypdf'' rendering of the same ''paper.pdf''. **One** quote is below threshold in both renderings: ''IEEE-SP/2012/rozzle-de-cloaking-internet-malware'' at 58%, //"The set contains 2,373 JavaScript files that were flagged by Zozzle, a static malicious JavaScript detector"//, which has **not** been read by hand. ''exact'' (34) and ''partial'' (19) did not move. |
| | |
| | Five of the then-13 were read by hand against ''paper.cols.txt'' — ''2013/USENIX/revolver'', ''2017/IMC/the-ad-wars'', ''2017/PETS/towards-seamless-tracking-free-web'', ''2011/CCS/fortifying-web-based-applications'', ''2012/USENIX/privilege-separation-in-html5-applications'' — and **all five are present**. **All five are also among the 12 the fallback rescues**, which is the strongest agreement between hand and script of any page in this sweep. The last is a good example of why the automated test could not be trusted alone; the source reads: |
| |
| <code> | <code> |
| </code> | </code> |
| |
| The extraction's "we (conservatively) identify all calls to privileged APIs (i.e., calls to the chrome object)" is correct; the two columns interleave inside the parenthesis. **The other 8 were not read.** | The extraction's "we (conservatively) identify all calls to privileged APIs (i.e., calls to the chrome object)" is correct; the two columns interleave inside the parenthesis — which is exactly the failure the PDF fallback undoes. **The other 8 were not read, and 7 of those 8 are now rescued; the unread remainder is the single Rozzle quote above.** |
| |
| //Reconstructed:// the original run recorded that "each number reproduced on this page was re-located in ''paper.cols.txt'' after whitespace normalisation", which is a stronger claim than the one above and applies to the //quoted prevalence figures// rather than to the schema tuples. Which numbers is not recoverable. One specific check from that run **is** recorded and is worth repeating here because it is the page's best cautionary tale: | //Reconstructed:// the original run recorded that "each number reproduced on this page was re-located in ''paper.cols.txt'' after whitespace normalisation", which is a stronger claim than the one above and applies to the //quoted prevalence figures// rather than to the schema tuples. Which numbers is not recoverable. One specific check from that run **is** recorded and is worth repeating here because it is the page's best cautionary tale: |
| * **Whether the 8 unread below-threshold quotes check out.** See §6. | * **Whether the 8 unread below-threshold quotes check out.** See §6. |
| * **Whether the per-1,000 decline is real.** The series peaks at 44.2 in 2014–2017 and falls to 24.5 in 2025–2026, but the last point is provisional and the page's own explanation — the topic being absorbed into tracking and supply-chain papers that no longer call themselves JavaScript analysis — is an interpretation the extraction cannot test. | * **Whether the per-1,000 decline is real.** The series peaks at 44.2 in 2014–2017 and falls to 24.5 in 2025–2026, but the last point is provisional and the page's own explanation — the topic being absorbed into tracking and supply-chain papers that no longer call themselves JavaScript analysis — is an interpretation the extraction cannot test. |
| * **The false-positive tail of the 206.** An e-voting client audit, a router-attack paper and a PHP injection-sink study are in the population and analyse JavaScript incidentally. They were left in and the page says so; ''--list'' prints them all so a reader can judge. Nobody has audited the list paper by paper on the new corpus. | * **The false-positive tail of the 206.** An e-voting client audit, a router-attack paper and a PHP injection-sink study are in the population and analyse JavaScript incidentally. They were left in and the page says so; ''%%--list%%'' prints them all so a reader can judge. Nobody has audited the list paper by paper on the new corpus. |
| * **Whether ''classification.method'' shares are worth publishing at all.** 58% run-to-run agreement is the weakest field carrying a table on this page. It is labelled as a rough share, which is the most that can honestly be done with it. | * **Whether ''classification.method'' shares are worth publishing at all.** 58% run-to-run agreement is the weakest field carrying a table on this page. It is labelled as a rough share, which is the most that can honestly be done with it. |
| * **ACSAC and EuroS&P are absent** and a good deal of web-script security work lands there. Stated on the page. | * **ACSAC and EuroS&P are absent** and a good deal of web-script security work lands there. Stated on the page. |
| |
| ===== 9. Run log ===== | ===== 10. Review pass, 2026-08-12 ===== |
| | |
| | //Recorded.// The refresh was reviewed by a second model (Claude Fable 5), told explicitly that the summary it was given might not be exhaustive, with instructions to hunt stale numbers. It found a **systematic defect, not a scatter of typos**, and it is worth stating because it will recur on the next refresh: |
| | |
| | * ''check_page_numbers.mjs'' was run with a **heading window** — normally ''Use in Publications'' to the next section — so it audited only the corpus section. Every corpus figure repeated in a page's **intro, tooling section, recommendations, footnotes, Related Pages or an embedded code block** was outside the window and stayed at its 4,322-corpus value. Across the six pages **29 such figures** survived the first pass. |
| | * The matcher was **substring**, not word-boundary, so ''report.includes('59')'' was satisfied by ''11.59 bits''. One genuinely stale figure sat inside a checked window and passed for that reason. |
| | |
| | Both are fixed in ''scripts/check_page_numbers.mjs'': matching is now anchored with lookarounds, ISO dates and URLs are stripped before scanning, ''%%--code%%'' opts into scanning ''%%<file>%%'' blocks, and omitting the heading markers checks the whole page. **Run it windowed //and// whole-page.** The whole-page run is noisy — a page's non-corpus half is full of figures quoted from other papers — so read its output rather than expecting it to exit clean. |
| | Fixed on this page's content page as a result — and one of them is the most instructive defect in the whole refresh: |
| | |
| | * **The embedded ''%%<file javascript js_fold.mjs>%%'' block still quoted the 4,322-corpus counts** — ''program-analysis'' on 959 papers, ''code-or-binary-analysis'' on 1,063, LLVM 66, Soot 61, IDA Pro 36, FlowDroid 34, angr 28, Esprima 15 — two screens below the page's own table saying 1,385 / 1,484 / 101 / 81 / 62 / 48 / 39 / 23. The published, downloadable source contradicted the prose. **''check_page_numbers.mjs'' strips ''%%<file>%%'' blocks and so could never have caught it**; it now takes ''%%--code%%''. Fixed in both ''scripts/js_fold.mjs'' and the embedded copy, and the two were diffed afterwards. |
| | * Related-Pages shares **42.4% → 39.8%** and **28.6% → 27.6%**. |
| | * "the privacy reader's own family is the largest but is barely a quarter of the field" was wrong against its own table: the largest single family is 29 of 206 = 14.1%. Rewritten to name the two families that together make 53 of 206 = 25.7%, which is what "barely a quarter" was always describing. |
| | |
| | ===== 11. Run log ===== |
| |
| ^ ^ ^ | ^ ^ ^ |
| | Model | Claude Opus 5, no sub-agents used for this page | | | Model | Claude Opus 5, no sub-agents used for this page | |
| | Scope | Mechanical re-derivation. One paragraph of new prose, on Foxhound and PageGraph growth, because the refresh turned an editorial currency judgement into a partly measured one. | | | Scope | Mechanical re-derivation. One paragraph of new prose, on Foxhound and PageGraph growth, because the refresh turned an editorial currency judgement into a partly measured one. | |
| | Script changes | ''report_javascript.mjs'' (bucket bug, hardcoded 6.1%, split artifact comparison), ''js_fold.mjs'' (comment only — the string count in a header comment) | | | Script changes | ''report_javascript.mjs'' (bucket bug, hardcoded 6.1%, split artifact comparison), ''js_fold.mjs'' (comments only — the ground-truth string count, and, after review, the module docstring's stale corpus counts; see §10) | |
| | Caveats deleted | "IEEE S&P is only 43% retrieved" — 780 of 780 selected papers are now retrieved. "This corpus ends in 2024." | | | Caveats deleted | "IEEE S&P is only 43% retrieved" — 780 of 780 selected papers are now retrieved. "This corpus ends in 2024." | |
| | Not deferred, but worth flagging | The ''llm'' row is 2 papers. If it is still 2 on a complete 2026, it means nothing; if it is 15, this page's //Methods// table needs a new row. | | | Not deferred, but worth flagging | The ''llm'' row is 2 papers. If it is still 2 on a complete 2026, it means nothing; if it is 15, this page's //Methods// table needs a new row. | |
| | | Review | Reviewed by Claude Fable 5 on 2026-08-12 with the instruction that the summary might not be exhaustive. It found the windowed-guard defect in §10 and 3 stale figures on this page plus the embedded js_fold.mjs docstring. All fixes were applied and re-saved the same day. | |
| | |
| | |
| | ===== 12. LLM-classification currency, 2026-09-03 ===== |
| | |
| | //Recorded during the run.// Three pages made currency claims about the same schema field, ''classification.method == "llm"'', from three separate queries. The shared numbers, the script that produces them, its unedited output, the folds and their residue, and the quote check are on **[[provenance:design:website_classification]] §12** and are not restated here. This section records only what is specific to this page. |
| | |
| | ==== 12.1 What was wrong, and what was right ==== |
| | |
| | ^ Claim on the page ^ Verdict ^ What changed ^ |
| | | "no peer-reviewed paper classifies web scripts as trackers with a language model" | **true, and now measured** | was the result of a keyword search; is now ''method == "llm"'' fired on **0 of the 44** papers with a ''javascript'' classification target and **0 of the 31** with a ''fingerprinting-script'' target, out of 5,859 | |
| | | "The ''llm'' row is new: on the 4,322-paper corpus this enum never fired for a JavaScript-classification task at all. Two papers is not a trend" | **misleading** | rewritten. The enum is per //paper//, not per JS task. Both papers are in this page's 206-paper population and neither classified a script | |
| | | the nearest work is three arXiv preprints and a de-minifier | **incomplete** | TGNN {[xiong2026_tgnn]} (TheWebConf 2026) is peer-reviewed, in-corpus, and was already cited nine times on [[privacy:requests]] | |
| | |
| | ==== 12.2 The two llm papers, named ==== |
| | |
| | The page's method table counts a paper if it carries **any** ''llm'' classification tuple, whatever the target. In this page's population that is two papers, and the reason the old sentence read as a JavaScript finding is that the table sits under a JavaScript heading. Query: ''node scripts/report_llm_currency.mjs'' and, for the population restriction, ''node scripts/report_javascript.mjs''. |
| | |
| | ^ Paper ^ Its ''llm'' target ^ What the model actually did ^ |
| | | {[chen2025_semantics]} — ''WWW/2025/semantics-aware-cookie-purpose-compliance'' | ''cookie'' | fine-tunes GPT-3.5 to interpret cookie value segments and label GDPR purposes | |
| | | PhishLang — ''NDSS/2026/phishlang-a-real-time-fully-client-side-phishing-detection-framework-using-mobilebert'' | ''other'' | queried GPT-4 with 3,000 confirmed phishing sites to pick which HTML tags matter; the shipped classifier is MobileBERT | |
| | |
| | Restricted to script targets the count is **zero**. That is the figure the page quotes; the "two" is reported only as an explanation of the enum row, which is now what the page says. |
| | |
| | ==== 12.3 Checking the "silence" claim before repeating it ==== |
| | |
| | This is the failure mode the site has hit before — a keyword sweep under-recalls and a sibling page already covers the paper you missed — so the check was run explicitly this time: |
| | |
| | * ''node scripts/dw.mjs search 'xiong2026_tgnn''' → **9 hits on [[privacy:requests]]**, 3 on [[literature:bibliography]]. The paper was already on the site, with its figures and its caveats, before this page claimed the nearest work was on arXiv. |
| | * The full text was then read rather than taken from the extraction: ''/workspace/publications_dataset/data/fulltext/2026/WWW/tgnn-enhancing-pixel-tracking-detection-via-llm-driven-annotation-and-gat-powere/paper.cols.txt''. |
| | |
| | **Why the core claim still survives TGNN.** TGNN's LLM (Qwen3) labels **HTTP request/response quadruples**, and the paper explicitly positions itself against methods that do "single-domain analysis-such as string matching against domain lists or scrutinizing JavaScript execution within a page". It is a request classifier that uses a model to manufacture labels, not a script classifier. The page says exactly that and points at [[privacy:requests]] for the full treatment, rather than re-describing the paper. |
| | |
| | ==== 12.4 The 98.17 / 98.19 discrepancy ==== |
| | |
| | TGNN gives its annotation F1 as **98.17%** twice in the body and as **98.19%** once. The discrepancy is the paper's own. Located by line offset against the section headers in ''paper.cols.txt'' on 2026-09-03, after a reviewer showed that the first draft of the footnote had two of the three locations wrong: |
| | |
| | ^ Figure ^ Where the page first said it was ^ Where it actually is ^ |
| | | 98.17% | §4.1.4 | **§4.1.3 //LLM-based Labeling//** — line 542, closing sentence of the subsection whose header is at line 489; §4.1.4 //Graph Learning// starts at line 545. //"demonstrate that 𝑀𝜆 performs well (𝐹1-score of 98.17%), thereby validating its effectiveness as the LLM-based labeling component."// | |
| | | 98.17% (second) | §5.5 | line 754, //"As shown in Figure 5, the 𝐹1-score of the data labeling component reaches 98.17%"//. This sits between the §5.2 header (line 597) and the §5.5 header (line 766), and ''.cols'' interleaving makes the assignment unreliable, so the page now says **"beside Figure 5"** rather than naming a section it cannot prove | |
| | | 98.19% | its abstract | the **Introduction**, line 177, in the contributions paragraph. **The abstract states no F1 for the annotation component at all** | |
| | |
| | The 55.14% filter-list comparison appears only in that same Introduction paragraph; the body's Figure 5 gives the two confusion matrices it summarises. The page quotes the pair as the Introduction states them. |
| | |
| | **Two mechanical notes on reading this paper's text.** It renders its F1 symbol as math-italic glyphs (''𝐹 1'', ''𝑀𝜆''), so any literal match must fold or skip them; and ''paper.cols.txt'' contains **913 NUL bytes**, which makes shell ''grep'' treat it as binary and suppress every match with no message — use ''grep -a''. 90 of the 5,869 ''paper.cols.txt'' files (1.5%) have NUL bytes. ''scripts/llm_currency_quotecheck.mjs'' now strips them; see [[provenance:design:website_classification]] §12.6. |
| | |
| | ==== 12.5 What could not be established ==== |
| | |
| | * **Whether an LLM script classifier exists outside these seven venues.** The outside search is reported on the page as a search, not as a corpus figure, and it is the weakest sentence on the page for exactly that reason. The corpus zero is the part that is measured. An external-currency reviewer re-ran the search on 2026-09-03 across arXiv, EuroS&P, ACSAC, RAID, AsiaCCS, WPES, SOUPS and CHI and found nothing; that is two independent searches agreeing, which is still not the same as a measurement. |
| | * **What ''target == "other"'' hides — now probed rather than deferred.** 116 of the 177 corpus LLM papers carry ''target == "other"'', so a paper that classified scripts and was extracted as ''other'' would not appear in the zero. An earlier draft of this section said "reading those 116 would settle it; it was not done"; a reviewer pointed out that the schema already answers most of it. ''other'' carries a free-text ''targetDetail'', stated on **all 157** such tuples, and ''report_llm_currency.mjs'' now probes it for //website, domain, URL, page, script, tracker, cookie, SDK, categor…//. It returns **16 tuples and none is a script, tracker or website-topic classification** — they are IoT device categories, image content, decompiler clusters, MCP server categories, GDPR data categories and, for Borges, "favicon and associated final-URL groups". **So the zero survives the ''other'' bucket at keyword recall.** It is a probe, not a read of 116 papers: it cannot rule out a paper whose ''targetDetail'' is phrased in none of those words, and the list must be read rather than the count trusted. Full output on [[provenance:design:website_classification]] §12.9. |
| | * **Nothing else on this page was re-derived in this run.** The 206-paper population, the ground-truth families and the method table are unchanged from the 2026-08-12 refresh (§4) and were re-run only to confirm the ''llm'' row still reads 2. |
| |
| [[privacy:javascript|← back to the content page]] · [[literature:corpus|corpus-level provenance]] | [[privacy:javascript|← back to the content page]] · [[literature:corpus|corpus-level provenance]] |
| | |
| | ===== Markup sweep, 2026-09-17 ===== |
| | |
| | Mechanical rendering repair only: a fresh live raw/XHTML export of 188 pages was checked with ''check_wrap.mjs'' and ''check_typography.mjs''. Affected plugin tags, CLI flags and heading markup were repaired; no figures or substantive prose were changed. The resulting source and rendered DOM were re-checked after saving. |
| | |
| | ===== Quote-check refresh, 2026-09-21 ===== |
| | |
| | The 2026-09-04 ''cols''-vs-PDF audit on [[:provenance:literature:corpus]] showed that 73.1% of evidence quotes that cannot be located in ''paper.cols.txt'' **are** present in an independent ''pypdf'' rendering of the same ''paper.pdf''. ''scripts/quote_check.mjs'' was patched the same day to re-check everything below threshold against that second rendering and report a fourth verdict, **RESCUED**. §6's figure predates the patch. Re-run, unedited first line: |
| | |
| | <code> |
| | $ node scripts/quote_check.mjs --classification javascript --show 400 |
| | 66 quotes checked: 34 exact, 19 partial (>=60% of 5-word windows), 12 rescued from the PDF, 1 below threshold in both renderings, 0 with no full text on disk. |
| | </code> |
| | |
| | ^ Figure ^ Was ^ Is ^ Why ^ |
| | | quotes checked | 66 | 66 | population unchanged — the corpus has not moved | |
| | | exact | 34 | 34 | unchanged | |
| | | partial (≥60% of 5-word windows) | 19 | 19 | unchanged | |
| | | rescued from the PDF | — | **12** | new verdict; these were inside the old 13 | |
| | | below threshold | **13** | **1** (in both renderings) | 13 = 12 + 1 exactly; nothing else moved | |
| | | below-threshold rate | 19.7% | **1.5%** | 1 of 66 | |
| | | unread below-threshold quotes | 8 | **1** | the ''rozzle-de-cloaking-internet-malware'' Zozzle quote | |
| | |
| | **Small population, so read the count and not the percentage.** 66 quotes is the smallest population in this sweep apart from the 9 Foxhound quotes, and a single quote is 1.5 points of it. What this run establishes is that **one** quote on this page is below threshold in both renderings and has not been read by hand — not that the page's quote-failure rate is 1.5%. |
| | |
| | **What this does and does not say.** It does not say 12 extractions were wrong and are now right — the quotes were always in the papers, and 5 of the 12 had already been read by hand and found present. It says the //stored text// could not locate them and a second rendering of the same PDF can. |
| | |
| | **Scope of this edit.** §6 only. ''report_javascript.mjs'' was **not** re-run in this pass; the tool table, the phenomenon fold, the 44-of-198 ground-truth figure, the PoPETs 2023 transposed-label reading and every citation stand as published. [[:privacy:javascript]] carries no quote-check figure, so it was not edited. |
| | |
| | ^ Item ^ Value ^ |
| | | Date | 2026-09-21, unsupervised | |
| | | Command | ''%%node scripts/quote_check.mjs --classification javascript --show 400%%'' | |
| | | Artifact | ''out/qc0921/class_javascript.txt'' (full run, 12 RESCUED rows and the 1 below-threshold row listed) | |
| | | Script changes | none — ''quote_check.mjs'' was already patched on 2026-09-04 | |
| | | Reviewers | one ''sonnet'' figures-vs-script pass | |
| | | Pages saved | this page only | |
| | |
| | ===== Foxhound count errata, 2026-09-21 ===== |
| | |
| | **What was wrong.** The toolchain table published ''Project Foxhound (taint tracking) | 8 | 3.9%'', and the sentence below it read "went from 2 papers to 8". The per-paper role audit on [[:programming:crawler:foxhound]] (''scripts/report_foxhound.mjs'' + ''scripts/fh_fold.mjs'', 2026-08-17) finds **9 papers in the corpus that actually ran the browser**, and its footnote named this page's table as one of the two to correct. |
| | |
| | **Why.** ''jsSignals()'' counts a tool only when the tuple says ''used'' or ''produced''. Khodayari et al.'s NDSS 2025 open-redirection paper names Foxhound as ''compared'' — //"We considered the following state-of-the-art detectors as baselines: dynamic taint-tracking [24, 36, 45] using Foxhound [44, 45]"// — and ran it over 42,288 webpages. It is in this page's 206-paper population already, on its ''detection'' and ''classification'' signals, so the only thing that was wrong is that it named no tool. |
| | |
| | **The fix, and the two things it deliberately does not do.** ''js_fold.mjs'' now exports ''TOOL_ROLE_OVERRIDE'', a hand map of papers whose tool role has been read and published by a named audit — currently one entry, citing the Foxhound ''ROLE'' map and the sentence it was decided on. It adds to ''tools'' only, **not** to ''strictTools'' and therefore **not** to ''reasons'': a hand entry must not be able to pull a paper into the 206. And it is not a general rule that ''compared'' means "ran it" — that needs the sentence, paper by paper. ''jsSignals()'' **throws** if the overridden tuple disappears from the extraction or is re-extracted as ''used''/''produced'', so a redundant hand entry cannot sit there unnoticed. |
| | |
| | <code> |
| | $ node scripts/report_javascript.mjs |
| | --- before |
| | +++ after |
| | -Project Foxhound (taint tracking) 8 3.9% |
| | +Project Foxhound (taint tracking) 9 4.4% |
| | -Papers naming no JavaScript-analysis tool at all: 120 of 206 (58.3%). |
| | +Papers naming no JavaScript-analysis tool at all: 119 of 206 (57.8%). |
| | </code> |
| | |
| | **Those two lines are the entire diff of the report.** The 206-paper population, the signal-combination table, the venue and period tables, the research-family fold and its 65-tuple residue, every classification, ground-truth, validation and crawl-config figure and every citation are byte-identical before and after. |
| | |
| | ^ Figure ^ Was ^ Is ^ |
| | | Project Foxhound, toolchain table | 8 (3.9%) | **9 (4.4%)** — and the row now sorts above PageGraph and VisibleV8 | |
| | | Papers naming no JS-analysis tool | 120 of 206 (58.3%) | **119 of 206 (57.8%)** | |
| | | "went from 2 papers to 8" | 8 | **9** | |
| | | PageGraph | 8 (3.9%) | 8 (3.9%), unchanged | |
| | |
| | The published ''%%<file javascript js_fold.mjs>%%'' block on [[:privacy:javascript]] was regenerated from the committed file in the same save, so the code the page shows is the code that produced the table, including the new override and its assertion. |
| | |
| | ^ Item ^ Value ^ |
| | | Date | 2026-09-21, unsupervised | |
| | | Script changes | ''scripts/js_fold.mjs'' (''TOOL_ROLE_OVERRIDE'' and its two assertions in ''jsSignals'') | |
| | | Reviewers | one ''sonnet'' figures-vs-script pass; one ''sonnet'' citations/quotes pass | |
| | | Pages saved | this page, [[:privacy:javascript]] | |
| |