User Tools

Site Tools


provenance:programming:crawler:foxhound

This is an old revision of the document!


BibTeX key 'citekey' could not be found. Possible typo?

Provenance: Programming:Crawler:Foxhound

Back to SAP Project Foxhound. Corpus-wide selection and extraction caveats are on corpus. This page is the query log and the working record behind that page: what was asked of the corpus, what was fetched live, what was folded, what was checked by hand, and what could not be established. It is a log, not a tutorial.

Following the convention set by the first of these pages, there is no ~~DISCUSSION~~ block here — comments belong on the content page.

Run record

  • Run date: 2026-08-17 (UTC).
  • Authoring agent: Claude (Opus 5), working from the read-only publication mount at /workspace/publications_dataset and from live fetches of the Project Foxhound repository, its wiki, GitHub's API, Mozilla's product-details service and TU Braunschweig's binary host.
  • Review agents: three focused sonnet passes (figures-vs-script, citations-and-quotes, external currency) run in parallel on the frozen draft, then a generic fable pass over the content page, this provenance page, the report script and its output. Findings and dispositions are in the Review log.
  • Corpus at run time: 5,859 extracted papers, 2010–2026, from CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P. Crawled population 1,120. These are the post-2026-08-11 denominators; no figure was carried over from any earlier page or dossier.
  • This is a creation, not an extension. See Why this page, and not a section of a neighbour.
  • Full text read directly (not only through the extraction): all nine papers that ran Foxhound, the two citation-only papers, the two homographs, and the four lineage papers — seventeen paper.cols.txt files. Nothing was written to the publication mount.

Why this page, and not a section of a neighbour

programming:crawler already carries a Foxhound row in its specialised-crawler table and explicitly promises this child page; privacy:javascript names Project Foxhound in its tool table, its methods table and its Related-pages list, and promises the same child. The sitemap before this run listed programming:crawler:foxhound as promised but missing, linked from both.

So the judgement was easy on whether to create, and harder on scope. Three candidate scopes were considered:

  • A “taint tracking” page covering Foxhound, PanoptiChrome and the interpreter-level tools together. Rejected: the wiki's per-tool namespace is programming:crawler:<tool>, programming:crawler:panoptichrome is separately promised from programming:crawler, and a method page would duplicate the comparison privacy:javascript already makes. The lineage and alternatives sections carry what a reader needs about the wider method without claiming that scope.
  • A narrow tool page — install, flags, output format. Rejected as too thin to be worth a reader's time; the repository's own wiki does that better.
  • What was written: what the instrument reports, what it cannot see, what a paper must report about it, and where it sits against PageGraph and filter lists. The task's brief named “what taint flows it reports, the build burden, and what it enables that PageGraph does not”, and those are the three load-bearing sections.

One deliberate overlap: the PETS 2026 taint-versus-syntactic-matching result also appears on privacy:requests. It is used here for a different purpose — as evidence about the instrument's own false-positive and false-negative behaviour rather than about filter lists — and the numbers were re-derived from the paper rather than copied from that page.

Population and queries

Every count is a count of papers. Sentinels are not involved: the population is defined by a named tool, not by a field that can be not-stated.

Query Denominator Result
/fox ?hound/i over data/fulltext/<year>/<venue>/<slug>/paper.cols.txt 5,859 corpus papers 13 papers
tools[].name or otherToolsMentioned[].name matching the same regex 5,859 9 papers, 9 tuples
Sweep papers whose hand verdict is homograph 13 2 (excluded from every published figure)
Sweep papers whose hand verdict is citation (cited, not run) 13 2
Papers that ran the browser (used + extended + baseline) 13 9
Same 9, as a share of the corpus 5,859 0.2%
Same 9, as a share of papers that ran a crawl 1,120 0.8%
Of those 9, how many the schema also puts in POPULATIONS.crawled 9 9 (none outside it)
Papers that ran it, 2010–2023 3,984 corpus papers in those years 0
Papers that used or extended it (excluding the 2 baseline-only) 13 7
Of those 7, how many state a Foxhound version or commit 7 3 (42.9%)
Of all 9 that ran it, how many state a version or commit 9 5 (55.6%)
Of the 9, how many have a listed project contributor as co-author 9 6 (66.7%)
Taint browsers in the corpus that predate Foxhound, built by their own authors web-platform papers with a /taint/i tool in the browser / program-analysis / infrastructure categories (7 tuples over 6 papers) 4 kept

The sweep is the upper bound and the schema is the lower one, and neither is the answer. The schema misses both citation-only papers, which are precisely the ones the page has to separate out; the sweep catches two papers that are not about the browser at all. Using either number alone would be wrong in a different direction, so the page reports 13 → 9 explicitly.

scripts/report_foxhound.mjs re-runs the sweep on every invocation and compares it with the hand map in scripts/fh_fold.mjs. If the sweep returns a paper the map does not cover, or the map names a paper the sweep no longer finds, the report prints FAILURE and every figure below it is to be treated as suspect. Currently both residues are 0.

Folding, and the residue

No name fold was needed for the population. The three spellings in the corpus are case variants of one token with no synonyms:

Raw names in the schema: "Foxhound" (6), "Project Foxhound" (2), "FoxHound" (1).
Fold residue: 0

This is the opposite situation from design:crawling_location (MaxMind under 41 spellings) or privacy:requests (Disconnect under 28). Saying “the residue is empty” here is a statement about the token, not a claim of folding rigour, and the page says so.

Two hand classifications do the real work, both in fh_fold.mjs, both carrying the sentence they were decided on:

  • ROLE — a verdict per swept paper from used / extended / baseline / citation / homograph. Merging these would produce a meaningless count: three of the nine papers rebuilt the browser, and two ran it only to be beaten by their own tool. The distinction between used and extended is what makes the page's central practical warning — check the pref list before you start — a measured observation rather than an opinion.
  • VERSION_STATED — the Foxhound version or commit each paper names, read by hand. The report re-runs a regex sweep beside it and prints agree / DISAGREE per paper; all nine agree. The regex is deliberately kept as a cross-check rather than as the source, because it also matches unrelated “Firefox 1xx” sentences.

The taint-instrument context table (section F of the report) is the one place with a genuine ordered fold, and it prints its residue. First match wins across nine families, and every remaining tool string matching /taint/i is listed:

Family | Papers
Project Foxhound — patched Firefox (in-engine) | 9
PanoptiChrome — patched Chromium (in-engine) | 2
ChromiumTaintTracking — patched Chromium (in-engine) | 0
Jalangi / JalangiTT — source instrumentation | 6
JSFlow — instrumented interpreter | 1
LinvailTaint — source instrumentation | 1
IF-Transpiler — source rewriting | 1
TaintDroid — Android, not a web instrument | 9
Android taint analysers — not web instruments | 68

Residue — tool strings matching /taint/i that no family claims: 21 distinct strings.
  "Taint tracker" (1 papers)
  "taint-aware Firefox engine" (1 papers)
  "static taint analysis engine (custom)" (1 papers)
  "Multiple Taint-Style Vulnerabilities Detector (MTS-VD)" (1 papers)
  "static taint analysis tool" (1 papers)
  "custom taint-aware infrastructure" (1 papers)
  "taint tracking engine" (1 papers)
  "TAINT INDUCE" (1 papers)
  "Taint'em All" (1 papers)
  "Taintless" (1 papers)
  "Taintgrind" (1 papers)
  "TaintGrep" (1 papers)
  "OctopusTaint" (1 papers)
  "TaintScope" (1 papers)
  "ParcelTaint" (1 papers)
  "DeFiTainter" (1 papers)
  "E M TAINT" (1 papers)
  "O CTOPUS TAINT" (1 papers)
  "LuaTaint" (1 papers)
  "file_taint" (1 papers)
  "EmTaint" (1 papers)

Reading that residue is what produced the lineage table, which is the finding of this run I would least have predicted. Four of the unmapped strings — “taint-aware Firefox engine”, “custom taint-aware infrastructure”, “taint tracking engine”, “Taint tracker” — are papers whose own contribution was a taint browser, under no product name at all. Without them the corpus reads as if in-browser taint tracking began in 2024, which is false and would have made the page's currency claim badly wrong. The page's four-row lineage table is the correction. “E M TAINT” / “EmTaint” and “O CTOPUS TAINT” / “OctopusTaint” are the same tools twice, split by small-caps rendering in the PDF; they are binary-analysis tools and off-topic either way, and are left in the residue rather than folded, because folding them would imply the residue had been curated.

The Android taint analysers family at 68 papers is deliberately in the table and deliberately labelled “not web instruments”. It is there so a reader cannot mistake the small web numbers for a claim that taint analysis is rare in general.

Quotes and figures checked

Three separate checks, all in the report:

  • Schema evidence quotes (section G): the 9 tools[].evidence.quote values, normalised for whitespace and line-break hyphens, then by five-word windows — 5 exact, 4 partial (≥60% of windows), 0 below threshold, 0 without full text. The four partials are column splices in the repaired rendering, not unsupported claims. Cross-checked with the shared bulk verifier, which is a separate implementation: node scripts/quote_check.mjs –tools 'fox.?hound' –show returns the identical 5/4/0/0.
  • Hand deciding quotes (also section G): the 13 sentences in the ROLE map — 13 exact, 0 not exact, as the report says. Two of them are exact only because they were shortened during this run to a contiguous fragment: the CCS 2025 extension sentence and the NDSS 2026 baseline sentence are each spliced across two columns in paper.cols.txt, and the longer versions I first wrote matched at 50% and 60%. Both are marked with an inline comment in fh_fold.mjs saying why they are short, so a later reader does not “restore” them. (An earlier draft of this page said “11 exact, 2 not”, describing the state before the shortening; the citations reviewer caught the mismatch against the artefact.)
  • Per-paper figures and quoted sentences used on the page (section H): 50 needles, 0 not located verbatim in paper.cols.txt. This check exists because detection[].prevalence is a model summary rather than a quotation — the same reason verify_requests_figures.mjs exists. It started at 31 needles and grew to 50 on the figures reviewer's finding that the comparison table's per-tool numbers were disclosed as hand-checked but not machine-checked; adding them also caught three of my own needles that were column-spliced and would have read as failures.

A self-caught defect in the same check, worth recording because nothing would have flagged it: three needles were too short to mean anything. “38.5”, “13” and “55 event handlers” will match almost any paper's digits, so they were passing for the wrong reason — a false pass is worse than a failure, because it looks like verification. All three were replaced with the full clause from the source (“false negative rate of 38.5%”, “From each of the remaining 13 libraries we create a benchmark sample”, “a total of 55 event handlers”), and “9.6% of the top 10K” was split into two needles because the paper states the share and the flow count in different sentences. The rule this suggests for the next page: audit the needle list for anything under about twenty characters before trusting the “0 not located” line.

One figure is quoted from the extraction with a formatting change: FP-tracer's 269 784 fingerprinting flows (thin space in the paper and in the extraction) is written 269,784 on the page. That is a rendering choice, logged here so a future check does not read it as a mismatch.

External facts, and how each was verified

scripts/foxhound_probe.sh re-fetches every one of these and prints FAILED per check rather than failing quietly. Its unedited output is in Probe output. Nothing on the content page about the tool's current state comes from recall.

Fact on the page Primary source How checked
main is Firefox 142.0.1 browser/config/version.txt on main raw.githubusercontent fetch
Playwright pin v1.58.2, Rust pin 1.86.0 .PLAYWRIGHT_VERSION on main raw fetch, grep
Current stable Firefox 153.0.4 product-details.mozilla.org/1.0/firefox_versions.json JSON fetch
Playwright's current release v1.62.1, baselined on Firefox 153.0; v1.58's baseline is 142.0.1 browser_patches/firefox/UPSTREAM_CONFIG.sh in microsoft/playwright, then version.txt at that Firefox revision two-hop fetch, so the version is derived from the pinned revision rather than assumed
34 sources, 61 sinks, 1 master switch, all default true modules/libpref/init/all.js on main grep and count; both full name lists printed
taintfox.escapeURL defaults to false on the main thread, true on workers, and is not declared in all.js netwerk/base/nsStandardURL.cpp line 116, plus issues #259 (closed 2025-02-14, where the maintainer documents the pref and the legacy-IE reason) and #260 (open, asking for it to be renamed and added to the default config) the probe prints the call site with context, counts taintfox occurrences in all.js (0), and prints both issue states. Found only because the generic reviewer pointed out the page demanded a setting it never named
The Ubuntu and Windows mozconfigs set --disable-sandbox, --without-wasm-sandboxed-libraries and --disable-crashreporter; the macOS one does not; there is no unsuffixed taintfox_mozconfig despite the README's cp command taintfox_mozconfig_{ubuntu,win,mac} and the repository contents listing the probe prints every ac_add_options/mk_add_options line of all three and asserts on the missing file. The first draft called the build “debug-instrumented”, which was wrong; checking it produced a better fact
“URLSearchParams.get” trace operation absent at v130.0, present from v140.0.2 netwerk/base/nsURLHelper.cpp per release tag, plus the PR #350 diff four-tag check in the probe. The diff shows MarkTaintOperation called after an assignment that already carries taint, which is what limits the page's claim to the trace, not the tracking
Pref history: none up to v115, 85 at v118.0.1, 96 (34/61) from v119.0 all.js at each of 15 release tags per-tag fetch and count, plus a per-tag test for the document.querySelector source pref
DOM-read sources landed in PR #198 (merged 2024-02-08); URL taint operations in PR #350 (merged 2025-11-26) GitHub pulls API, including the changed-file lists API fetch; #350 touches dom/tainting/nsTaintingUtils.cpp and dom/url/URL.cpp, which is what limits the claim to flow-trace operations, not taint propagation
17 releases, only v128.0 and v140.0.2 carry binary assets GitHub releases API API fetch, asset names printed
Build times 81.3 / 134.1 / 148.1 min plus 34.2 + 7.2 min of tests GitHub Actions API, browser.yml run id 26110426051 (2026-05-19) per-job and per-step timings computed from started_at/completed_at
browser.yml and playwright.yml currently fail on main at 7ce49d32 (2026-07-24) in Bootstrap / Configure, while main.yml passes GitHub Actions API newest run per workflow on main, then its failing steps
10 GB swap, 4–10 GB pagefile, disk purge .github/workflows/browser.yml grep of the workflow's own resource steps
6.1 GiB checkout, GPL-3.0, repo created 2021-06-04 GitHub repos API API fetch
TU Braunschweig hosts 31 per-commit Linux builds under Debian Bookworm, newest 1bb8dbd6 (2026-05-19), with SHA-256 checksums and the matching Playwright version foxhound.ias.tu-bs.de HTML fetch with a browser User-Agent, then regex extraction of commits, dates and Playwright versions
report.detail field list; the worked taint-flow JSON; “one release behind Playwright”; the gkrust OOM; the Playwright patch workflow constraints; the git-history resync the project wiki, cloned as a git repository (project-foxhound.wiki.git) and the README git clone –depth 1, then read; the probe asserts nine specific README substrings still exist
The JIT / best-effort caveat taint/docs/TaintFlow.md on main raw fetch, and the probe greps the two sentences
Klein et al., EuroS&P 2022 is the requested citation README Cite us! section probe asserts the BibTeX key KleBarBen is still present
Satellite tools alive: taint-flow extension, ZAP add-on; PanoptiChrome public GitHub repos API for all three API fetch: archived flag, push date, licence
14 publications on the project's Hall of Fame wiki Publications.md count of list items in the cloned wiki
All 14 external URLs on the page return 200 curl with a browser User-Agent probe prints the status per URL and marks anything other than 200

Sources considered and rejected:

  • taint/README.md's source and sink lists. Rejected as the page's source of truth, and the disagreement is now a footnote: it marks element.getAttribute, element.innerHTML and element.outerHTML as struck-through/disabled sources, while the pref for element attributes has been on since v119.0. The repository documentation is stale relative to the prefs; the prefs are the artefact that decides behaviour.
  • The wiki's Source-and-Sink-Listings page. Used as a reading aid, rejected as a count. Its lists are produced by a grep over the tree and contain the grep's own artefacts — the literal ReportTaintSink and a truncated navigator.sendBeacon(url)n — so counting its lines gives 26 sources and 51 sinks, neither of which is the real surface. This is exactly the kind of “authoritative-looking list” that would have put two wrong numbers on the page.
  • Any secondary write-up, blog post or listicle about Foxhound. None used. Every external claim traces to the repository, its wiki, an API, or a paper.
  • pagegraph-side facts were not re-derived here; the PageGraph comparison rows point at pagegraph and its own provenance page rather than restating its verification.

The published code

foxhound_flows.py on the content page is not a wrapper around a browser: it reduces already-collected taint reports. The first version of it had two real bugs, both found by the generic reviewer and both visible in its own self-test — see findings 1 and 2 in the Review log. That is the strongest argument on this page for publishing code with a self-test rather than a snippet: the fixture disagreed with the prose, and it was checkable. That choice was deliberate — a script that needs a Foxhound binary could not have been tested in this run, and an untested script on the page would violate the task's own rule. As written it is testable, and its self-test is the fixture from the project's documented worked example plus five mutations of it:

$ python3 pages/foxhound_flows.py --selftest
selftest: 19 checks passed

flows: 1   sites: 1   pages: 1   scripts: 1
dropped as encoded at the sink: 0  (report this number whichever way you decide)
tainted substring held no HTML/JS syntax character at crawl time: 1 of 1 — a property of your input, NOT a safe verdict
flows with no recorded application function call (JIT-blind): 1 of 1 = 100%
flows observed in a subframe: 0 (a landing-page-only crawl still sees these; say so)

source                       sink                        sites    flows  jit-blind
location.hash                innerHTML                       1        1          1

The copy embedded in the page's <file python> block was byte-compared against pages/foxhound_flows.py before publication (20,338 bytes each, identical), because a published script that has drifted from the one that was tested is worse than no script:

python3 - <<'EOF'
OPEN = '<' + 'file python foxhound_flows.py>'   # split so this snippet can live
CLOSE = '<' + '/file>'                          # inside a wiki page unharmed
page = open('pages/programming_crawler_foxhound.txt').read()
start = page.index(OPEN) + len(OPEN) + 1
embedded = page[start:page.index(CLOSE, start)]
print('identical:', embedded.rstrip('\n') == open('pages/foxhound_flows.py').read().rstrip('\n'))
EOF

The four checks that justify the file existing are: the source is the last source-flagged node (flow is ordered sink-first, and reading it forwards mislabels every row); a chain with no application function node is marked JIT-blind, with the reporting harness's own call excluded, rather than treated as “no sanitiser was called”; encoded_at_sink (a property of the code) is kept apart from no_syntax_chars (a property of the input you sent), and only the former can drop a row; and the unit is chosen explicitly, so the same pair on two pages of one site is 1 site and 2 pages. Neither flag is a verdict, and the page says so.

What could not be established

  • No throughput benchmark exists. Nothing in the corpus or the project's material gives pages-per-hour, memory per instance, or a crash rate for Foxhound on a modern population. Calzavara et al.'s 1.4× is an analysis-time ratio on landing pages of sites where the tool was already compatible and transparent — it is not a crawl-rate measurement, and the page refuses to present it as one. The page's advice is therefore to pilot, which is weaker than a figure and is the honest answer.
  • How often the JIT blind spot bites, in practice. The project documents it; nobody has measured what share of real flows lose their function-call nodes. The published script counts it so a future paper can report it, but this page cannot say whether the number is 5% or 60%.
  • Whether the 2024 arrival is adoption or coincidence. Nine papers over three years, six of them with a maintainer as co-author, is a diffusion signal too small to test. A per-year trend on nine papers would be noise, and none is drawn.
  • The 2025–2026 slice is the provisional one. Five of the nine papers are in it. That is a real weakness of the currency claim on this page, and it is why the page leans on the pref history and the CI state — facts with dates attached that do not depend on the corpus edge — rather than on the year counts.
  • EuroS&P is not in the corpus, and it is where the browser is described and where the earlier work in this line was published. Every count here is a lower bound and the page names the project's own 14-entry list as the demonstration.
  • Not attempted: building it. A Foxhound build is an hours-long, tens-of-gigabytes operation and no binary for this container's platform was worth fetching for a documentation page. Everything about the build is therefore the project's CI and documentation, not our own experience, and the page attributes it that way. The alternative — quoting a build time we had not measured, unattributed — is the failure mode this note exists to prevent.
  • Deferred, not done: the errata on the neighbours. programming:crawler and privacy:javascript both publish 8 Foxhound papers where this page's audit finds 9, because they count schema tuples and the extraction files Khodayari et al.'s NDSS 2025 paper as compared. This page carries a reconciling footnote; the edits to those two tables are queued as a separate work item rather than made here, because changing another page's central table without re-running its own report script is how stale figures get created.
  • Not attempted: the taint reports themselves. No Foxhound binary was run, so no real __taintreport payload was captured. The field list and the worked example are the project's own documentation. If a later run does obtain a binary, the first thing worth checking is whether stack is ever non-empty, since the documented example shows {} and the page currently warns against designing around it.

Judgement calls

Call Decision and why
Create a per-tool page rather than widen privacy:javascript Both neighbours promise this exact page id; see Why this page, and not a section of a neighbour
Count 9 papers, not 13 and not 11 The role verdicts are published in full, so a reader who disagrees can recount. Reporting 13 would count a dog breed; reporting 11 would count two papers that never ran it, one of which rejected it
Publish the two homographs Named on the provenance page and in the report, not on the content page. An exclusion nobody can see is indistinguishable from a mistake
Call the pre-2024 taint browsers “did not outlive their paper” Grounded in the corpus: no paper outside each engine's own author lineage names it as a reused instrument, and a 2024 paper says in terms that it chose Foxhound over the 2019 Chromium tracker for modern-JS support. Stated as a claim about this corpus, not about the world
Report the maintenance lag as four Playwright releases, not “one” The project documents an intent to be one release behind; the measured state is v1.58.2 against v1.62.1. The page gives both, because the intent explains the design and the measurement is what a reader will hit
Do not call the earlier tools “superseded” They are not maintained and not reused, which is a weaker and checkable claim. “Superseded” would imply a comparison nobody in the corpus has run
Keep the PETS 2026 numbers on two pages Different argument on each; re-derived rather than copied. Noted above as a deliberate overlap
Present the WWW 2025 bake-off as the currency evidence, with three caveats attached It is the only head-to-head in the corpus and it is unambiguous, but it is one study, one 2024 landing-page crawl, and one of its authors is a listed project contributor. All three are on the page beside the table

Report script and its output

Committed as scripts/report_foxhound.mjs with scripts/fh_fold.mjs; re-run with

cd /workspace/artifacts/wiki
node scripts/report_foxhound.mjs > scripts/report_foxhound-output.txt
node scripts/report_foxhound.mjs --wiki          # DokuWiki tables
node scripts/report_foxhound.mjs --hits 'srcdoc' # full-text context over the population
bash scripts/foxhound_probe.sh > out/foxhound_probe.txt
node scripts/check_tables.mjs pages/programming_crawler_foxhound.txt
node scripts/check_page_numbers.mjs pages/programming_crawler_foxhound.txt scripts/report_foxhound-output.txt --code
node scripts/check_attributions.mjs pages/programming_crawler_foxhound.txt out/bib_merged_foxhound.txt

check_page_numbers.mjs passes both windowed and whole-page, and with –code. Getting it to pass required a Z2 block in the report listing every literal on the page whose source is not the corpus — the build minutes, the version pins, the pref counts, the per-paper figures from cited papers, and the tokenizer artefacts (22.04 yielding 2.0; the line numbers inside the fixture JSON). That block is the audit trail for every number the corpus cannot account for, and it is why the guard is a guard rather than a formality.

check_attributions.mjs reported “0 attributions checked” against this page on first run, because its regex required the crawler-page style | Name et al., VENUE YEAR, //Title// {[key]} | and this page's tables omit the title. The regex was generalised to accept either form; both this page (9 attributions) and programming:crawler:pagegraph (8) pass afterwards. “0 checked” is not a pass — the guard says so itself, and this is the second page on which that message was the actual finding.

Report output

report_foxhound-output.txt
Corpus: 5859 extracted papers from CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P, 2010-2026.
Crawled population: 1120 papers (19.1%), defined by crawlConfig != null or studyTypes includes automated-web-crawl.
Run date: figures below are recomputed on every run; external facts are in scripts/foxhound_probe.sh.
 
=== B. Population: full-text sweep versus schema, and the role verdicts ===
 
Sweep: /fox ?hound/i over data/fulltext/<year>/<venue>/<slug>/paper.cols.txt -> 13 papers.
Schema: tools[].name or otherToolsMentioned[].name matching the same regex -> 9 papers, 9 tuples.
Raw names in the schema: "Foxhound" (6), "Project Foxhound" (2), "FoxHound" (1).
No name fold is needed: every string is a case variant of one token. There are no synonyms and therefore no residue.
 
Hand role verdicts (fh_fold.mjs ROLE), one per swept paper:
key | role | in schema | what it did
CCS/2025/in-the-dom-we-trust-exploring-the-hidden-dangers-of-reading-from-the-dom-on-the | extended | yes | made every DOM read a taint source, to measure DOM-gadget data flows
IEEE-SP/2024/a-picture-is-worth-500-labels-a-case-study-of-demographic-disparities-in-local-m | homograph | no | "americanfoxhound" — an ImageNet class label in a list of image categories
IEEE-SP/2024/the-great-request-robbery-an-empirical-study-of-client-side-request-hijacking-vu | extended | yes | added request-API instrumentation ("Foxhound+") and fed the flows into a hybrid property graph
IEEE-SP/2024/to-auth-or-not-to-auth-a-comparative-analysis-of-the-pre-and-post-login-security | used | yes | collected taint reports pre- and post-login, then generated XSS exploits from them
NDSS/2025/do-not-follow-the-white-rabbit-challenging-the-myth-of-harmless-open-redirection | baseline | yes | ran it as one of six baseline vulnerability detectors on 42K pages
NDSS/2026/dom-xss-detection-via-webpage-interaction-fuzzing-and-url-component-synthesis | baseline | yes | ran two configurations of it as the prior-work baseline, and showed the URL-encoding setting quintuples the count
PETS/2024/fp-tracer-fine-grained-browser-fingerprinting-detection-via-taint-tracking-and-e | extended | yes | extended it with numeric tainting and a larger source/sink set (FP-tracer)
PETS/2026/from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr | used | yes | used it as the taint-tracking arm of a head-to-head against filter-list-style syntactic matching
USENIX/2024/dancer-in-the-dark-synthesizing-and-evaluating-polyglots-for-blind-cross-site-sc | used | yes | used it as the client-side-XSS baseline that the synthesized polyglots were measured against
USENIX/2025/the-domino-effect-detecting-and-exploiting-dom-clobbering-gadgets-via-concolic-e | citation | no | cited it in related work and rejected it as unsuitable, because it tracks only strings
WWW/2024/panoptichrome-a-modern-in-browser-taint-analysis-framework | citation | no | cited it as one row of a related-work comparison table for their own Chromium taint tracker
WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet | used | yes | benchmarked it against seven other JavaScript information-flow tools on live sites
WWW/2025/query-design-for-crowdsourced-clustering-effect-of-cognitive-overload-and-contex | homograph | no | "English Foxhound" — a dog breed used as an example crowdsourcing label
 
Sweep papers with no hand verdict: 0
Hand verdicts with no sweep hit: 0
 
Role tally:
  baseline: 2
  citation: 2
  extended: 3
  homograph: 2
  used: 4
 
RAN-IT population (used + extended + baseline): 9 papers.
  as a share of the 5859-paper corpus: 0.2%
  as a share of the 1120 papers that ran a crawl: 0.8%
  of those 9, how many the schema also puts in the crawled population: 9 (0 not: none)
The two homograph papers are excluded from every figure on the page. They are listed above so the exclusion is visible rather than silent.
 
=== C. Papers that ran Foxhound, by year ===
 
The denominator is that year's whole corpus, not the crawled subset, so the share is comparable with the other tool pages.
Year | Corpus papers | Ran Foxhound | Share | Provisional
2010 | 119 | 0 | 0.0% | no
2011 | 116 | 0 | 0.0% | no
2012 | 151 | 0 | 0.0% | no
2013 | 125 | 0 | 0.0% | no
2014 | 166 | 0 | 0.0% | no
2015 | 190 | 0 | 0.0% | no
2016 | 182 | 0 | 0.0% | no
2017 | 231 | 0 | 0.0% | no
2018 | 254 | 0 | 0.0% | no
2019 | 402 | 0 | 0.0% | no
2020 | 404 | 0 | 0.0% | no
2021 | 379 | 0 | 0.0% | no
2022 | 546 | 0 | 0.0% | no
2023 | 719 | 0 | 0.0% | no
2024 | 690 | 4 | 0.6% | no
2025 | 770 | 3 | 0.4% | yes
2026 | 415 | 2 | 0.5% | yes
 
Aggregate row used on the page: 2010-2023 = 3984 corpus papers, 0 ran Foxhound (0.0%). That is 14 consecutive zero years.
 
Same table for the sweep population including citation-only papers, for contrast:
Year | Named anywhere in full text (excl. homographs) 
2024 | 5
2025 | 4
2026 | 2
 
=== D. Does the paper say which Foxhound it ran? ===
 
Population: the papers that ran it. A version or commit is the only way a reader can know which source/sink set and which propagation bugs were in play.
key | role | version stated
CCS/2025/in-the-dom-we-trust-exploring-the-hidden-dangers-of-reading-from-the-dom-on-the | extended | NONE
IEEE-SP/2024/the-great-request-robbery-an-empirical-study-of-client-side-request-hijacking-vu | extended | v98.0.2
IEEE-SP/2024/to-auth-or-not-to-auth-a-comparative-analysis-of-the-pre-and-post-login-security | used | commit 2916e01 (Firefox 109 fork)
NDSS/2025/do-not-follow-the-white-rabbit-challenging-the-myth-of-harmless-open-redirection | baseline | v98.0.2
NDSS/2026/dom-xss-detection-via-webpage-interaction-fuzzing-and-url-component-synthesis | baseline | v126.0
PETS/2024/fp-tracer-fine-grained-browser-fingerprinting-detection-via-taint-tracking-and-e | extended | v96.0.3
PETS/2026/from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr | used | NONE
USENIX/2024/dancer-in-the-dark-synthesizing-and-evaluating-polyglots-for-blind-cross-site-sc | used | NONE
WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet | used | NONE
 
Stated: 5 of 9 (55.6%).
Restricted to the 7 papers that used or extended it (excluding the 2 that ran it only as a baseline): 3 state a version (42.9%).
Broken down by role (computed, not asserted — an earlier hand-written sentence here claimed both extension papers state a version, which is false: Drescher et al. do not):
  baseline: 2 of 2 state a version
  extended: 2 of 3 state a version
  used: 1 of 4 state a version
 
The sweep that produced the hand map (re-run here, so a new edition of the corpus cannot silently change it):
CCS/2025/in-the-dom-we-trust-exploring-the-hidden-dangers-of-reading-from-the-dom-on-the | regex: no match | hand: NONE | agree
IEEE-SP/2024/the-great-request-robbery-an-empirical-study-of-client-side-request-hijacking-vu | regex: "Firefox known as Foxhound (v98.0.2" | hand: v98.0.2 | agree
IEEE-SP/2024/to-auth-or-not-to-auth-a-comparative-analysis-of-the-pre-and-post-login-security | regex: "Foxhound browser commit 2916e01" | hand: commit 2916e01 (Firefox 109 fork) | agree
NDSS/2025/do-not-follow-the-white-rabbit-challenging-the-myth-of-harmless-open-redirection | regex: "Firefox (v98.0.2" | hand: v98.0.2 | agree
NDSS/2026/dom-xss-detection-via-webpage-interaction-fuzzing-and-url-component-synthesis | regex: "FoxHound v126.0" | hand: v126.0 | agree
PETS/2024/fp-tracer-fine-grained-browser-fingerprinting-detection-via-taint-tracking-and-e | regex: "Foxhound [50] (v96.0.3" | hand: v96.0.3 | agree
PETS/2026/from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr | regex: no match | hand: NONE | agree
USENIX/2024/dancer-in-the-dark-synthesizing-and-evaluating-polyglots-for-blind-cross-site-sc | regex: no match | hand: NONE | agree
WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet | regex: no match | hand: NONE | agree
The regex is an upper bound (it also matches an unrelated "Firefox 1xx" sentence), which is why the hand column decides.
 
=== E. Measured results, with each paper's own denominator ===
 
Straight from detection[].prevalence for the papers that ran it. metric names the unit; the denominator is from population[] in the same record.
 
CCS/2025/in-the-dom-we-trust-exploring-the-hidden-dangers-of-reading-from-the-dom-on-the  —  In the DOM We Trust: Exploring the Hidden Dangers of Reading from the DOM on the Web.
   population: 15000 domains from "Tranco list (ID: W88P9)" (top-n), listVersion="W88P9"
   population: 522860 web-pages from "custom seed list" (seed-and-crawl), listVersion=null
   "DOM-to-sink data flows" | verified flow count and affected sites | 357,982 verified gadgets across 14,345 webpages and 2,259 sites
   "Markup injection vulnerabilities" | verified dataflow count | 4,722 verified dataflows across 34,223 webpages
   "DOM-gadget exploitability" | end-to-end verified flows and sites | 657 flows across 37 sites
   "Missing sanitization or validation" | share of static flows without relevant patterns | 10.38% contained no sanitization or validation patterns
   "DOM selector complexity" | mean and median complexity | average 1.80 and median 2
   "Element-order exploitation requirement" | share requiring reordering techniques | 34% of 253K combinations had injected markup after the selected element
   "Detection false negatives" | false negative rate | 38.5%
 
IEEE-SP/2024/the-great-request-robbery-an-empirical-study-of-client-side-request-hijacking-vu  —  The Great Request Robbery: An Empirical Study of Client-side Request Hijacking Vulnerabilities on the Web.
   population: 10000 websites from "Tranco" (top-n), listVersion="downloaded September 29, 2022; ID N7QWW"
   "client-side request hijacking data flows" | verified vulnerable data flows, affected webpages and sites | 202,834 verified flows affecting 17,805 webpages and 961 sites; 9.6% of the top 10K sites
   "request-sending API usage" | API calls, webpages and domains | Approximately 7.9M API calls across 1,032,795 webpages and 9,901 domains
   "request hijacking exploitability" | proof-of-concept exploits and affected websites | 67 proof-of-concept exploits across 49 websites
   "defense adoption and coverage" | pages and sites adopting defenses; mitigated flow share | CSP mitigated information leakage and XSS in 58.7% of flows; 7.6% of webpages deployed the relevant CSP directive
 
IEEE-SP/2024/to-auth-or-not-to-auth-a-comparative-analysis-of-the-pre-and-post-login-security  —  To Auth or Not To Auth? A Comparative Analysis of the Pre- and Post-Login Security Landscape.
   population: 445 websites from "Tranco" (top-n), listVersion="ID N76GW, July 4, 2023"
   population: 5000 websites from "CrUX" (top-n), listVersion="Top 5K, April 2023"
   population: 4485 websites from "Tranco and CrUX" (purposive), listVersion=null
   population: 200 websites from "Tranco and CrUX" (purposive), listVersion=null
   "client-side XSS" | vulnerable sites and verified exploits | 7 unique vulnerable sites; 6 persistent and 1 reflected
   "security-header deployment" | site-level secure, insecure, or missing headers | X-Frame-Options appeared on average in 56% of responses
   "security-header inconsistency" | share of URLs with consistent headers | over 99% of URLs had consistent headers
   "JavaScript inclusions" | parsed scripts and unique scripts | 42,437,161 scripts parsed
   "vulnerable JavaScript libraries" | sites containing vulnerable libraries | 143 authenticated and 145 unauthenticated sites
   "third-party scripts and tracking" | unique third-party scripts and trackers | 15.47% more unique tracking entities in Sauth
   "postMessage handlers" | AST-unique handlers | 899 authenticated versus 493 unauthenticated AST-unique handlers
   "postMessage vulnerabilities" | verified exploitable handlers | 2 exploits affecting one authenticated-state site
 
NDSS/2025/do-not-follow-the-white-rabbit-challenging-the-myth-of-harmless-open-redirection  —  Do (Not) Follow the White Rabbit: Challenging the Myth of Harmless Open Redirection
   population: 10000 websites from "Tranco" (top-n), listVersion="ID N7QWW, downloaded Sept. 29, 2022"
   population: 1034521 web-pages from "Tranco" (top-n), listVersion="ID N7QWW, collected October 2022"
   population: 42288 web-pages from "P2 dataset" (random), listVersion=null
   population: 4000 websites from "candidate sites matching indicators" (random), listVersion=null
   "open redirect vulnerabilities" | number of confirmed vulnerabilities and affected websites | 20,898 confirmed open redirections across 623 websites
   "open redirect prevalence" | share of top-10K websites | approximately 8.7% of the top 10K websites
   "archived open redirects" | confirmed vulnerabilities and affected websites | 375 vulnerabilities across 326 websites
   "DOM-based XSS escalation" | share of vulnerabilities and affected sites | about 9% of vulnerabilities across 33.2% of affected sites
   "client-side CSRF escalation" | number and share of open redirects | 42 vulnerabilities, over 2.4% of open redirects
   "information leakage escalation" | number and share of open redirects | 3 vulnerabilities, about 0.2% of open redirects
   "redirect mitigations" | share of audited sites | six mitigation types; redirect notices used by 54.4%
   "indicator false negatives" | false-negative rate | 76% for indicators compared with static analysis
 
NDSS/2026/dom-xss-detection-via-webpage-interaction-fuzzing-and-url-component-synthesis  —  DOM-XSS Detection via Webpage Interaction Fuzzing and URL Component Synthesis
   population: 30000 domains from "Tranco" (top-n), listVersion="generated 04 March 2025"
   population: 44480 web-pages from "Tranco" (seed-and-crawl), listVersion="generated 04 March 2025"
   population: 13555 web-pages from "custom seed list" (random), listVersion=null
   population: 194 web-pages from "custom seed list" (exhaustive), listVersion=null
   "DOM-XSS vulnerabilities" | unique confirmed vulnerable flows and pages | 114 unique DOM-XSS vulnerable flows in 146 pages
   "Interaction-triggered DOM-XSS" | confirmed-flow increase over passive analysis | 15% more confirmed flows than Passive
   "URL-parameter and fragment-triggered DOM-XSS" | new confirmed vulnerabilities | 20 new vulnerabilities
   "Synthesized GET parameters" | overlap with ffuf/wfuzz wordlists | 95.6% of DSE-synthesized keys absent from those wordlists
 
PETS/2024/fp-tracer-fine-grained-browser-fingerprinting-detection-via-taint-tracking-and-e  —  FP-tracer: Fine-grained Browser Fingerprinting Detection via Taint-tracking and Entropy-based Thresholds
   population: 100000 domains from "Tranco" (top-n), listVersion="N7QVW"
   population: 85576 other from "Ad Fingerprinting dataset from a related research study [14]" (pre-existing-dataset), listVersion=null
   "browser fingerprinting flows" | number of fingerprinting flows and attribute combinations | 269 784 fingerprinting flows and 15 239 unique browser attribute combinations
   "entropy-based fingerprinting severity" | share of crawled domains per entropy category | Very High 8.08%, High 61.49%, Medium 30.94%, Low 58.99%
   "audio fingerprinting" | number of crawled domains | 54 crawled domains
   "canvas fingerprinting" | number of crawled domains | 6237 crawled domains
   "storage fingerprinting" | number of domains | storageEstimate.quota detected in 148 domains
   "fingerprinting obfuscation" | share of transmitted attributes obfuscated | 46% of transmitted attributes in the most severe category
   "collaborative fingerprinting" | share of fingerprinting involving multiple domains | 38% of fingerprinters involve two or more domains
   "consent-banner impact" | domain prevalence by entropy category | Accepting all data collection increased activity to almost 90% of domains
 
PETS/2026/from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr  —  From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques
   population: 10000 websites from "Tranco" (top-n), listVersion="generated February 8, 2026"
   "stateful tracking requests" | number of tracking requests | 40,605 total; 33,584 detected by syntactic matching
   "stateful tracking requests" | number of tracking requests | 23,109 detected by taint tracking
   "syntactic-matching false positives" | false-positive rate | 16%-19% overall; 27%-30% for syntactic-only requests
   "syntactic-matching false negatives" | share of dataset | 7,021 requests, around 17%, detected by taint tracking alone
 
USENIX/2024/dancer-in-the-dark-synthesizing-and-evaluating-polyglots-for-blind-cross-site-sc  —  Dancer in the Dark: Synthesizing and Evaluating Polyglots for Blind Cross-Site Scripting
   population: 10000 domains from "Tranco" (top-n), listVersion="W95V9, Dec. 15, 2022"
   population: 100000 domains from "Tranco" (top-n), listVersion="824JV, Oct. 9, 2022"
   population: 111 other from "Google Firing Range" (purposive), listVersion="0.48"
   "XSS polyglot coverage" | number of injection contexts solved | Seven polyglots covered all 111 selected GFR test cases.
   "client-side XSS" | validated vulnerabilities | 147 vulnerabilities triggered by synthesized polyglots versus 145 by precise payload generation.
   "blind XSS" | vulnerabilities and affected websites | 20 vulnerabilities on 18 websites.
   "blind XSS" | share of backends by submission type | Headers triggered 10 vulnerabilities, URLs 9, and forms 1.
   "crawler page failures" | share of visited pages failing | Approximately 7.4% of 1,676,812 visited pages failed to load.
 
WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet  —  Dynamic Security Analysis of JavaScript: Are We There Yet?
   population: 6921 domains from "Tranco" (top-n), listVersion="27 September 2024"
   "JavaScript compatibility" | percentage of scripts compatible | Project Foxhound successfully analyzed 95% of collected scripts
   "Transparency violations" | transparency rate | Project Foxhound was transparent on 97% of websites
   "Information flows" | number of detected flows and estimated true positives | Project Foxhound detected 919 flows; 94% met at least one agreement heuristic
   "Runtime overhead" | average overhead ratio | PanoptiChrome 36.7x, LinvailTaint 23.9x, JalangiTT 8.6x, Project Foxhound 1.4x
   "JavaScript language features" | feature frequency among analyzed scripts | Block scoping 25% and arrow functions 24%
 
=== F. Other in-browser taint trackers named in the corpus ===
 
Counts papers over tools[] and otherToolsMentioned[]. Ordered families from fh_fold.mjs TAINT_TOOLS, first match wins; every remaining tool string matching /taint/i is printed as residue.
Family | Papers
Project Foxhound — patched Firefox (in-engine) | 9
PanoptiChrome — patched Chromium (in-engine) | 2
ChromiumTaintTracking — patched Chromium (in-engine) | 0
Jalangi / JalangiTT — source instrumentation | 6
JSFlow — instrumented interpreter | 1
LinvailTaint — source instrumentation | 1
IF-Transpiler — source rewriting | 1
TaintDroid — Android, not a web instrument | 9
Android taint analysers — not web instruments | 68
 
Residue — tool strings matching /taint/i that no family claims: 21 distinct strings.
  "Taint tracker" (1 papers)
  "taint-aware Firefox engine" (1 papers)
  "static taint analysis engine (custom)" (1 papers)
  "Multiple Taint-Style Vulnerabilities Detector (MTS-VD)" (1 papers)
  "static taint analysis tool" (1 papers)
  "custom taint-aware infrastructure" (1 papers)
  "taint tracking engine" (1 papers)
  "TAINT INDUCE" (1 papers)
  "Taint'em All" (1 papers)
  "Taintless" (1 papers)
  "Taintgrind" (1 papers)
  "TaintGrep" (1 papers)
  "OctopusTaint" (1 papers)
  "TaintScope" (1 papers)
  "ParcelTaint" (1 papers)
  "DeFiTainter" (1 papers)
  "E M TAINT" (1 papers)
  "O CTOPUS TAINT" (1 papers)
  "LuaTaint" (1 papers)
  "file_taint" (1 papers)
  "EmTaint" (1 papers)
 
These are schema counts, not sweep counts, so they are lower bounds in exactly the way the Foxhound count is. The point the page makes from this table is the shape — one web instrument with most of the use, everything else in single digits — not the absolute numbers.
 
=== F2. Taint-tracking browsers in the corpus BEFORE Foxhound ===
 
Query: tools[] or otherToolsMentioned[] with /taint/i in the name and category in {browser, program-analysis, infrastructure}, on papers whose platforms include "web". Then the sentence was read and the paper kept only if the taint browser was its own contribution or its own group's.
year | key | engine | quote located in paper.cols.txt
2013 | CCS/2013/25-million-flows-later-large-scale-detection-of-dom-based-xss | patched Chromium — V8 and the WebKit DOM, byte-level taint | true
2014 | USENIX/2014/precise-client-side-protection-against-dom-based-cross-site-scripting | taint-aware parsers inside the browser, for client-side XSS filtering | true
2015 | CCS/2015/from-facepalm-to-brain-bender-exploring-client-side-cross-site-scripting | patched Firefox — SpiderMonkey and Gecko | true
2019 | NDSS/2019/dont-trust-the-locals-investigating-the-prevalence-of-persistent-client-side-cross-site-scripting-in-the-wild | modified Chromium, storage and cookie sources | true
 
Papers in the lineage table: 4. Papers that ran Foxhound: 9. Earliest Foxhound year in the corpus: 2024.
The full sweep those four were selected from, printed in full so the selection is auditable:
  2015 CCS/2015/from-facepalm-to-brain-bender-exploring-client-side-cross-site-scripting | "taint-aware Firefox engine" [produced] browser
  2015 NDSS/2015/ekhunter-a-counter-offensive-toolkit-for-exploit-kit-infiltration | "Multiple Taint-Style Vulnerabilities Detector (MTS-VD)" [produced] program-analysis
  2014 USENIX/2014/precise-client-side-protection-against-dom-based-cross-site-scripting | "custom taint-aware infrastructure" [produced] infrastructure
  2019 NDSS/2019/dont-trust-the-locals-investigating-the-prevalence-of-persistent-client-side-cross-site-scripting-in-the-wild | "taint tracking engine" [used] program-analysis
  2021 CCS/2021/spinner-automated-dynamic-command-subsystem-perturbation | "Taint'em All" [used] program-analysis
  2021 CCS/2021/spinner-automated-dynamic-command-subsystem-perturbation | "Taintless" [compared] program-analysis
  2025 WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet | "LinvailTaint" [used] program-analysis
 
=== F3. How much of the use is by the people who maintain the browser ===
 
A listed contributor on the project README is counted as a maintainer. Author lists come from data/corpus2/.meta, except PETS and USENIX which carry none (100% of both venues) and were read off the venue landing page — see AUTHORS_FROM_VENUE_PAGE in fh_fold.mjs.
key | authors | contributor co-author(s)
CCS/2025/in-the-dom-we-trust-exploring-the-hidden-dangers-of-reading-from-the-dom-on-the | Jan Drescher; Sepehr Mirzaei; Soheil Khodayari; David Klein; Thomas Barber; Martin Johns; Giancarlo Pellegrino | Thomas Barber, David Klein
IEEE-SP/2024/the-great-request-robbery-an-empirical-study-of-client-side-request-hijacking-vu | Soheil Khodayari; Thomas Barber; Giancarlo Pellegrino | Thomas Barber
IEEE-SP/2024/to-auth-or-not-to-auth-a-comparative-analysis-of-the-pre-and-post-login-security | Jannis Rautenstrauch; Metodi Mitkov; Thomas Helbrecht; Lorenz Hetterich; Ben Stock | none
NDSS/2025/do-not-follow-the-white-rabbit-challenging-the-myth-of-harmless-open-redirection | Soheil Khodayari; Kai Glauber; Giancarlo Pellegrino | none
NDSS/2026/dom-xss-detection-via-webpage-interaction-fuzzing-and-url-component-synthesis | Nuno Sabino; Darion Cassel; Rui Abreu; Pedro Adão; Lujo Bauer; Limin Jia | none
PETS/2024/fp-tracer-fine-grained-browser-fingerprinting-detection-via-taint-tracking-and-e | Soumaya Boussaha; Lukas Hock; Miguel Bermejo; Ruben Cuevas Rumin; Angel Cuevas Rumin; David Klein; Martin Johns; Luca Compagna; Daniele Antonioli; Thomas Barber | Thomas Barber, David Klein, Soumaya Boussaha, Lukas Hock
PETS/2026/from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr | Stefano Calzavara; Samuele Casarin; Marco Squarcina; Matteo Maffei | Samuele Casarin
USENIX/2024/dancer-in-the-dark-synthesizing-and-evaluating-polyglots-for-blind-cross-site-sc | Robin Kirchner; Jonas Moller; Marius Musch; David Klein; Konrad Rieck; Martin Johns | David Klein
WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet | Stefano Calzavara; Samuele Casarin; Riccardo Focardi | Samuele Casarin
 
Papers with at least one listed contributor as co-author: 6 of 9 (66.7%).
This is a lower bound in both directions: the README contributor list is "in no particular order ... ..." and is not exhaustive, and name matching is exact after diacritic folding.
 
=== G. Evidence quotes checked against paper.cols.txt ===
 
PETS/2024/fp-tracer-fine-grained-browser-fingerprinting-detection-via-taint-tracking-and-e | Foxhound [used] | implementation | exact (100%) | "Our instrumented browser FP-tracer extends on a modified version of Foxhound [50] (v96.0.3)"
USENIX/2024/dancer-in-the-dark-synthesizing-and-evaluating-polyglots-for-blind-cross-site-sc | Project Foxhound [used] | methodology | exact (100%) | "we re-use a state-of-the-art taint tracking engine [36] and the associated exploit generation by Bensalim et al. [4]."
CCS/2025/in-the-dom-we-trust-exploring-the-hidden-dangers-of-reading-from-the-dom-on-the | Foxhound [produced] | methodology | partial (67%) | "we created an extended version of the taint-aware Foxhound browser"
WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet | Project Foxhound [used] | methodology | exact (100%) | "Project Foxhound [32]: a modified version of Mozilla Firefox supporting dynamic taint tracking"
NDSS/2026/dom-xss-detection-via-webpage-interaction-fuzzing-and-url-component-synthesis | FoxHound [used] | evaluation | partial (62%) | "We run FoxHound v126.0, the latest release at the time of the crawl, as an end-to-end tool"
NDSS/2025/do-not-follow-the-white-rabbit-challenging-the-myth-of-harmless-open-redirection | Foxhound [compared] | evaluation | partial (62%) | "We considered the following state-of-the-art detectors as baselines: dynamic taint-tracking [24, 36, 45] using Foxhound [44, 45]"
PETS/2026/from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr | Foxhound [used] | methodology | partial (95%) | "To experiment with taint tracking, we use Foxhound [26], a fork of Firefox which modifies its internal string operations to propagate taint information."
IEEE-SP/2024/the-great-request-robbery-an-empirical-study-of-client-side-request-hijacking-vu | Foxhound [used] | methodology | exact (100%) | "We developed a taint-aware crawler based on Playwright [59], an instrumented version of Firefox known as Foxhound (v98.0.2) [22, 23], and Firefox DevTools [60]."
IEEE-SP/2024/to-auth-or-not-to-auth-a-comparative-analysis-of-the-pre-and-post-login-security | Foxhound [used] | methodology | exact (100%) | "To collect taint reports, we used the Foxhound browser engine [39], a fork of Firefox with taint tracking capabilities."
 
Summary: 9 quotes: 5 exact, 4 partial (>=60% of 5-word windows), 0 below threshold, 0 without full text.
 
The deciding quotes in the ROLE hand map are checked separately, because they were read by hand rather than taken from the schema:
PETS/2024/fp-tracer-fine-grained-browser-fingerprinting-detection-via-taint-tracking-and-e | exact (100%)
IEEE-SP/2024/the-great-request-robbery-an-empirical-study-of-client-side-request-hijacking-vu | exact (100%)
IEEE-SP/2024/to-auth-or-not-to-auth-a-comparative-analysis-of-the-pre-and-post-login-security | exact (100%)
USENIX/2024/dancer-in-the-dark-synthesizing-and-evaluating-polyglots-for-blind-cross-site-sc | exact (100%)
CCS/2025/in-the-dom-we-trust-exploring-the-hidden-dangers-of-reading-from-the-dom-on-the | exact (100%)
WWW/2025/dynamic-security-analysis-of-javascript-are-we-there-yet | exact (100%)
PETS/2026/from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr | exact (100%)
NDSS/2025/do-not-follow-the-white-rabbit-challenging-the-myth-of-harmless-open-redirection | exact (100%)
NDSS/2026/dom-xss-detection-via-webpage-interaction-fuzzing-and-url-component-synthesis | exact (100%)
WWW/2024/panoptichrome-a-modern-in-browser-taint-analysis-framework | exact (100%)
USENIX/2025/the-domino-effect-detecting-and-exploiting-dom-clobbering-gadgets-via-concolic-e | exact (100%)
IEEE-SP/2024/a-picture-is-worth-500-labels-a-case-study-of-demographic-disparities-in-local-m | exact (100%)
WWW/2025/query-design-for-crowdsourced-clustering-effect-of-cognitive-overload-and-contex | exact (100%)
Summary: 13 deciding quotes: 13 exact, 0 not exact (column-repair splices; each was read on screen when the verdict was made).
 
=== H. Per-paper figures the page quotes, re-checked against the source text ===
 
paper | figure | found verbatim in paper.cols.txt
WWW/2025 | 18 tools to evaluate | true
WWW/2025 | eight tools run | true
WWW/2025 | 6,921 domains | true
WWW/2025 | 95% compatibility | true
WWW/2025 | 97% transparency | true
WWW/2025 | 919 flows, 94% agreeing | true
WWW/2025 | 1.4x overhead | true
WWW/2025 | PanoptiChrome 36.7x | true
WWW/2025 | six tools evaluated on 6,921 domains | true
WWW/2025 | JSFlow timed out on every site | true
WWW/2025 | GIFC dropped, legacy Linvail | true
WWW/2025 | PanoptiChrome 50% compatibility, unresponsive | true
WWW/2025 | PanoptiChrome unresponsive on complex sites | true
WWW/2025 | PanoptiChrome authors drove it by hand | true
WWW/2025 | PanoptiChrome transparency 77% | true
WWW/2025 | JalangiTT transparency 71% | true
WWW/2025 | JalangiTT 67% / 96% compatibility | true
WWW/2025 | LinvailTaint 47% / 63% compatibility | true
WWW/2025 | LinvailTaint transparency 7% | true
WWW/2025 | JEST 32% and IF-Transpiler 16% eventual compatibility | true
WWW/2025 | IF-Transpiler transparency 82%, JEST 60% | true
WWW/2025 | flow counts 0/35/67/919/128 | true
WWW/2025 | the quoted conclusion | true
NDSS/2026 | 55 event handlers | true
CCS/2025 | one site per library in the benchmark | true
CCS/2025 | 8 of 13 detected = 38.5% FN rate | true
PETS/2026 | 40,605 requests on 7,614 sites | true
PETS/2026 | 23,109 by taint tracking | true
PETS/2026 | 7,021 taint-only | true
PETS/2026 | 4%-7% taint FP vs 16%-19% | true
PETS/2026 | union 34,358 (+49%) | true
PETS/2026 | thousands of LOC to add data types | true
PETS/2026 | yandex numeric round-trip loses taint | true
PETS/2026 | slice over-tainting | true
NDSS/2025 | 72 flows, 2 confirmed XSS | true
NDSS/2025 | why the FP rate is high | true
NDSS/2026 | 68 -> 347 with URL encoding off | true
NDSS/2026 | the extra ones are not exploitable | true
NDSS/2026 | TalkGen ran with encoding disabled | true
IEEE-SP/2024 | Playwright + Foxhound v98.0.2 + DevTools | true
IEEE-SP/2024 | 202,834 flows, 9.6% of top 10K | true
IEEE-SP/2024 | 202,834 verified flows | true
IEEE-SP/2024 | no iframe.srcdoc support | true
IEEE-SP/2024 | Playwright 1.33, commit 2916e01 | true
IEEE-SP/2024 | chose it for modern JS features | true
PETS/2024 | 62 sources, 25 sinks | true
PETS/2024 | added numeric tainting | true
CCS/2025 | DOM reads as sources | true
CCS/2025 | 38.5% false negatives on benchmark | true
USENIX/2025 | rejected: interpreter-level string taint | true
 
50 figures checked, 0 not located.
 
=== Z. Every number on the page that does NOT come from this corpus ===
 
figure | primary source | re-checked by
Firefox 142.0.1 | browser/config/version.txt on SAP/project-foxhound main | foxhound_probe.sh
Playwright v1.58.2, Rust 1.86.0 | .PLAYWRIGHT_VERSION on main | foxhound_probe.sh
34 source prefs, 61 sink prefs, 1 master switch (96 tainting.* prefs) | modules/libpref/init/all.js on main | foxhound_probe.sh
taintfox.escapeURL defaults to false on the main thread and is not declared in all.js; issues #259 (closed 2025-02-14) and #260 (open) | netwerk/base/nsStandardURL.cpp line 116 and the GitHub issues API | foxhound_probe.sh
the Ubuntu and Windows mozconfigs set --disable-sandbox, --without-wasm-sandboxed-libraries and --disable-crashreporter; the macOS one does not; there is no unsuffixed taintfox_mozconfig | taintfox_mozconfig_* on main and the repository contents listing | foxhound_probe.sh
"URLSearchParams.get" trace operation absent at v130.0, present from v140.0.2 | netwerk/base/nsURLHelper.cpp per release tag | foxhound_probe.sh
17 GitHub releases, 2 with binary assets (v128.0, v140.0.2) | GitHub releases API | foxhound_probe.sh
prefs first appear in v118.0.1 (85 prefs, 25 sources); the DOM-read sources and the current 34/61 arrive in v119.0 | all.js at each release tag | foxhound_probe.sh
DOM-read sources added in PR #198, merged 2024-02-08 | GitHub pulls API | foxhound_probe.sh
URL.parse / URLSearchParams operations added in PR #350, merged 2025-11-26 | GitHub pulls API | foxhound_probe.sh
build 81 min Ubuntu / 134 min Windows / 148 min macOS; 34 min JS tests; 7 min taint tests | GitHub Actions job timings, browser.yml run 26110426051 (2026-05-19) | foxhound_probe.sh
browser.yml and playwright.yml fail on main at 7ce49d32 (2026-07-24), in Bootstrap/Configure, while main.yml passes | GitHub Actions API | foxhound_probe.sh
the playwright-1.62 catch-up branch fails the browser build (newest run 2026-08-06) | GitHub Actions API, browser.yml runs filtered to non-main branches | foxhound_probe.sh
TU-BS: "All binaries are compiled under Debian Bookworm (i.e., stable) and target Linux", 61 SHA256 Checksum labels | foxhound.ias.tu-bs.de, quoted verbatim by the probe | foxhound_probe.sh
newest prebuilt binary: commit 1bb8dbd6, 2026-05-19 | foxhound.ias.tu-bs.de | foxhound_probe.sh
Firefox stable 153.0.4 | product-details.mozilla.org | foxhound_probe.sh
Playwright 1.62.1 baseline is Firefox 153.0; 1.58 baseline is 142.0.1 | playwright browser_patches/firefox/UPSTREAM_CONFIG.sh | foxhound_probe.sh
GPL-3.0, 6.1 GiB checkout, repository created 2021-06-04 | GitHub repos API | foxhound_probe.sh
Klein et al., EuroS&P 2022 is the citation the project asks for | README "Cite us!" section | foxhound_probe.sh
14 publications on the project wiki Hall of Fame | project-foxhound.wiki Publications.md | foxhound_probe.sh
flow trace is "best-effort" and records no function-call nodes under JIT | taint/docs/TaintFlow.md | foxhound_probe.sh
report.detail fields: subframe, loc, parentloc, referrer, str, sink, stack | wiki Playwright-Integration.md | foxhound_probe.sh
Ubuntu CI asks for 10 GB swap and a disk purge; Windows for a 4-10 GB pagefile | .github/workflows/browser.yml | foxhound_probe.sh
TU-BS offers 31 per-commit builds, Debian Bookworm, Linux only | foxhound.ias.tu-bs.de | foxhound_probe.sh
 
=== Z2. The exact literals those facts appear as on the page ===
 
So that check_page_numbers.mjs can pass over the whole page without polluting its shared ALLOW map. Every line here is a number printed on the page whose source is NOT this corpus.
literal | source
142.0.1 | Foxhound main version.txt
153.0.4 | current stable Firefox (product-details.mozilla.org)
153.0 | Firefox baseline of Playwright main
v1.58.2 / 1.58 | PLAYWRIGHT_VERSION on Foxhound main
v1.62.1 / 1.62 | Playwright's current release, and the name of Foxhound's catch-up branch
1.86.0 | RUST_VERSION in .PLAYWRIGHT_VERSION
34 / 61 / 96 | tainting.* pref counts on main
85 / 25 / 59 | tainting.* pref counts at v118.0.1
17 releases, 2 with binaries, v128.0 and v140.0.2 | GitHub releases API
31 commits | builds offered by foxhound.ias.tu-bs.de
SHA-256 | checksum algorithm named on the TU-BS page — not a figure
1bb8dbd6 / 7ce49d32 | commit hashes, GitHub Actions API
81.3 / 34.2 / 7.2 / 130.6 min (Ubuntu) | browser.yml run 26110426051 step timings
134.1 / 147.5 min (Windows) | same run
148.1 / 153.0 min (macOS) | same run
ubuntu-22.04 | runner image named in browser.yml — not a figure. The number scanner also extracts 22.04 and 2.0 from this token; neither is a figure.
10 GB swap, 4-10 GB pagefile | browser.yml resource steps
6.1 GiB | repository size, GitHub repos API
14 publications | project wiki Publications.md
taint-flow extension last pushed 2026-03-11; ZAP add-on last pushed 2026-08-06; ZAP catalogue status Alpha | GitHub repos API and zaproxy.org/docs/desktop/addons/foxhound/
v119.0, 2024-03-07 / PR #198, 2024-02-08 / PR #350, 2025-11-26 / issues #259, #260, #289 | release tags, pulls and issues API
taintfox.escapeURL, default false, line 116; 0 occurrences of "taintfox" in all.js | netwerk/base/nsStandardURL.cpp and all.js
68 -> 347 confirmed DOM-XSS flows, i.e. 5x | Sabino et al., NDSS 2026, already in section H
19 self-test checks, 7 mutations of the documented fixture | python3 pages/foxhound_flows.py --selftest
PR #198 touched 36 files | the PR object's changed_files field. A naive GET of /pulls/198/files returns 30 (its default page size) and under-counts; the external-currency reviewer reported 29 for this reason. The probe asks for per_page=50 and prints changed_files beside it.
12345, TRK-a55bd7c6, 11-16, 22 characters, 5 characters | strings from the documented worked example and from a cited paper — not figures
200, 202, 203, 204 | line numbers inside the documented worked-example JSON reproduced in the embedded script fixture, plus the digits of citekeys such as klein2022_handsanitizers — not figures. Only visible with check_page_numbers.mjs --code.
 
And the per-paper literals the page quotes that are in a cited paper but not in the extraction schema (all re-checked in section H):
  16,088 requests found by both techniques (Calzavara et al., PETS 2026)
  34,358 requests in the union, +49% (same)
  4%-7% and 16%-19% false-positive estimates (same)
  40,605 / 33,584 / 23,109 / 7,021 requests (same)
  7,614 websites correctly accessed (same)
  18 tools screened, eight run, 6,921 domains (Calzavara et al., WWW 2025)
  95% / 97% / 919 / 94% / 1.4x / 36.7x / 23.9x / 8.6x / 128 / 67 / 35 / 0 / 77% / 71% / 82% / 63% / 16% (same, Tables 1-3)
  68 -> 347 confirmed flows, 15% more confirmed flows, 20 new vulnerabilities, 55 event handlers (Sabino et al., NDSS 2026)
  72 flows, 2 confirmed, 42,288 pages (Khodayari et al., NDSS 2025)
  202,834 flows, 9.6% of the top 10K (Khodayari et al., IEEE S&P 2024)
  7 vulnerable sites, ~200 sites (Rautenstrauch et al., IEEE S&P 2024)
  62 sources, 25 sinks, 269,784 flows, top 100K (Boussaha et al., PETS 2024) — the extraction renders the flow count with a thin space, the page with a comma
  357,982 gadgets, 14,345 pages, 2,259 sites, 38.5%, 13 sites (Drescher et al., CCS 2025)

Probe output

foxhound_probe-output.txt
foxhound_probe.sh — run at 2026-08-17T17:36:18Z
 
=== 1. Repository state ===
  full_name: SAP/project-foxhound
  description: A web browser with dynamic data-flow tracking enabled in the Javascript engine and DOM, based on Mozilla Firefox (https://github.com/mozilla-firefox/firefox). It can be used to identify insecure data flows or data privacy leaks in client-side web applications.
  license: GPL-3.0
  archived: False
  pushed_at: 2026-07-29T12:55:26Z
  updated_at: 2026-07-31T16:57:03Z
  stargazers_count: 177
  forks_count: 30
  open_issues_count: 60
  size: 6354292 KB checkout (6.1 GiB)
  default_branch: main
  created_at: 2021-06-04T12:32:12Z
 
=== 2. What main is pinned to ===
  browser/config/version.txt: 142.0.1
  PLAYWRIGHT_VERSION="v1.58.2"
  RUST_VERSION="1.86.0"
  --- current upstream, for the lag ---
  Firefox stable: 153.0.4  ESR: 140.13.0esr
  Playwright latest release: v1.62.1
  Playwright release-1.58: Firefox baseline e0df3d59 = 142.0.1
  Playwright main: Firefox baseline f1b6c0f8 = 153.0
 
=== 3. Taint sources and sinks, counted from the pref list on main ===
  tainting.* prefs total: 96
  sources: 34
  sinks:   61
  master switch: pref("tainting.active", true)
  prefs not defaulting to true: 0
  --- source names ---
    location.hash
    location.host
    location.hostname
    location.href
    location.origin
    location.pathname
    location.port
    location.protocol
    location.search
    window.name
    document.referrer
    document.baseURI
    document.documentURI
    document.cookie
    localStorage.getItem
    sessionStorage.getItem
    MessageEvent
    PushMessageData
    PushSubscription.endpoint
    WebSocket.MessageEvent.data
    XMLHttpRequest.response
    input.value
    textarea.value
    script.innerHTML
    document.getElementById
    document.getElementsByTagName
    document.getElementsByTagNameNS
    document.getElementsByClassName
    document.querySelector
    document.querySelectorAll
    document.elementFromPoint
    document.elementsFromPoint
    element.attribute
    element.closest
  --- sink names ---
    element.after
    element.before
    EventSource
    Function.ctor
    Range.createContextualFragment(fragment)
    WebSocket
    WebSocket.send
    XMLHttpRequest.open(password)
    XMLHttpRequest.open(url)
    XMLHttpRequest.open(username)
    XMLHttpRequest.send
    XMLHttpRequest.setRequestHeader(name)
    XMLHttpRequest.setRequestHeader(value)
    a.href
    area.href
    document.cookie
    document.writeln
    document.write
    element.style
    embed.src
    eval
    eventHandler
    fetch.body
    fetch.url
    form.action
    iframe.src
    iframe.srcdoc
    img.src
    img.srcset
    innerHTML
    insertAdjacentHTML
    insertAdjacentText
    localStorage.setItem
    localStorage.setItem(key)
    location.assign
    location.hash
    location.host
    location.href
    location.pathname
    location.port
    location.protocol
    location.replace
    location.search
    media.src
    navigator.sendBeacon(body)
    navigator.sendBeacon(url)
    object.data
    outerHTML
    script.innerHTML
    script.src
    script.text
    script.textContent
    sessionStorage.setItem
    sessionStorage.setItem(key)
    setInterval
    setTimeout
    source
    srcset
    track.src
    window.open
    window.postMessage
 
=== 3b. taintfox.escapeURL — the URL-encoding knob, which is NOT in all.js ===
  114-
  115-  // Foxhound: check whether to encode URL
  116:  bool encodeURL = NS_IsMainThread() ? Preferences::GetBool("taintfox.escapeURL", false) : true;
  117-  if (!encodeURL) {
  118-    aMask |= esc_Never;
  119-  }
  declared in all.js? 0 occurrences of "taintfox" (expect 0)
  issue #259: Passing URL directly in FoxHound command brings back URL encoding | state closed | created 2025-02-13 | closed 2025-02-14
  issue #260: Clear up URL encoding flags | state open | created 2025-02-14 | closed -
 
=== 3c. The build configuration actually shipped ===
  --- taintfox_mozconfig_ubuntu ---
    ac_add_options --disable-updater
    ac_add_options --with-branding=browser/branding/foxhound
    export MOZ_PACKAGE_JSSHELL=1
    ac_add_options --with-app-name=foxhound
    mk_add_options MOZ_APP_NAME=foxhound
    mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-tf-release
    ac_add_options --disable-sandbox
    ac_add_options --without-wasm-sandboxed-libraries
    ac_add_options --disable-crashreporter
    ac_add_options --disable-backgroundtasks
    ac_add_options --enable-release
    ac_add_options --enable-js-shell
  --- taintfox_mozconfig_win ---
    ac_add_options --disable-updater
    ac_add_options --with-branding=browser/branding/foxhound
    export MOZ_PACKAGE_JSSHELL=1
    ac_add_options --with-app-name=foxhound
    mk_add_options MOZ_APP_NAME=foxhound
    mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-tf-release
    ac_add_options --disable-sandbox
    ac_add_options --without-wasm-sandboxed-libraries
    ac_add_options --disable-crashreporter
    ac_add_options --disable-backgroundtasks
    ac_add_options --enable-release
  --- taintfox_mozconfig_mac ---
    mk_add_options MOZ_MAKE_FLAGS="-s -j5"
    ac_add_options --with-ccache=/usr/bin/ccache
    ac_add_options --enable-macos-target=10.10
    mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-tf-release
    ac_add_options --disable-tests
  --- is there an unsuffixed taintfox_mozconfig, as the README command implies? ---
    mozconfig files present: ['taintfox_mozconfig_mac', 'taintfox_mozconfig_spidermonkey', 'taintfox_mozconfig_ubuntu', 'taintfox_mozconfig_ubuntu_clang_plugin', 'taintfox_mozconfig_ubuntu_debug', 'taintfox_mozconfig_win']
    unsuffixed taintfox_mozconfig present: False (README shows `cp taintfox_mozconfig .mozconfig`)
 
=== 4. When the pref mechanism and the DOM-read sources arrived ===
  v80.0: total=0 sources=0 sinks=0 querySelector-source=0
  v96.0.3: total=0 sources=0 sinks=0 querySelector-source=0
  v98.0.2: total=0 sources=0 sinks=0 querySelector-source=0
  v112: total=0 sources=0 sinks=0 querySelector-source=0
  v115: total=0 sources=0 sinks=0 querySelector-source=0
  v118.0.1: total=85 sources=25 sinks=59 querySelector-source=0
  v119.0: total=96 sources=34 sinks=61 querySelector-source=1
  v121.0: total=96 sources=34 sinks=61 querySelector-source=1
  v123.0: total=96 sources=34 sinks=61 querySelector-source=1
  v125.0: total=96 sources=34 sinks=61 querySelector-source=1
  v126.0: total=96 sources=34 sinks=61 querySelector-source=1
  v128.0: total=96 sources=34 sinks=61 querySelector-source=1
  v130.0: total=96 sources=34 sinks=61 querySelector-source=1
  v140.0.2: total=96 sources=34 sinks=61 querySelector-source=1
  142.0.1: total=96 sources=34 sinks=61 querySelector-source=1
  --- URLSearchParams.get trace operation, per release tag (PR #350) ---
    v130.0: 0
    v140.0.2: 1
    142.0.1: 1
    main: 1
  --- the two PRs the page dates a capability to ---
  PR #198: DOM Related Sources and Sinks | author tmbrbr | merged True at 2024-02-08T09:35:43Z | changed_files 36 (+957/-235)
  NOTE: changed_files comes from the PR object. The /files endpoint pages at 30 by
        default, so a naive fetch under-counts; this probe asks for per_page=50.
      modified +2 -0 dom/base/CharacterData.h
      modified +2 -0 dom/base/DocumentFragment.h
      modified +24 -3 dom/base/DocumentOrShadowRoot.cpp
      modified +64 -23 dom/base/Element.cpp
      modified +29 -13 dom/base/Element.h
      modified +10 -6 dom/base/XPathGenerator.cpp
      modified +4 -1 dom/base/XPathGenerator.h
      modified +15 -4 dom/base/nsAttrValue.cpp
      modified +4 -0 dom/base/nsAttrValue.h
      modified +3 -0 dom/base/nsAttrValueInlines.h
      modified +20 -5 dom/base/nsContentList.cpp
      modified +8 -0 dom/base/nsContentUtils.cpp
      modified +2 -0 dom/base/nsIContent.h
      modified +52 -1 dom/base/nsINode.cpp
      modified +1 -1 dom/html/HTMLInputElement.cpp
      modified +1 -1 dom/html/HTMLTextAreaElement.cpp
      modified +2 -2 dom/html/HTMLTextAreaElement.h
      modified +4 -1 dom/html/nsGenericHTMLElement.cpp
      modified +73 -26 dom/tainting/nsTaintingUtils.cpp
      modified +13 -17 dom/tainting/nsTaintingUtils.h
      modified +22 -4 js/xpconnect/src/xpcpublic.h
      modified +38 -15 modules/libpref/init/all.js
      modified +3 -3 parser/html/nsHtml5Portability.cpp
      modified +1 -0 parser/html/nsHtml5Portability.h
      modified +6 -0 parser/html/nsHtml5String.cpp
      modified +20 -1 parser/html/nsHtml5String.h
      modified +72 -72 parser/html/nsHtml5Tokenizer.cpp
      modified +16 -11 parser/html/nsHtml5Tokenizer.h
      modified +1 -0 parser/html/nsHtml5TreeBuilder.cpp
      modified +2 -0 parser/html/nsHtml5TreeOperation.cpp
      modified +132 -20 taint/Taint.cpp
      modified +61 -3 taint/Taint.h
      added +0 -0 taint/test/mochitest/default16.png
      modified +1 -0 taint/test/mochitest/mochitest.ini
      added +247 -0 taint/test/mochitest/test_dom.html
      modified +2 -2 xpcom/string/nsStringBuffer.cpp
  PR #350: Adding URL related Taint Operations | author tmbrbr | merged True at 2025-11-26T16:50:06Z | changed_files 4 (+28/-1)
  NOTE: changed_files comes from the PR object. The /files endpoint pages at 30 by
        default, so a naive fetch under-counts; this probe asks for per_page=50.
      modified +22 -0 dom/tainting/nsTaintingUtils.cpp
      modified +1 -0 dom/tainting/nsTaintingUtils.h
      modified +3 -1 dom/url/URL.cpp
      modified +2 -0 netwerk/base/nsURLHelper.cpp
 
=== 5. Releases, and which ship a binary ===
  17 releases
  142.0.1      2026-06-15  assets: 0 
  v140.0.2     2026-02-23  assets: 3 ['foxhound-140.0.2.en-US.linux-x86_64.tar.xz', 'foxhound-140.0.2.en-US.mac.dmg', 'foxhound-140.0.2.en-US.win64.installer.exe']
  v130.0       2025-09-05  assets: 0 
  v128.0       2025-05-16  assets: 4 ['foxhound-128.0.en-US.linux-x86_64.tar.bz2', 'foxhound-128.0.en-US.macos-13.dmg', 'foxhound-128.0.en-US.macos-latest.dmg', 'foxhound-128.0.en-US.win64.installer.exe']
  v126.0       2025-03-17  assets: 0 
  v125.0       2025-01-27  assets: 0 
  v123.0       2024-09-09  assets: 0 
  v121.0       2024-04-25  assets: 0 
  v119.0       2024-03-07  assets: 0 
  v118.0.1     2024-01-17  assets: 0 
  v115         2024-01-09  assets: 0 
  v114.0.2     2023-10-12  assets: 0 
  v113.0.1     2023-08-11  assets: 0 
  v112         2023-07-31  assets: 0 
  v98.0.2      2023-05-08  assets: 0 
  v96.0.3      2022-04-20  assets: 0 
  v80.0        2021-10-21  assets: 0 
  releases with binary assets: 2 -> ['v140.0.2', 'v128.0']
 
=== 6. Prebuilt binaries hosted by TU Braunschweig ===
  page bytes: 78313
  platform sentence: All binaries are compiled under Debian Bookworm (i.e., stable) and target Linux
  SHA256 Checksum labels on the page: 61
  commits offered: 31
    1bb8dbd6  Tue, 19 May 2026 17:16:09 GMT
    a3def318  Wed, 13 May 2026 12:11:03 GMT
    09dda176  Wed, 25 Feb 2026 14:22:21 GMT
    8c191733  Mon, 23 Feb 2026 13:33:07 GMT
  playwright versions offered: ['v1.46.0', 'v1.47.0', 'v1.48.2', 'v1.49.1', 'v1.53.2', 'v1.56.1', 'v1.58.2']
 
=== 7. CI state on main, and how long a build takes ===
  browser.yml on main (newest first):
    2026-07-24  failure  7ce49d32
    2026-05-19  success  1bb8dbd6
    2026-05-12  success  a3def318
  playwright.yml on main (newest first):
    2026-07-24  failure  7ce49d32
    2026-05-19  success  1bb8dbd6
    2026-05-12  success  a3def318
  main.yml on main (newest first):
    2026-07-24  success  7ce49d32
    2026-05-19  success  1bb8dbd6
    2026-05-12  success  a3def318
  --- newest browser.yml run on the Playwright catch-up branch (page claims it fails) ---
    2026-08-06  failure  playwright-1.62  b1610aba
    2026-08-06  failure  playwright-1.62  58a55435
    2026-08-06  failure  playwright-1.62  ca7868b2
    2026-08-06  failure  playwright-1.62  7beb96ee
  --- failing steps of the newest browser.yml run on main ---
    Windows: failure
        failing step: Configure = failure
    Ubuntu: failure
        failing step: Bootstrap = failure
    MacOS: failure
        failing step: Bootstrap = failure
  --- newest SUCCESSFUL browser.yml run on main, with per-step minutes ---
    run id 26110426051
    MacOS: 153.0 min total, runner GitHub Actions 1018788187
        Checkout release branch: 2.8 min
        Bootstrap: 1.1 min
        Build: 148.1 min
    Ubuntu: 130.6 min total, runner GitHub Actions 1018788185
        Free Disk Space (Ubuntu): 1.5 min
        Checkout release branch: 1.8 min
        Bootstrap: 1.3 min
        Build: 81.3 min
        JavaScript Tests: 34.2 min
        Tainting Tests: 7.2 min
        Package: 3.0 min
    Windows: 147.5 min total, runner GitHub Actions 1018788188
        Download Mozilla Build: 1.0 min
        Checkout release branch: 2.5 min
        Bootstrap: 6.8 min
        Build: 134.1 min
        Package: 2.2 min
  --- build resources the workflow itself asks for ---
        runs-on: ubuntu-22.04
            uses: jlumbroso/free-disk-space@main
              swap-size-gb: 10
        runs-on: windows-latest
              minimum-size: 4GB
              maximum-size: 10GB
        runs-on: macos-latest
 
=== 8. The reporting surface the README and wiki document ===
  README contains: __taintreport
  README contains: report.detail
  README contains: JS_ReportTaintSink
  README contains: // Foxhound
  README contains: String.tainted
  README contains: foxhound.ias.tu-bs.de
  README contains: KleBarBen
  README contains: taintfox_mozconfig
  README contains: ./mach build
  --- wiki pages (the wiki is a git repo, so this is the whole set) ---
    Adding-and-Running-Mochi-Tests.md
    Adopting-Foxhound-for-your-Requirements.md
    Building-Foxhound-(with-playwright-integration).md
    Building-Manually.md
    Debugging-Crash-Dumps.md
    Firefox-String-Type.md
    Garbage-Collection-in-Spidermonkey.md
    Home.md
    Memory-Leak-Debugging.md
    Observing-Taint-Flows.md
    Playwright-Integration.md
    Publications.md
    Release-Scheduling.md
    Rust-Errors-due-to-invalid-Bindings-during-Foxhound-Compilation.md
    Source-and-Sink-Listings.md
    Spidermonkey-Debugging-and-Understanding.md
    Taint-Flow-Design-2.0.md
    TaintOperations-and-how-they-come-to-be.md
    Updating-from-upstream-Firefox.md
    Visualizing-Taint-Flows.md
  Publications.md lists: 14 publications
  report.detail fields documented in Playwright-Integration.md:
      subframe:
      loc:
      parentloc:
      referrer:
      str:
      sink:
      stack:
  TaintFlow.md best-effort / JIT caveat:
    (TaintFlow.md is in the repo, not the wiki — see below)
  --- taint/docs/TaintFlow.md in the repo: the JIT caveat ---
    4:The flow is made up of several nodes, one for each operation that was performed on the tainted data. The taint flow tracing is currently considered a "best-effort" service.
    12:The engine will generally fail to record function call information when executing in one of the JIT modes (instead of the interpreter). As such, functions
    19:In theory, they should still be available during JIT execution, however, a few methods are actually "inlined" by the JIT compiler and will thus not be recorded.
  --- taint/docs/SupportedFunctions.md ---
    # List of supported functions
 
    ```
    encodeURI
    encodeURIComponent
    decodeURI
    decodeURIComponent
    JSON.stringify
    JSON.parse
    Array.join
    escape
    unescape
    ```
 
    and [String functions](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String)
 
=== 9. Satellite tooling ===
  --- is the ZAP add-on in ZAP own catalogue? ---
    title: Foxhound
    status Alpha present: True
  m10x/project-foxhound-taint-flow-extension: archived=False pushed=2026-03-11 license=Apache-2.0 stars=1
  SAP/project-foxhound-zap-addon: archived=False pushed=2026-08-06 license=Apache-2.0 stars=2
  therahulkanyal/PanoptiChrome: archived=False pushed=2025-05-05 license=MIT stars=10
 
=== 10. Every external URL the page links, with its HTTP status ===
  200  https://github.com/SAP/project-foxhound
  200  https://github.com/SAP/project-foxhound/tree/main/taint
  200  https://github.com/SAP/project-foxhound/wiki
  200  https://github.com/SAP/project-foxhound/wiki/Observing-Taint-Flows
  200  https://github.com/SAP/project-foxhound/wiki/Source-and-Sink-Listings
  200  https://github.com/SAP/project-foxhound/wiki/Playwright-Integration
  200  https://github.com/SAP/project-foxhound/wiki/Release-Scheduling
  200  https://github.com/SAP/project-foxhound/wiki/Publications
  200  https://foxhound.ias.tu-bs.de/
  200  https://github.com/SAP/project-foxhound-zap-addon
  200  https://github.com/m10x/project-foxhound-taint-flow-extension
  200  https://www.zaproxy.org/docs/desktop/addons/foxhound/
  200  https://firefox-source-docs.mozilla.org/setup/linux_build.html
  200  https://firefox-source-docs.mozilla.org/writing-rust-code/update-policy.html
  200  https://domgo.at/cxss/example/1
 
=== done ===

Bibliography additions

Twelve entries were appended to bibliography, all generated with scripts/bibgen.mjs from the corpus index and then checked for key collisions against the live bibliography (0 collisions, 0 duplicate keys after merge). Four existing keys were reused: klein2022_handsanitizers, boussaha2024_tracer, kanyal2024_panoptichrome, calzavara2026_syntactic.

Key Metadata source Note
lekies2013_million OpenAlex via DOI
stock2014_precise USENIX landing page index record has no authors and no DOI (true of 100% of USENIX and PETS records); bibgen.mjs failed loudly and the author list was read off the venue page with curl and a browser User-Agent
stock2015_facepalm OpenAlex via DOI
steffens2019_dont NDSS venue page bibgen.mjs emitted the slug as the title; corrected by hand
kirchner2024_dancer USENIX landing page authors fetched as above
khodayari2024_great OpenAlex via DOI
rautenstrauch2024_auth OpenAlex via DOI
khodayari2025_follow NDSS venue page no DOI; cited by URL
calzavara2025_dynamic OpenAlex via DOI
liu2025_domino USENIX landing page authors fetched as above
drescher2025_trust OpenAlex via DOI
sabino2026_detection NDSS venue page no DOI; cited by URL

The bibtex plugin serves a cached parse, so after appending, both literature:bibliography and this run's two pages were purged with ?purge=true and the rendered pages re-read to count bibtex_citekey markers and reference-list entries. Skipping that step renders every new citation as broken while both raw sources look perfect.

Review log

Three focused reviewers were run in parallel on the frozen draft, then the generic pass. Each was told explicitly that the author's context may not be exhaustive and was handed the page text, both scripts, both outputs, the published code and the corpus paths.

sonnet — figures versus script

Re-ran both scripts. report_foxhound.mjs output byte-identical to the committed file; foxhound_probe.sh byte-identical except its own run timestamp — no drift in any external fact. Both guards and the code self-test reproduced. It traced ~90 numeric claims and found no wrong figure, no denominator mismatch and no invented pref name. Eight findings, all accepted:

# Finding Disposition
1 The DOM-read source row dropped the document. prefix on 9 of its 10 entries while every other row kept it. Accepted. All ten written out in full.
2 The Calzavara et al. comparison table's per-tool numbers (128/67/35/0 flows, 77%/71%/82%/7% transparency, the compatibility rates) were not in the report's machine-checked FIGURES array — disclosed in Z2 as hand-checked, but a reader who saw check_page_numbers.mjs pass would over-trust them. The reviewer hand-checked all of them and found every value exact. Accepted. Sixteen further needles added to section H; it now checks 48 figures, 0 not located. Also caught two of my own needles that were column-spliced and would have read as failures.
3 “55 realistic event handlers” was in Z2 as “re-checked in section H” but was not actually in section H. The reviewer verified it by hand: the paper says “a total of 55 event handlers”. Accepted, and it is the sharpest kind of finding — the disclosure was true of the intent and false of the artefact. Now in section H.
4 “13-site benchmark” looked like a mis-transcription of the paper's “13 libraries”, but reading the paragraph confirms one site is built per library. Accepted as confirmation; needle added.
5 The prose called Firefox 153.0 “also current stable Firefox”, where stable is 153.0.4 — looser than the page's own Z2 bookkeeping, which lists the two separately. Accepted. Rewritten to give both, and “eleven Firefox versions” is now “eleven Firefox major versions”.
6 A hardcoded sentence in report_foxhound.mjs asserted “both papers whose own contribution is a Foxhound extension state one”, which its own data contradicts: there are three extension papers and Drescher et al. state no version. Never quoted on the page. Accepted, and it is the most useful finding of the round. The sentence is replaced by a computed per-role breakdown (baseline 2 of 2, extended 2 of 3, used 1 of 4). A hand-written sentence inside an audit script is exactly the thing nothing else checks.
7 The “Linux only” and “SHA-256 checksum” claims about the TU Braunschweig host were true but not printed by the probe, so not mechanically re-verifiable. Accepted. The probe now quotes the platform sentence verbatim (“All binaries are compiled under Debian Bookworm (i.e., stable) and target Linux”) and counts the checksum labels (61).
8 The claim that the playwright-1.62 branch was failing CI was not fetched by any script and was untraceable from the artefacts. Accepted. The probe now lists the newest non-main browser.yml runs; the branch's newest run is 2026-08-06, failure.

sonnet — external currency

~25 live fetches. Confirmed as still true today: all 14 page URLs at 200; the Firefox/Playwright/Rust pins and the current-stable comparison; the release list and which two carry binaries; every row of the pref-history table including the document.querySelector pref flipping on at v119.0; both pull-request numbers and merge dates; issue #289 closed 2026-02-09, matching the page's re-clone cut-off; the CI failure on main at 7ce49d32 with no newer run; the per-step build minutes; the TU Braunschweig commit count, platform and newest commit; the taint/README.md staleness and the wiki grep artefacts, both of which the page describes as defects and both of which are still there; 14 publications; and the Cite us! request, unchanged. One finding accepted, one rejected:

# Finding Disposition
1 The ZAP add-on is not merely “first-party”: it is listed in ZAP's own add-on catalogue. Accepted. The page now links the catalogue entry and gives its status (Alpha), and the probe fetches it. The reviewer also reported a version and publication date from the catalogue; those were not reproducible on the page I fetched, so only the facts I could see are on the page.
2 PR #198 changed 29 files, not the 36 the page states. Rejected — the reviewer is wrong, and the reason is worth recording. The GitHub pulls API's /files endpoint pages at 30 by default, so a naive fetch under-counts a 36-file PR. The PR object's own changed_files field says 36; the probe asks for per_page=50 and now prints changed_files beside the file list so the disagreement cannot recur.
3 The extension's last push is 2026-03-11, five months ago, so “maintained” is generous; PanoptiChrome's last commit is 2025-05-05, so it should not be called maintained (the page does not). Accepted in part. The page no longer calls the extension “maintained”; it gives the push dates and lets the reader judge. No change for PanoptiChrome, which the page only cites as the Chromium-side alternative.

sonnet — citations and quotes

16 of 16 citekeys resolve, 0 collisions with the live bibliography, 0 duplicates, all 12 additions valid BibTeX, and every author list, title, venue and year in all 16 entries verified against a primary source — Crossref for the DOI-bearing ones, the venue's own author block for USENIX, PETS and NDSS. It checked 17 quotations: 14 verbatim, 1 genuinely present but column-spliced, 2 wrong, 0 not found. It also independently recounted PR #198 at 36 files, which settles the disagreement with the currency reviewer.

# Finding Disposition
1 The page quoted the project wiki as “always one release behind Playwright”. The wiki says “will always be one release behind Playwright”. Not a splice — this is a plain markdown file, so it was a transcription error. Accepted. Fixed to the exact wording. A one-word slip in a quotation is still a wrong quotation.
2 The page silently corrected a typo in a quoted sentence: Khodayari et al. write “the presense of data flows”; the page wrote “presence”. Accepted. Restored the source spelling with [sic]. Silently fixing a source's typo makes the quote unfindable by anyone who greps for it.
3 The provenance page's methodology paragraph said the 13 hand-picked deciding quotes were “11 exact, 2 shortened”, while the report it cites says “13 exact, 0 not exact”. Accepted. The page was describing the state before I shortened the two spliced quotes. Rewritten to match the artefact and to say why the two are short. This is the failure the provenance page exists to catch, caught on the provenance page itself.
4 The “entire parts array is tainted” quote is present but interleaved line-by-line across two PDF columns in both .cols and .norm; the reviewer reconstructed it from paper.txt. Accepted as confirmation, and noted here as a case where the repaired rendering is worse than the raw one — the opposite of the usual assumption.

Everything else it checked came back verbatim, including all of the load-bearing ones: the JIT/best-effort sentences, the URL-encoding result and its manual sample, the yandex round-trip, “thousands of lines of code”, the 72/2 result, “Foxhound+”, the iframe.srcdoc gap, the modern-JS-features reason for choosing Foxhound over the 2019 Chromium tracker, every cell of the bake-off table, the Cite us! request, the gkrust note, the Atoms “indicate a bug in the engine” line, the worked example's offsets and operation chain, both homographs, and the 6-of-9 contributor overlap with its three named exceptions.

fable — generic

The strongest pass of the four. It read both pages, the assembled provenance page, the published code, and all four neighbouring pages, and it found two genuine defects in the published script plus a factual error, a missing definition, an omitted table row, and a structural problem. Twelve findings; eleven accepted in whole or part, none rejected outright.

# Finding Disposition
1 The published script's encoded flag did not measure what the page claimed. It conflated “arrived URL-encoded” with “the crawl-time substring happened to contain no HTML-significant character”, ignored decoding operations and their order, and — provably, from the self-test — marked the documented location.hashunescapeinnerHTML flow, the textbook exploitable DOM-XSS, as droppable. --drop-encoded would have silently removed true positives. “Deliberately conservative” was also the wrong word: over-marking flows as droppable is aggressive. Accepted in full; this is the most important finding of the whole review. The flag is split into encoded_at_sink (a property of the code: an encode is the last transformation before the sink, decided by walking the sink-first chain and letting the first encode or decode win) and no_syntax_chars (a property of the input you sent, reported beside the table and never dropped). Two new self-tests cover encode-then-decode and the dangerous-payload case; the encodeURIComponent leaves-'() caveat is in the code and on the page. The page paragraph was rewritten around the distinction.
2 jit_blind was satisfied by the reporting harness's own function call. In the documented fixture the only function node is ReportTaintSink from taint_reporting.js — the harness, not application code — so the metric the page presents as a contribution would read 0% blind on every flow of any harness whose report path is traced. script_of had the same bug: it could return the harness script's scripthash as the deduplication key. Accepted in full. A HARNESS_RE (overridable with --harness) excludes harness nodes from both. The fixture's own verdict flipped to JIT-blind, and the self-test now asserts that — the comment that said the opposite was wrong. Running the script with a non-matching harness regex reports 0% instead of 100%, which is the trap made visible.
3 The page's count of 9 contradicts the live programming:crawler and privacy:javascript tables, which say 8. The difference is explicable — those tables count schema tuples, and the extraction files Khodayari et al.'s NDSS 2025 paper as compared — but this page's own reading shows that paper ran the browser, so the neighbours are slightly wrong and a reader following the link meets 8, then 9, unexplained. Accepted. A footnote on this page reconciles the two and says which is the deeper audit. The errata edit to the two neighbours is deferred rather than made silently here: it is queued as its own work item, because editing another page's central table belongs with that page.
4 “Report whether URL encoding was enabled” never named the knob — the page's most emphasised advice was its least usable. Accepted, and it turned into the best external finding of the run. The knob is taintfox.escapeURL, read at netwerk/base/nsStandardURL.cpp:116 with a false default on the main thread (true on workers), documented only in a closed issue thread, and absent from all.js — so it is not one of the 96 prefs and does not appear in about:config until you type it. Open issue #260 asks for exactly that to be fixed. The maintainer's stated reason (mimic legacy IE, which did not encode the hash) is now quoted. The probe fetches the call site, counts taintfox in all.js, and prints both issues' states.
5 The sentence “Part of the apparent decade-long decline in DOM-XSS prevalence is this setting, not the web” was an unattributed causal claim. Accepted. It is Sabino et al.'s argument — “several factors … may contribute to the dwindling number … First, modern browsers encode any special characters in URLs” — and it is now attributed to them rather than asserted.
6 “A field with one instrument and a fringe” listed the three smallest families and omitted Jalangi/JalangiTT at 6, the largest row in the report's own table. Accepted. Jalangi's 6 is now on the page with the reason it is not a competing instrument (a general source-instrumentation framework, mostly used for other things), and the claim is scoped to in-browser engines. Presenting the small rows and skipping the big one is exactly what the residue discipline exists to prevent.
7 Structure: the decision-relevant sections sat behind a 330-line code listing, and “Getting a browser” came after the reducer although you need a browser before you have reports. Accepted, reordered: report contents → source/sink surface → what it does not track → versus the alternatives → getting a browser → reducing reports → use in publications → what to report. The full listing was kept inline (house style on this wiki publishes whole files) but now sits after both decision sections.
8 “Foxhound is a debug-instrumented browser build” was unsupported and probably wrong. Accepted — it was wrong, and checking it produced a better fact. taintfox_mozconfig_ubuntu has the DEBUG block commented out and --enable-release set. What it does set is --disable-sandbox, --without-wasm-sandboxed-libraries and --disable-crashreporter — as does the Windows one, though not the macOS one. The page now has a box on crawling with the sandbox off and on counting crashes yourself, which is a stronger warning than the one it replaced.
9 Two date claims were inferences presented as facts: that PR #350 first shipped in v140.0.2, and that taint “still propagated” through URLSearchParams.get before it. Accepted, both now verified rather than inferred. “URLSearchParams.get” is absent from netwerk/base/nsURLHelper.cpp at v130.0 and present from v140.0.2 (probe checks four tags). The PR diff shows MarkTaintOperation called after an assignment that already carries the taint, so the gap was in the trace, not the tracking — and the page says that, with the call site quoted.
10 “The single most common reporting failure on the tool” was a superlative over an unmeasured field, and “state any of this” over-claimed what the 3-of-7 figure covers. Accepted. The superlative is gone, replaced by the honest reason it cannot be measured (the extraction has no field for which prefs a paper set). “Any of this” is now “even the version or commit”.
11 The provenance run record claimed a generic pass whose findings the log did not contain. Accepted — this section is that content, added before publication, and the assembler refuses to build with an empty slot.
12 Minor: “recent and it is dated” ambiguous; the referrer row had an empty cell; “All three checked” followed a list of two repositories plus a catalogue entry; the intro footnote's “so” was a non-sequitur; the harness input contract lived only in the docstring with no link to the project's Playwright page; UNITS[“flow”] was dead code; the GPL-3.0 licence was missing. All accepted and fixed. The harness contract is now a short paragraph above the listing with a link to the wiki page that gives the ten-line Node script — the reviewer was right that this saves a first-time user a confused half-hour.

Two things the pass explicitly endorsed and which were therefore left alone: the fourteen-zero-years table with its lineage explanation, and the calibrated wording of the judgement-calls table (“did not outlive their paper” rather than “superseded”).

Re-review round

The task's rule is to re-run any reviewer whose findings were acted on. All four rounds' findings were acted on, so the figures/code pass and the citations pass were re-run against the published text (fetched back with ?do=export_raw and byte-identical to the local drafts).

One re-run failed to do its job: the first citations re-review returned a single line saying it would wait for a background agent, with no findings at all. That is recorded rather than quietly dropped — a reviewer that returns nothing is not a pass — and it was replaced with a re-run given an explicit A–K checklist of the specific claims that were new or changed since the first round, with an instruction not to delegate.

The re-review round also produced one finding I caught myself while it ran, recorded above under Quotes and figures checked: three of the section-H needles were short enough to match almost anything, so they were passing for the wrong reason.

The re-run of the claims check verified 15 items against primary sources and confirmed all of them except two, both accepted:

# Finding Disposition
1 The page said Sabino et al. read the decade-long decline in DOM-XSS as this setting “rather than the web having got safer”. The paper actually names several contributing factors and credits genuine improvements among them — better ad blocking, HTTPS/mixed-content enforcement — so the “rather than” was a false dichotomy the authors do not assert. Accepted. Rewritten to quote “several factors, such as dataset and methodology, may contribute”, to say the encoding is the first of them, and to name the genuine improvements alongside. The page now calls it “one measurement artefact among real effects rather than a debunking”.
2 The page stated as fact that PanoptiChrome's own authors avoided the unresponsiveness because they drove it by hand; the paper hedges with “likely because”. Accepted. The hedge is restored.

Everything else it checked came back verbatim, including the taintfox.escapeURL call site and its false default, the absence of taintfox from all.js, the 34/61/1 pref counts, both issue states and the maintainer's legacy-IE sentence, all three mozconfigs and the missing unsuffixed one, the PR #350 diff and the trace-versus-tracking reading of it, the 68→347 quintupling and “would not be exploitable in any modern browser”, every cell of the bake-off table including the five compatibility and five transparency figures, the “presense” misspelling (confirmed in both renderings, so the [sic] is right), and the neighbours' published count of 8. It also noted that for the NDSS 2026 paper paper.cols.txt is the well-ordered rendering and paper.txt the interleaved one — the opposite of the case flagged in round one, which is a useful reminder that neither rendering is reliably the better one.

Rendering check

Both pages were published, then literature:bibliography and both new pages were purged with ?purge=true and the rendered HTML re-read. Without the purge the bibtex plugin serves a cached parse and every new citation renders broken while both raw sources look perfect — the trap recorded on programming:crawler:webxray, where 14 of 20 citations were broken until the purge.

Check Result
literature:bibliography entries after the append 314 → 326 (12 added, 0 collisions, 0 duplicates)
[citekey] markers rendered on the content page 90 bibtex_citekey spans, 0 broken
Distinct citekeys on the content page 16, all resolving
Reference list at the foot of the content page 16 entries, each with author list, venue and a DOI or venue URL
<WRAP important> boxes 5, all rendered as boxes
Footnotes 20
Tables 10 on the content page, 8 here
Downloadable foxhound_flows.py snippet present
Literal {[ sequences left unrendered in prose 0
Real citations on this provenance page 0, as intended; the one textual match is the words “bibtex_citekey” in the prose above
{[key]} written as a literal example here escaped with , renders as text
Unfilled double-brace marker slots in this page 0 — and scripts/build_provenance_foxhound.py refuses to build if a slot has no content. It fired on the first draft of this very row, which wrote the marker syntax out literally; that is the guard working, and the row is now phrased so it cannot trip it
Both <file text> blocks render as downloadable snippets with the full output inline
Reachability the content page was already linked from programming:crawler and privacy:javascript before it existed, so no new inbound link was needed; the two pages link each other, and this one links corpus

Guards run against the final text, all passing: check_tables.mjs on both pages, check_page_numbers.mjs on the content page both windowed and whole-page and with --code, check_attributions.mjs (9 attributions), a citekey-resolution check, a byte-comparison of the embedded script against pages/foxhound_flows.py, and the script's own 19-check self-test.

References

provenance/programming/crawler/foxhound.1786988894.txt.gz · Last modified: by karel.kubicek.claude

Except where otherwise noted, content on this wiki is licensed under the following license: CC BY-NC-SA 4.0
CC BY-NC-SA 4.0 Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki