User Tools

Site Tools


provenance:programming:internet_scanning

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
provenance:programming:internet_scanning [2026/09/17 02:14] – Follow-up run 2026-09-17: ZMap/XMap reconciliation with design:dns, hand audit of all 173 HAND verdicts (ACTIVE 245->242), pinned precision samples; 5 new/changed scripts published. Authored by Claude karel.kubicek.claudeprovenance:programming:internet_scanning [2026/09/17 07:24] (current) – Markup rendering sweep: wrap escapes, CLI flag typography, and heading quotes. Authored by Claude. karel.kubicek.claude
Line 11: Line 11:
   * Corpus at run time: **5,859** extracted papers, 2010–2026, CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf, IEEE S&P. Read-only inputs under ''/workspace/publications_dataset/data/''. No write to the publication mount.   * Corpus at run time: **5,859** extracted papers, 2010–2026, CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf, IEEE S&P. Read-only inputs under ''/workspace/publications_dataset/data/''. No write to the publication mount.
   * **Creating**, not extending. Before writing: ''node scripts/sitemap.mjs'' (168 existing pages, 7 promised-but-missing, all 7 declared on [[:roadmap]]), then exported and read [[design:automated_measurements]], [[:design]], [[:programming]], [[design:ip_classification]], [[design:dns]], [[practices:ethics]], [[security:email_authentication]], [[programming:crawler]] and [[:roadmap]].   * **Creating**, not extending. Before writing: ''node scripts/sitemap.mjs'' (168 existing pages, 7 promised-but-missing, all 7 declared on [[:roadmap]]), then exported and read [[design:automated_measurements]], [[:design]], [[:programming]], [[design:ip_classification]], [[design:dns]], [[practices:ethics]], [[security:email_authentication]], [[programming:crawler]] and [[:roadmap]].
-  * Wiki saves through ''scripts/dw.mjs'' (JSON-RPC) with ''--if-rev'' on every existing page.+  * Wiki saves through ''scripts/dw.mjs'' (JSON-RPC) with ''%%--if-rev%%'' on every existing page.
   * Pages saved this sitting: ''literature:bibliography'' (rev 1789063332 → 1789074254, 8 entries appended), ''programming:internet_scanning'' (new), ''roadmap'' (1789062297 →), ''programming'' (1788006004 →), ''design:automated_measurements'' (1787943845 →), ''security:email_authentication'' (1788954595 →), and this page.   * Pages saved this sitting: ''literature:bibliography'' (rev 1789063332 → 1789074254, 8 entries appended), ''programming:internet_scanning'' (new), ''roadmap'' (1789062297 →), ''programming'' (1788006004 →), ''design:automated_measurements'' (1787943845 →), ''security:email_authentication'' (1788954595 →), and this page.
  
-**A follow-up run on 2026-09-17** worked the three items the 2026-09-10 review left open. It changed the page's population from 245 to **242** and refreshed forty figures. Everything below that carries a number is the state //after// that run; the run itself is written up in [[#Follow-up run, 2026-09-17]], which also says which of the three items is still open.+**A follow-up run on 2026-09-17** worked the three items the 2026-09-10 review left open. It changed the page's population from 245 to **241** and refreshed about forty figures. Everything below that carries a number is the state //after// that run; the run itself is written up in [[#Follow-up run, 2026-09-17]], which also says which of the three items is still open.
  
   * Run date: **2026-09-17** (UTC). Single sitting. Authoring agent: **Claude Opus 5** (Claude Code), item //"internet_scanning: three follow-ups the review left open"//.   * Run date: **2026-09-17** (UTC). Single sitting. Authoring agent: **Claude Opus 5** (Claude Code), item //"internet_scanning: three follow-ups the review left open"//.
   * Corpus unchanged: **5,859** extracted papers. No re-extraction, no new venue-years.   * Corpus unchanged: **5,859** extracted papers. No re-extraction, no new venue-years.
-  * Pages saved: ''programming:internet_scanning'' (rev 1789075937 → 1789610996), ''design:dns'' (1787872903 → 1789610997), this page, and ''provenance:design:dns''. No bibliography change — no new citekeys. +  * Pages saved: ''programming:internet_scanning'', ''design:dns'', ''roadmap'', this page and ''provenance:design:dns''. Each was saved twice: once at ACTIVE=242, then again at **241** after the review passes returned. No bibliography change — no new citekeys. 
-  * Scripts added: ''scripts/reconcile_zmap.mjs'', ''scripts/tool_use_overrides.mjs'', ''scripts/audit_hand_verdicts.mjs''. Scripts changed: ''scripts/scan_fold.mjs'', ''scripts/dns_fold.mjs'', ''scripts/report_internet_scanning.mjs'', ''scripts/report_dns.mjs''. All are published in full at the foot of this page or of [[provenance:design:dns]].+  * Scripts added: ''scripts/reconcile_zmap.mjs'', ''scripts/tool_use_overrides.mjs'', ''scripts/audit_hand_verdicts.mjs''. Scripts changed: ''scripts/scan_fold.mjs'', ''scripts/dns_fold.mjs'', ''scripts/report_internet_scanning.mjs'', ''scripts/report_dns.mjs'', ''scripts/verify_scanning_figures.mjs''. All are published in full at the foot of this page or of [[provenance:design:dns]].
  
 ==== Accidental exposure, caught in this run ==== ==== Accidental exposure, caught in this run ====
Line 33: Line 33:
 | **Creating a page rather than broadening [[design:automated_measurements]]** | That page is a three-branch //router// with a 20 KB budget; it already carries the crawl branch's routing without absorbing [[programming:crawler]]. Absorbing the scan instrument would have made it the only branch page that is also a tool page. | | **Creating a page rather than broadening [[design:automated_measurements]]** | That page is a three-branch //router// with a 20 KB budget; it already carries the crawl branch's routing without absorbing [[programming:crawler]]. Absorbing the scan instrument would have made it the only branch page that is also a tool page. |
 | **A separate fold (''scan_fold.mjs'') rather than extending ''am_fold.mjs''** | ''am_fold.mjs'' backs [[design:automated_measurements]]. Editing it would silently move that page's published 93/40/38/31/25 and its 205-string residue. ''scan_fold.mjs'' is a superset with different //kinds//, a negative-guard list, a generic/proper-name distinction and a 173-entry hand map. The two folds therefore give different counts for the same family — ZMap 95 here against 93 there, nmap 45 against 40, ZGrab 32 against 31, RIPE Atlas 25 there and excluded here. **The content page does not currently enumerate those differences**; the difference is the category restriction plus the looser ''nmap'' anchor, and it is set out in this row rather than there. | | **A separate fold (''scan_fold.mjs'') rather than extending ''am_fold.mjs''** | ''am_fold.mjs'' backs [[design:automated_measurements]]. Editing it would silently move that page's published 93/40/38/31/25 and its 205-string residue. ''scan_fold.mjs'' is a superset with different //kinds//, a negative-guard list, a generic/proper-name distinction and a 173-entry hand map. The two folds therefore give different counts for the same family — ZMap 95 here against 93 there, nmap 45 against 40, ZGrab 32 against 31, RIPE Atlas 25 there and excluded here. **The content page does not currently enumerate those differences**; the difference is the category restriction plus the looser ''nmap'' anchor, and it is set out in this row rather than there. |
-| **ACTIVE = 242, not SCAN = 930, as the page's population** | 930 is a ''studyTypes'' tag and ''studyTypes'' is the least stable field in the schema (57% run-to-run). An instrument page should be denominated by the instrument. The page's //Methodology// section says to treat every //share of 930// as ranking-grade; the individual shares (10.4%, 10.2%, 57.4%, 30.2% …) are **not** individually labelled where they appear, which a review pass fairly called out. | +| **ACTIVE = 241, not SCAN = 930, as the page's population** | 930 is a ''studyTypes'' tag and ''studyTypes'' is the least stable field in the schema (57% run-to-run). An instrument page should be denominated by the instrument. The page's //Methodology// section says to treat every //share of 930// as ranking-grade; the individual shares (10.4%, 10.2%, 57.4%, 30.2% …) are **not** individually labelled where they appear, which a review pass fairly called out. | 
-| **ACTIVE membership is decided by the instrument, not by ''tools[].category''** | ''category'' is a denominator: restricting to ''network-scanner'' gives 228 and loses 14 papers whose ZMap/OONI/Geneva/Censored Planet/hitlist entry is filed under ''other'', ''infrastructure'', ''http-client'' or ''program-analysis''. All 14 are listed in section 1 of the report. |+| **ACTIVE membership is decided by the instrument, not by ''tools[].category''** | ''category'' is a denominator: restricting to ''network-scanner'' gives 227 and loses 14 papers whose ZMap/OONI/Geneva/Censored Planet/hitlist entry is filed under ''other'', ''infrastructure'', ''http-client'' or ''program-analysis''. All 14 are listed in section 1 of the report. |
 | **…but generic strings and hand verdicts stay inside ''category == "network-scanner"''** | Without that restriction ''%%/^custom\b/i%%'' alone put **464** papers in the population, almost all custom //crawlers// and custom //scripts//, and the hand entries ''Python script'', ''nc'' and ''whois'' fired on unrelated papers (so did ''Unicorn'', which the 2026-09-17 audit then removed from the map for a different reason). Families whose regex is a descriptor rather than a coined name are flagged ''generic'' in the fold and only trusted inside that category. | | **…but generic strings and hand verdicts stay inside ''category == "network-scanner"''** | Without that restriction ''%%/^custom\b/i%%'' alone put **464** papers in the population, almost all custom //crawlers// and custom //scripts//, and the hand entries ''Python script'', ''nc'' and ''whois'' fired on unrelated papers (so did ''Unicorn'', which the 2026-09-17 audit then removed from the map for a different reason). Families whose regex is a descriptor rather than a coined name are flagged ''generic'' in the fold and only trusted inside that category. |
-| **The four practice figures are published as "about a fifth", not as percentages** | They are regex probes with a hand-read precision sample of 10–12. Publishing "18.6%" would be a false precision claim. The probe count, the sample, the per-paper verdict and the deciding reading are all below. |+| **The four practice figures are published as "about a fifth", not as percentages** | They are regex probes with a hand-read precision sample of 10–12. Publishing "19.9%" would be a false precision claim. The probe count, the sample, the per-paper verdict and the deciding reading are all below. |
 | **The ethics norms are routed to [[practices:ethics]] and not restated** | That page already carries the SURF/Jisc/Internet2 policy text, Hantke et al.'s operator interviews and the opt-out norm, all with primary sources. This page carries only the //mechanics//: which file, which flag, which DNS record. | | **The ethics norms are routed to [[practices:ethics]] and not restated** | That page already carries the SURF/Jisc/Internet2 policy text, Hantke et al.'s operator interviews and the opt-out norm, all with primary sources. This page carries only the //mechanics//: which file, which flag, which DNS record. |
 | **DNS scanning routed to [[design:dns]]** | ''zdns'' and ''massdns'' fold to kind ''dns'' and are reported but excluded from ACTIVE. [[design:dns]] was written on 2026-08-27 for exactly this reason. | | **DNS scanning routed to [[design:dns]]** | ''zdns'' and ''massdns'' fold to kind ''dns'' and are reported but excluded from ACTIVE. [[design:dns]] was written on 2026-08-27 for exactly this reason. |
Line 47: Line 47:
 ^ Item ^ State ^ ^ Item ^ State ^
 | (1) ''design:dns'' publishes "ZMap and XMap (112 papers)" while this page has 95 + 16 = 111 over a different fold. Overlap artefact or real disagreement? | **Closed.** Neither: one compound ''tools[]'' string. Both pages now agree. | | (1) ''design:dns'' publishes "ZMap and XMap (112 papers)" while this page has 95 + 16 = 111 over a different fold. Overlap artefact or real disagreement? | **Closed.** Neither: one compound ''tools[]'' string. Both pages now agree. |
-| (2) Nobody hand-audited the 174 HAND verdicts for judgement | **Closed.** All read; five kinds changed, one entry removed, ACTIVE 245 → 242. | +| (2) Nobody hand-audited the 174 HAND verdicts for judgement | **Closed.** All read; five kinds changed, one entry removed, five tuples suppressed, ACTIVE 245 → **241**. A review pass re-read every change and every borderline against the papers and found a sixth (see [[#D. Review log, 2026-09-17]]). | 
-| (3) Replace the four practice estimates with per-paper verdicts over the whole hit list | **Not done.** ~354 reads. The sample was made survivable instead; see below. |+| (3) Replace the four practice estimates with per-paper verdicts over the whole hit list | **Not done.** ~351 reads. The sample was made survivable instead; see below. |
  
 ==== A. The ZMap/XMap disagreement with design:dns — resolved ==== ==== A. The ZMap/XMap disagreement with design:dns — resolved ====
Line 83: Line 83:
 The HAND map in ''scan_fold.mjs'' is one verdict per distinct ''category == "network-scanner"'' string the FAMILIES list does not fold. The coverage and staleness guards prove every string has a verdict and every verdict matches a string; **they prove nothing about whether the //kind// is right.** A wrong kind on a one-off scanner name moves ACTIVE by one paper and nothing fires. The HAND map in ''scan_fold.mjs'' is one verdict per distinct ''category == "network-scanner"'' string the FAMILIES list does not fold. The coverage and staleness guards prove every string has a verdict and every verdict matches a string; **they prove nothing about whether the //kind// is right.** A wrong kind on a one-off scanner name moves ACTIVE by one paper and nothing fires.
  
-''scripts/audit_hand_verdicts.mjs'' dumps every entry with the evidence needed to judge it — the tool's ''purpose'', the extractor's ''evidence.quote'', the category and the paper's own title — and its full output is published at the foot of this page. All **174** entries were read on 2026-09-17. Where the name and purpose did not settle it, the paper's ''paper.cols.txt'' was read as well.+''scripts/audit_hand_verdicts.mjs'' dumps every entry with the evidence needed to judge it — the tool's ''purpose'', the extractor's ''evidence.quote'', the category and the paper's own title — and its full output is published at the foot of this page. All **174** entries were read on 2026-09-17 (the map is 173 afterwards, because one entry was removed). Where the name and purpose did not settle it, the paper's ''paper.cols.txt'' was read as well.
  
 **Five verdicts changed.** Each is annotated inline in the fold source with the sentence that decided it. **Five verdicts changed.** Each is annotated inline in the fold source with the sentence that decided it.
Line 94: Line 94:
 | ''LFP'' | topology | grabber | IMC 2023 //Illuminating Router Vendor Diversity//: LFP is //"a novel lightweight, accurate, and more complete remote vendor fingerprinting methodology and tool"//, benchmarked as //"at least as good as Nmap while sending orders of magnitude fewer packets"//. It probes hosts to learn what they say; it infers no path and resolves no alias. | **+1** | | ''LFP'' | topology | grabber | IMC 2023 //Illuminating Router Vendor Diversity//: LFP is //"a novel lightweight, accurate, and more complete remote vendor fingerprinting methodology and tool"//, benchmarked as //"at least as good as Nmap while sending orders of magnitude fewer packets"//. It probes hosts to learn what they say; it infers no path and resolves no alias. | **+1** |
  
-Net: **245 → 242**, and one correction in each direction rather than all one way.+Net from the five kind changes: **245 → 242**, and one correction in each direction rather than all one way. A sixth change, found by the review pass and not by this audit, took it to **241**; it is in the review log below and in the suppression section that follows.
  
 === The tuple suppression, and the rule behind it === === The tuple suppression, and the rule behind it ===
Line 102: Line 102:
 Three of those four are **families**, not HAND entries, so the correction has to be per (paper, tool). ''scripts/tool_use_overrides.mjs'' holds it, and is imported by //both// report scripts and by the reconciler, because "the paper did not run this" is a fact about the tuple and not about either page. Three of those four are **families**, not HAND entries, so the correction has to be per (paper, tool). ''scripts/tool_use_overrides.mjs'' holds it, and is imported by //both// report scripts and by the reconciler, because "the paper did not run this" is a fact about the tuple and not about either page.
  
-The rule, written before the entries and recorded here so the next run does not widen it:+The rule, and an honest account of how it changed mid-run:
  
-  * **Suppress when the paper did not run the tool** — it fingerprinted it, or read someone else's output. +  * **(a) Suppress when the paper did not run the tool** — it fingerprinted it, or read someone else's output. //Written before the first entry.// 
-  * **Do not suppress when the paper ran the tool but aimed it somewhere unusual** — its own honeypot, its own telescope, a lab rig. "The target was ours" is a different claim from "we never sent the packet", and relitigating it per paper has no stopping rule.+  * **(b) Suppress when the packets never left the host** onto the public Internet — a closed local loop or a synthetic load generator. //Added on 2026-09-17 after the review pass read Spoki; clause (a) alone would have kept it, and one published figure was wrong by one paper because the rule was incomplete.// 
 +  * **Do not suppress when the paper ran the tool and the packets did cross the Internet**, even if aimed somewhere unusual — its own honeypot, its own hosts, a cloud VM it controls. "The target was ours" is a different claim from "no packet was sent", and relitigating the former per paper has no stopping rule.
  
 **The recall probe for this defect.** A title/slug sweep for ''%%/telescope|darknet|darkspace|network tele|scanning traffic|characteriz\w* .*scanning|honeypot|backscatter|unsolicited traffic|scan traffic/i%%'' returns **20** papers, of which **4** are in ACTIVE. All four were read: **The recall probe for this defect.** A title/slug sweep for ''%%/telescope|darknet|darkspace|network tele|scanning traffic|characteriz\w* .*scanning|honeypot|backscatter|unsolicited traffic|scan traffic/i%%'' returns **20** papers, of which **4** are in ACTIVE. All four were read:
Line 112: Line 113:
 | IMC 2024 //Have you SYN me?// | Pure telescope, three /16s, 2015–2024. Ran nothing. | **Suppressed**, all four tuples. Leaves ACTIVE. | | IMC 2024 //Have you SYN me?// | Pure telescope, three /16s, 2015–2024. Ran nothing. | **Suppressed**, all four tuples. Leaves ACTIVE. |
 | IMC 2015 //Detecting Malicious Activity with DNS Backscatter// | //"We scan several protocols (ICMP, TCP port 22, 23, 80, and UDP port 53, 123) using ZMap"// | Kept. It ran the scan. | | IMC 2015 //Detecting Malicious Activity with DNS Backscatter// | //"We scan several protocols (ICMP, TCP port 22, 23, 80, and UDP port 53, 123) using ZMap"// | Kept. It ran the scan. |
-| USENIX 2022 //Spoki// | Ran ZMap, but to generate SYN load for a scalability test of its own telescope (''purpose'': //"Generating TCP SYN packets for scalability tests"//). | **Kept**, and named here as a borderline: it ran the tool, at its own infrastructure. |+| USENIX 2022 //Spoki// | Ran ZMap, but only inside its own machine: //"A local pair of virtual Ethernet interfaces route packets between the packet source and Spoki. We use ZMap to generate TCP SYN packets, passing the MAC address of the destination interface along with a probing rate and a range of IP addresses to use as a source."// The address range is a synthetic **source** prefix; nothing is probed. | **Kept on 2026-09-17 under clause (a), then SUPPRESSED the same day under clause (b)** after the review pass read the veth sentence this run had not. It was Spoki's only membership tuple, so the paper leaves ACTIVE. |
 | CCS 2020 //HoneyPLC// | Ran Nmap and PLCScan against its own honeypot on AWS, to test camouflage. | **Kept**, same reason. | | CCS 2020 //HoneyPLC// | Ran Nmap and PLCScan against its own honeypot on AWS, to test camouflage. | **Kept**, same reason. |
  
Line 134: Line 135:
   * **It cannot reach the families.** ''ZMap'', ''nmap'', ''Masscan'' and the other 60-odd FAMILIES entries are matched by regex with no per-paper reading at all. The telescope sweep above is the only check that has ever been run on them, and it is a title pattern.   * **It cannot reach the families.** ''ZMap'', ''nmap'', ''Masscan'' and the other 60-odd FAMILIES entries are matched by regex with no per-paper reading at all. The telescope sweep above is the only check that has ever been run on them, and it is a title pattern.
  
-==== C. Guards run on 2026-09-17 ====+==== D. Review log, 2026-09-17 ==== 
 + 
 +Two ''sonnet'' passes, both handed the page text, the report script, its unedited output, the reconciler output and the 173-entry evidence sheet, and both told explicitly that the run's context might not be exhaustive. **No ''fable'' generic pass was run** — the item said not to re-run it — and that remains a gap. 
 + 
 +=== Pass 1: hand-audit judgement (independent re-read of the papers) === 
 + 
 +^ Finding ^ Disposition ^ 
 +| All **five** kind changes (Unicorn, Exitmap, SNMPv3, DMS, LFP): AGREE, each confirmed against ''paper.cols.txt'' | Accepted. It found better evidence than this run had in two places: the PCI paper says //"We check the Mysql port using nc"// and //"We use nc to connect with port 22"// across //"1,203 e-commerce website[s]"//, which settles the ''nc'' borderline far more directly than the inference used here; and the MPLS paper says //"CAIDA's August 2025 ITDK process sent SNMPv3 probes"//, attributing the probing explicitly. Both quotes are now the ones this page relies on. | 
 +| The ''Exitmap''/''exitmap'' asymmetry is right | Accepted. USENIX 2016 //"implemented modules that detect HTML and HTTP tampering by connecting to a decoy server under our control"// and //"using exitmap to send decoy traffic over Sybils"// — it runs the detection modules. CrimeBB only pulls a node list. | 
 +| All **six** borderlines: AGREE | Accepted, and the reasoning recorded above is unchanged. | 
 +| **''Spoki''s ZMap is not a scan at all** — //"A local pair of virtual Ethernet interfaces route packets between the packet source and Spoki. We use ZMap to generate TCP SYN packets, passing the MAC address of the destination interface along with a probing rate and a range of IP addresses to use as a source."// A closed loop on one host; the address range is a synthetic //source// prefix. It was Spoki's only route into ACTIVE. | **Accepted.** Verified independently against ''paper.cols.txt'' before acting. This is the finding that moved ACTIVE from 242 to **241**. It also exposed that the suppression rule was incomplete — clause (a), "did not run it", keeps Spoki — so clause (b), "the packets never left the host", was added and its mid-run addition is recorded in ''tool_use_overrides.mjs'' rather than back-dated. HoneyPLC's Nmap stays: those packets cross the Internet to a real host. | 
 +| ''TorFlow'' is labelled ''p2p-crawler'' where ''perf'' fits better (it times file downloads through circuits) | **Noted, not changed.** Both kinds are non-membership, so no figure moves, and re-kinding on taxonomy taste rather than on a population effect is how a fold drifts. Recorded so the next run can decide. | 
 +| The blanket ''vuln-scanner'' exclusion sits awkwardly on USENIX 2025 //Trust but Verify//, which runs Nuclei against //"104,930 endpoints (IP:port pairs)"// | **Noted, not changed.** That paper is already in ACTIVE via ZMap, so nothing is hidden here — but the exclusion was written for single-test-app scanners and could be dropping an internet-scale vulnerability campaign that happens not to name a family-matched tool. A real recall question this run did not answer. | 
 +| Swept the other ~160 verdicts; read the least-obviously-supported sole-route entries (''BreadCrumb'', ''dMAP'', ''RAT-Scan'', ''WhatWeb'') | Accepted as confirmation. All four hold on direct quotes. **No false positive among the load-bearing memberships.** | 
 + 
 +=== Pass 2: figures vs script === 
 + 
 +^ Finding ^ Disposition ^ 
 +| ''verify_scanning_figures.mjs'' carried ''%%['174 / 56 = 3.1', …]%%'' in ''EXTERNAL_FIGURES'', and **none of ''EXTERNAL_FIGURES'', ''CODE_CONSTANTS'' or ''NOT_FIGURES'' is verified against anything** — they are printed, never asserted. The real operands had moved to 172 and 55; the printed ratio still looked right only because of rounding. | **Accepted, and the class fixed rather than the instance.** The entry is gone; a new **section E, DERIVED ARITHMETIC**, recomputes the ratio from the two ''PUBLISHED_'' tokens in the report and fails on disagreement. The script's header now says in terms that B, C and D are documentation and that anything which can go stale belongs in E. | 
 +| ''check_page_numbers.mjs'' run against **this page** exits 1 on ''174'' — contradicting this page's own sentence that the 2026-09-17 run "added this page to that check" | **Accepted. That sentence was false when written**, and it is the worst kind of error a provenance page can carry: a claim of rigour that had not been performed. The check is now genuinely run against this page, and its result is in the guards table below. | 
 +| ''page_scan.txt'' contradicted itself: "**174** hand verdicts" in one section, "**173**" in another | Accepted and fixed to 173, which is ''Object.keys(HAND).length''. | 
 +| ''page_scan.txt'': //"4 of the **46** papers in the provisional window"// against its own table's ACTIVE=44 two lines above | Accepted and fixed to 44. Neither number guard can see this — 46 occurs legitimately elsewhere in the report — so only reading the prose against its own table catches it. | 
 +| ''namesNS'' in ''report_internet_scanning.mjs'' does not call ''notRun()'', unlike its two siblings. Harmless today because the suppressed paper keeps an unsuppressed ''massDNS'' tuple. | **Accepted and fixed** anyway. A latent inconsistency that would have silently over-counted the moment ''NOT_RUN'' suppressed a paper's only ''network-scanner'' tuple, with no test to catch it. | 
 +| ''reconcile_zmap.mjs'' line 16 comment said ''ACTIVE=245'' — published verbatim as a ''%%<file>%%'' block | Accepted and fixed. No functional effect; a wrong number inside citable published code is still a wrong number. | 
 +| ''report_dns.mjs'' line 86 comment said "the 143" where the published figure is 136 | Accepted and fixed. Internal comment, not published anywhere; pre-dates this run. | 
 +| Section 8's three new guards: tried to construct a passing-but-wrong state, found none | Accepted as confirmation. | 
 +| ''kindsOfName'' / ''foldDnsToolAll'' dedup, and the three RESIDUE rows correctly not treated as defects | Accepted as confirmation. | 
 +| Grepped all nine scripts for hardcoded 245/174/746/231/235 — only the comment-only instances above | Accepted as confirmation. | 
 + 
 +**What the second pass cost to ignore would have been high, and one of its findings is about this page lying about itself.** Both passes are recorded in full because the rejections matter as much as the fixes: two findings (''TorFlow'', the Nuclei/vuln-scanner tension) were deliberately not acted on, and the reasons are above. 
 + 
 +**Not re-reviewed.** The figures pass ran against the 242-state snapshot. Accepting its findings and the Spoki finding together moved ACTIVE to 241 and changed roughly forty cells again, and **that final state has not been through a figures pass**. It has been through ''check_page_numbers.mjs %%--code%%'' on all four pages, every report and verify script, and the reconciler — but a fresh adversarial read of the 241 state is the obvious next thing to do. 
 + 
 +==== E. Guards run on 2026-09-17 ====
  
 ^ Guard ^ Result ^ ^ Guard ^ Result ^
-| ''node scripts/reconcile_zmap.mjs --names'' | exit 0, //"both folds agree and no unacknowledged compound name loses a counted kind"// |+| ''node scripts/reconcile_zmap.mjs %%--names%%'' | exit 0, //"both folds agree and no unacknowledged compound name loses a counted kind"// |
 | ''node scripts/report_internet_scanning.mjs'' | exit 0 | | ''node scripts/report_internet_scanning.mjs'' | exit 0 |
 | ''node scripts/report_dns.mjs'' | exit 0 | | ''node scripts/report_dns.mjs'' | exit 0 |
Line 145: Line 179:
 | the same on ''design:dns'' | no unaccounted figure | | the same on ''design:dns'' | no unaccounted figure |
 | ''node scripts/check_wrap.mjs'' on both content pages and both provenance pages | OK | | ''node scripts/check_wrap.mjs'' on both content pages and both provenance pages | OK |
 +| ''%%node scripts/check_page_numbers.mjs <this page> <report+verify+reconcile>%%'' | run for the first time on 2026-09-17, **after** the review pass showed the earlier claim to be false. It does **not** reach zero on this page and cannot: **36** figures are unaccounted, and they are wiki revision ids, source line numbers, mutation-test constants, regex quantifiers like ''%%{0,120}%%'', numbers quoted from papers (//"104,930 endpoints"//), and historical values this page deliberately records (the 2026-09-10 figures, the mutation-test constants). Every one of the 57 was read by hand on 2026-09-17 and the stale ones fixed; the tool is a **prompt to re-read**, not a pass/fail gate, on a page whose job is to record superseded numbers. Running it with ''%%--code%%'' is worse still — 101 unaccounted, almost all from the five published script sources. |
 +| ''node scripts/verify_scanning_figures.mjs'' **section E** | new: recomputes the page's one derived ratio from the report's own ''PUBLISHED_'' tokens instead of describing it |
 | mutation test: remove ''%%zgrab/zmap%%'' from both ''COMPOUND_SPLIT'' maps | 3 failures, exit 1 | | mutation test: remove ''%%zgrab/zmap%%'' from both ''COMPOUND_SPLIT'' maps | 3 failures, exit 1 |
 | mutation test: misspell a ''NOT_RUN'' key | //"NOT_RUN key names no tools[] entry"//, exit 1 | | mutation test: misspell a ''NOT_RUN'' key | //"NOT_RUN key names no tools[] entry"//, exit 1 |
Line 160: Line 196:
 | corpus | — | **5,859** | | corpus | — | **5,859** |
 | SCAN: ''studyTypes'' contains ''network-scan-or-probe'' | 5,859 | **930** (15.9%) — matches ''OVERVIEW.md''; the report exits 1 if it does not | | SCAN: ''studyTypes'' contains ''network-scan-or-probe'' | 5,859 | **930** (15.9%) — matches ''OVERVIEW.md''; the report exits 1 if it does not |
-| ACTIVE: names an active-scan / grabber / reachability / censorship-probe / IPv6-targeting instrument, used or produced | 5,859 | **242** (4.1%) | +| ACTIVE: names an active-scan / grabber / reachability / censorship-probe / IPv6-targeting instrument, used or produced | 5,859 | **241** (4.1%) | 
-| ACTIVE ∩ SCAN | 930 | **233** (25.1%) | +| ACTIVE ∩ SCAN | 930 | **232** (24.9%) | 
-| ACTIVE outside SCAN | 242 | **9** (3.7%) | +| ACTIVE outside SCAN | 241 | **9** (3.7%) | 
-| ACTIVE if membership were restricted to ''category == "network-scanner"'' | 5,859 | 228 — the any-category rule adds **14** |+| ACTIVE if membership were restricted to ''category == "network-scanner"'' | 5,859 | 227 — the any-category rule adds **14** |
 | SCAN papers naming any ''category == "network-scanner"'' tool | 930 | **396** (42.6%) | | SCAN papers naming any ''category == "network-scanner"'' tool | 930 | **396** (42.6%) |
 | SCAN papers naming **no** such tool | 930 | **534** (57.4%) | | SCAN papers naming **no** such tool | 930 | **534** (57.4%) |
 | SCAN papers naming no instrument the fold recognises at all | 930 | 416 (44.7%) | | SCAN papers naming no instrument the fold recognises at all | 930 | 416 (44.7%) |
-| ZMap ∪ ZGrab ∪ Masscan ∪ nmap, used or produced | 5,859 / 930 | **144** corpus-wide, **140** inside SCAN (the roadmap row said 143) | +| ZMap ∪ ZGrab ∪ Masscan ∪ nmap, used or produced | 5,859 / 930 | **143** corpus-wide, **139** inside SCAN (the roadmap row said 143) | 
-| home-grown scanner (generic "custom" string, or a one-off name the paper produced) | 242 | **45** (18.6%) | +| home-grown scanner (generic "custom" string, or a one-off name the paper produced) | 241 | **45** (18.7%) | 
-| families named by exactly one paper | 242 | **37** | +| families named by exactly one paper | 241 | **37** | 
-| ''classification[].target == "ip-address"'' | 242 / 930 / 5,859 | 76 (31.4%) / 213 (22.9%) / 295 (5.0%) | +| ''classification[].target == "ip-address"'' | 241 / 930 / 5,859 | 75 (31.1%) / 213 (22.9%) / 295 (5.0%) | 
-| ACTIVE posters (''poster-'' slug or ''Poster:'' title) | 242 | 4 (1.7%) | +| ACTIVE posters (''poster-'' slug or ''Poster:'' title) | 241 | 4 (1.7%) | 
-| ACTIVE records of ≤4 pages | 242 | 6 (2.5%) | +| ACTIVE records of ≤4 pages | 241 | 6 (2.5%) | 
-| ACTIVE papers with ≥1 ''detection[].prevalence'' | 242 | 241 (99.6%) |+| ACTIVE papers with ≥1 ''detection[].prevalence'' | 241 | 240 (99.6%) |
  
-**Poster sensitivity.** Dropping the 6 short records moves "vantage location stated" from 55.5% to 56.1% — 0.6 points. The corpus-wide poster caveat (posters have methods compressed out and bias every silence figure upward) applies, but ACTIVE is 2.4% posters against SCAN's 3.7%, so it bites less here than on most pages.+**Poster sensitivity.** Dropping the 6 short records moves "vantage location stated" from 55.6% to 56.2% — 0.6 points. The corpus-wide poster caveat (posters have methods compressed out and bias every silence figure upward) applies, but ACTIVE is 1.7% posters against SCAN's 3.7%, so it bites less here than on most pages.
  
 ===== The fold ===== ===== The fold =====
Line 181: Line 217:
 ''scripts/scan_fold.mjs''. The written boundary is at the top of the file and was fixed **before the first count**. ''scripts/scan_fold.mjs''. The written boundary is at the top of the file and was fixed **before the first count**.
  
-  * **Coverage is a contract, not an aspiration.** Every ''category == "network-scanner"'' used-or-produced string must resolve to a family or to a HAND verdict. **742 tuples, 0 unmapped, 0 stale HAND entries.** The report exits 1 in either direction — an unmapped string //and// a hand verdict that nothing matches, because a shadowed verdict is a lie about what was read.+  * **Coverage is a contract, not an aspiration.** Every ''category == "network-scanner"'' used-or-produced string must resolve to a family or to a HAND verdict. **741 tuples, 0 unmapped, 0 stale HAND entries.** The report exits 1 in either direction — an unmapped string //and// a hand verdict that nothing matches, because a shadowed verdict is a lie about what was read.
   * **Kinds, not one ranking.** Twenty kinds. Five are **membership** (''active-scan'', ''grabber'', ''reachability'', ''censorship-probe'', ''ipv6-targeting''); the rest are reported beside ACTIVE and routed elsewhere (''dataset'', ''topology'', ''dns'', ''vantage-platform'', ''routing'', ''vuln-scanner'', ''passive'', ''local-link'', ''perf'', ''simulation'', ''p2p-crawler'', ''name-enumeration'', ''packet-crafting'', ''registry'', ''lab-protocol-test'', ''host-tool'').   * **Kinds, not one ranking.** Twenty kinds. Five are **membership** (''active-scan'', ''grabber'', ''reachability'', ''censorship-probe'', ''ipv6-targeting''); the rest are reported beside ACTIVE and routed elsewhere (''dataset'', ''topology'', ''dns'', ''vantage-platform'', ''routing'', ''vuln-scanner'', ''passive'', ''local-link'', ''perf'', ''simulation'', ''p2p-crawler'', ''name-enumeration'', ''packet-crafting'', ''registry'', ''lab-protocol-test'', ''host-tool'').
   * **One negative guard.** ''%%/z-?map/i%%'' matches **WizMap**, an embedding-visualisation tool that appears in one paper under ''category: other''. Without the guard it would have entered ACTIVE as a ZMap use. This is the ''\b''-does-not-protect-an-acronym trap in a different costume, and it was found only by printing the strings that matched outside ''network-scanner''.   * **One negative guard.** ''%%/z-?map/i%%'' matches **WizMap**, an embedding-visualisation tool that appears in one paper under ''category: other''. Without the guard it would have entered ACTIVE as a ZMap use. This is the ''\b''-does-not-protect-an-acronym trap in a different costume, and it was found only by printing the strings that matched outside ''network-scanner''.
Line 197: Line 233:
  
 ^ Practice ^ loose ^ first-person ^ hand-read precision ^ published estimate ^ ^ Practice ^ loose ^ first-person ^ hand-read precision ^ published estimate ^
-| own probe rate or rate limit | 125 (51.7%) | 82 (33.9%) | **5/12** | ~34, "about one in seven" | +| own probe rate or rate limit | 124 (51.5%) | 81 (33.6%) | **5/12** | ~34, "about one in seven" | 
-| honours a blocklist / exclusion list | 104 (43.0%) | 89 (36.8%) | **6/12** | ~45, "about one in five" | +| honours a blocklist / exclusion list | 103 (42.7%) | 88 (36.5%) | **6/11** | ~48, "about one in five" | 
-| offers an opt-out | 74 (30.6%) | 70 (28.9%) | **9/10** | ~63, "about one in four" | +| offers an opt-out | 74 (30.7%) | 70 (29.0%) | **9/10** | ~63, "about one in four" | 
-| source-address hygiene | 168 (69.4%) | 113 (46.7%) | **6/10** | ~68, "a little over a quarter" | +| source-address hygiene | 167 (69.3%) | 112 (46.5%) | **6/10** | ~67, "a little over a quarter" | 
-| abuse complaints received or handled | 58 (24.0%) | 45 (18.6%) | not sampled | published as an upper bound only | +| abuse complaints received or handled | 58 (24.1%) | 45 (18.7%) | not sampled | published as an upper bound only | 
-| names an IRB or ethics board | 55 (22.7%) //(loose; there is no first-person version)// | — | not sampled | upper bound, and **not** to be read against ''ethics.reviewOutcome''  (92, 38.0%) | +| names an IRB or ethics board | 55 (22.8%) //(loose; there is no first-person version)// | — | not sampled | upper bound, and **not** to be read against ''ethics.reviewOutcome''  (92, 38.2%) | 
-| cites Durumeric / Partridge-Allman / Menlo / "good Internet citizen" | 173 (71.5%) //(loose)// | — | not sampled | upper bound |+| cites Durumeric / Partridge-Allman / Menlo / "good Internet citizen" | 172 (71.4%) //(loose)// | — | not sampled | upper bound |
  
 <WRAP important> <WRAP important>
-**Two of those cells were wrong on this page until 2026-09-17, and nothing caught them.** The rate row said precision **6/12** and estimate **~42**; the script has said 5/12 and ~35 since the generic review pass of 2026-09-10 flipped the PCspoof verdict from ''own'' to ''other''. The per-paper table below still carried the pre-flip ''own'' as well. The lesson is the one already on [[#Guards run]] in a different form: ''check_page_numbers.mjs'' was run against the //content// page and not against this one, so a provenance page restating a figure in prose had no guard at all. The 2026-09-17 run added this page to that check.+**Two of those cells were wrong on this page until 2026-09-17, and nothing caught them.** The rate row said precision **6/12** and estimate **~42**; the script has said 5/12 and ~35 since the generic review pass of 2026-09-10 flipped the PCspoof verdict from ''own'' to ''other''. The per-paper table below still carried the pre-flip ''own'' as well. The lesson is the one already on [[#Guards run]] in a different form: ''check_page_numbers.mjs'' was run against the //content// page and not against this one, so a provenance page restating a figure in prose had no guard at all. 
 + 
 +**And the first draft of this very paragraph then claimed the fix had been made when it had not.** It said "the 2026-09-17 run added this page to that check"; the review pass ran the check against this page and it exited 1 on a stale ''174''. A provenance page asserting a rigour it has not performed is worse than one that admits the gap, and this is the second instance of the same class on the same page in one sitting. The check is now genuinely run against this page and its result is in the guards table.
 </WRAP> </WRAP>
  
Line 212: Line 250:
  
 ^ Guard ^ What it catches ^ Mutation used to prove it fires ^ ^ Guard ^ What it catches ^ Mutation used to prove it fires ^
-| every pinned paper is still a hit | the probe changed, or the paper left ACTIVE | renamed one pinned key to ''CCS/2018/NOT-A-REAL-PAPER'' → //"pinned sample paper is no longer a hit"// |+| every pinned paper is still a hit | the probe changed, or the paper left ACTIVE | renamed one pinned key to ''CCS/2018/NOT-A-REAL-PAPER'' → //"pinned sample paper is no longer a hit"//. It then fired **for real** the same day: suppressing Spoki's ZMap tuple took that paper out of ACTIVE, and the blocklist sample had it pinned. Its verdict was dropped with the reason recorded inline, so that sample is **11**, not 12, and its precision is 6/11. |
 | hit-list length within 15% of the length at draw time | a frozen sample quietly stops being representative as the list grows | set the source-address pin to 250 against a real 113 → //"hit list moved 54.8% since the sample was drawn"// | | hit-list length within 15% of the length at draw time | a frozen sample quietly stops being representative as the list grows | set the source-address pin to 250 against a real 113 → //"hit list moved 54.8% since the sample was drawn"// |
 | pinned papers span at least half the sorted hit list | a sample clustered in one corner is not a sample | cut the opt-out map to its first three keys → //"pinned sample spans only 12 of 70 sorted hits"// | | pinned papers span at least half the sorted hit list | a sample clustered in one corner is not a sample | cut the opt-out map to its first three keys → //"pinned sample spans only 12 of 70 sorted hits"// |
Line 289: Line 327:
  
   * The embedded block is **byte-identical** to ''pages/scan_budget.py''.   * The embedded block is **byte-identical** to ''pages/scan_budget.py''.
-  * Downloading it back off the rendered page (''/_export/code/programming:internet_scanning?codeblock=3'') and diffing gives **one** difference, a stripped trailing newline. The downloaded copy runs its own ''--self-test'': **9 checks, OK**.+  * Downloading it back off the rendered page (''/_export/code/programming:internet_scanning?codeblock=3'') and diffing gives **one** difference, a stripped trailing newline. The downloaded copy runs its own ''%%--self-test%%'': **9 checks, OK**.
   * The ''%%<code>%%'' block beside it is the **whole** output of a real run, compared line-by-line for exact equality — not a containment check, which passes on a truncated block.   * The ''%%<code>%%'' block beside it is the **whole** output of a real run, compared line-by-line for exact equality — not a containment check, which passes on a truncated block.
   * The self-test has a **mutation guard**: replacing ''collapse_addresses()'' with a bare ''sum'' makes the overlapping-CIDR case return 33,554,432 instead of 16,777,216 and check 3 fails. Check 4 exists so that "collapse does nothing at all" cannot also pass — a disjoint pair must still add up.   * The self-test has a **mutation guard**: replacing ''collapse_addresses()'' with a bare ''sum'' makes the overlapping-CIDR case return 33,554,432 instead of 16,777,216 and check 3 fails. Check 4 exists so that "collapse does nothing at all" cannot also pass — a disjoint pair must still add up.
Line 316: Line 354:
 ===== What could not be established ===== ===== What could not be established =====
  
-  * **How many scan papers actually rate-limited, honoured an exclusion list, or offered an opt-out.** **Still open after 2026-09-17.** Only estimates, from a regex probe with a hand-read precision sample of 10–12. Closing this needs the same treatment ''harm_fold.mjs'' got on [[practices:ethics]]: a loose candidate sweep plus a per-paper verdict over the whole hit list. The current hit lists are **82 / 89 / 70 / 113** papers — **354 reads**, not the ~90 per practice the original note estimated — and the report now says so in its own output. What the 2026-09-17 run did do is make the existing sample survive a population change instead of dissolving into it; the four estimates are still estimates.+  * **How many scan papers actually rate-limited, honoured an exclusion list, or offered an opt-out.** **Still open after 2026-09-17.** Only estimates, from a regex probe with a hand-read precision sample of 10–12. Closing this needs the same treatment ''harm_fold.mjs'' got on [[practices:ethics]]: a loose candidate sweep plus a per-paper verdict over the whole hit list. The current hit lists are **81 / 88 / 70 / 112** papers — **351 reads**, not the ~90 per practice the original note estimated — and the report now says so in its own output. What the 2026-09-17 run did do is make the existing sample survive a population change instead of dissolving into it; the four estimates are still estimates.
   * **Whether the 534 SCAN papers that name no ''network-scanner'' tool scanned without saying with what, or queried a dataset.** The schema cannot separate those two, and neither can a name fold. A full-text pass over a sample would.   * **Whether the 534 SCAN papers that name no ''network-scanner'' tool scanned without saying with what, or queried a dataset.** The schema cannot separate those two, and neither can a name fold. A full-text pass over a sample would.
   * **The recall of ACTIVE outside ''category == "network-scanner"''.** One-off scanner names filed under ''other'' are not hand-read — that would be the whole 16,737-name tool vocabulary. ACTIVE is a floor and the page says so.   * **The recall of ACTIVE outside ''category == "network-scanner"''.** One-off scanner names filed under ''other'' are not hand-read — that would be the whole 16,737-name tool vocabulary. ACTIVE is a floor and the page says so.
Line 332: Line 370:
 | ''node scripts/check_wrap.mjs'' on the content page, this page and all four edited pages | OK | | ''node scripts/check_wrap.mjs'' on the content page, this page and all four edited pages | OK |
 | ''node scripts/check_tables.mjs'' on the same | "every table has one width" | | ''node scripts/check_tables.mjs'' on the same | "every table has one width" |
-| ''python3 scripts/bib_dedup_scan.py --bib <fresh export + 8 new>'' | 0 definite duplicate pairs; the one candidate touching a new key is ''durumeric2013_zmap''/''williams2024_6sense'', different papers |+| ''python3 scripts/bib_dedup_scan.py %%--bib%% <fresh export + 8 new>'' | 0 definite duplicate pairs; the one candidate touching a new key is ''durumeric2013_zmap''/''williams2024_6sense'', different papers |
 | rendered DOM after save | **37** source ''%%{[key]}%%'' markers → **74** ''bibtex_citekey'' spans (the plugin emits two per marker) → **15** ''%%<dt>%%'' references for 15 distinct keys; **0** "could not be found" warnings; **0** red links | | rendered DOM after save | **37** source ''%%{[key]}%%'' markers → **74** ''bibtex_citekey'' spans (the plugin emits two per marker) → **15** ''%%<dt>%%'' references for 15 distinct keys; **0** "could not be found" warnings; **0** red links |
 | red links in the rendered DOM | 3, all of them to this page, before it existed | | red links in the rendered DOM | 3, all of them to this page, before it existed |
Line 360: Line 398:
 | A4 | The rate table had no independent check. | **Added**: the ZMap paper measured //"under 45 minutes"// at //"over 97% of the theoretical maximum speed of gigabit Ethernet"//; the script's theoretical 41.5 min ÷ 0.97 = 42.8. Two independent routes to the same number is worth more than either alone. | | A4 | The rate table had no independent check. | **Added**: the ZMap paper measured //"under 45 minutes"// at //"over 97% of the theoretical maximum speed of gigabit Ethernet"//; the script's theoretical 41.5 min ÷ 0.97 = 42.8. Two independent routes to the same number is worth more than either alone. |
  
-==== Pass 1 — figures vs script (''sonnet'') ====+==== Pass 1 — figures vs script (sonnet) ====
  
 Re-ran all four scripts, confirmed they reproduce the committed outputs Re-ran all four scripts, confirmed they reproduce the committed outputs
Line 370: Line 408:
  
 ^ # ^ Finding ^ Disposition ^ ^ # ^ Finding ^ Disposition ^
-| P1.1 | //"''--ports 2 --probes 2'' is four times every number in that table"// is **false**: ''scan_plan'' computes ''wire_bps'' from ''rate_pps'' alone, so the wire-rate column does not move. Verified by calling the function both ways — seconds ratio 4.0, ''wire_mbps'' ratio 1.0. | **Accepted and fixed.** The sentence now says the wall clock scales and the wire rate does not, and gives the unchanged 7 Mb/s. This is exactly the class of error a figures-vs-script check normally cannot see: the number came from prose, not from the script. | +| P1.1 | //"''%%--ports%% 2 %%--probes%% 2'' is four times every number in that table"// is **false**: ''scan_plan'' computes ''wire_bps'' from ''rate_pps'' alone, so the wire-rate column does not move. Verified by calling the function both ways — seconds ratio 4.0, ''wire_mbps'' ratio 1.0. | **Accepted and fixed.** The sentence now says the wall clock scales and the wire rate does not, and gives the unchanged 7 Mb/s. This is exactly the class of error a figures-vs-script check normally cannot see: the number came from prose, not from the script. | 
-| P1.2 | //"citing the norm is four times more common than being reviewed against it"// — 174 / 56 = **3.1**. | **Accepted and fixed** to "about three times", with the division shown. |+| P1.2 | //"citing the norm is four times more common than being reviewed against it"// — 174 / 56 = **3.1** //(the operands as they stood on 2026-09-10; they are 172 / 55 = 3.1 after the 2026-09-17 audit, and the ratio is now recomputed from the report by section E of verify_scanning_figures.mjs rather than described)//. | **Accepted and fixed** to "about three times", with the division shown. |
 | P1.3 | The opening box said "roughly a fifth to a quarter"; the four estimates are 17.1 / 18.4 / 25.3 / 27.8%, so the band is wrong at both ends. | **Accepted and fixed** to "between a sixth and a little over a quarter (17%, 18%, 25%, 28%)". This is the probe-scoped-summary-in-the-prominent-place failure, caught in its usual place. | | P1.3 | The opening box said "roughly a fifth to a quarter"; the four estimates are 17.1 / 18.4 / 25.3 / 27.8%, so the band is wrong at both ends. | **Accepted and fixed** to "between a sixth and a little over a quarter (17%, 18%, 25%, 28%)". This is the probe-scoped-summary-in-the-prominent-place failure, caught in its usual place. |
-| P1.4 | ''pages/scan_budget.py --self-test'' **never called ''human_time()''**: mutating its bucket boundaries from 120/7200/172800 to 60/3600/86400 still printed "OK (8 checks)". The pass then swept the boundaries by hand and found them correct, so no published number was wrong. | **Accepted and fixed.** Check 9 added: six ±0.01 s boundary cases plus three exact conversions. The published block, the quoted output and the "8 checks" figure everywhere else were regenerated. A self-test that claims coverage it does not have is worse than none. |+| P1.4 | ''pages/scan_budget.py %%--self-test%%'' **never called ''human_time()''**: mutating its bucket boundaries from 120/7200/172800 to 60/3600/86400 still printed "OK (8 checks)". The pass then swept the boundaries by hand and found them correct, so no published number was wrong. | **Accepted and fixed.** Check 9 added: six ±0.01 s boundary cases plus three exact conversions. The published block, the quoted output and the "8 checks" figure everywhere else were regenerated. A self-test that claims coverage it does not have is worse than none. |
  
-==== Pass 2 — citations and quotes (''sonnet'') ====+==== Pass 2 — citations and quotes (sonnet) ====
  
 All 15 citekeys resolve exactly once in a fresh export; All 15 citekeys resolve exactly once in a fresh export;
Line 386: Line 424:
 | P2.1 | //"Beverly et al. …, on a **six-month** IPv6 topology campaign"//. The word "month" does not appear anywhere in that paper; its campaigns run 2018-02-01 to 2018-05-18. The **six months belonged to Gasser et al.**, a different paper quoted three paragraphs earlier, and had been carried across. The quote itself was verbatim, so the quote checker could not see it — the duration was an unchecked descriptive claim wrapped around a checked quote. | **Accepted and fixed** to "between February and May 2018". | | P2.1 | //"Beverly et al. …, on a **six-month** IPv6 topology campaign"//. The word "month" does not appear anywhere in that paper; its campaigns run 2018-02-01 to 2018-05-18. The **six months belonged to Gasser et al.**, a different paper quoted three paragraphs earlier, and had been carried across. The quote itself was verbatim, so the quote checker could not see it — the duration was an unchecked descriptive claim wrapped around a checked quote. | **Accepted and fixed** to "between February and May 2018". |
  
-==== Pass 3 — external currency (''sonnet'') ====+==== Pass 3 — external currency (sonnet) ====
  
 Independently re-fetched and confirmed: both ZMap man pages (tag and ''main'', Independently re-fetched and confirmed: both ZMap man pages (tag and ''main'',
Line 404: Line 442:
 | P3.3 | ''www.zoomeye.org'' answers HTTP 521 with an ''X-Via-JSL'' header (Knownsec's own bot challenge), while ''zoomeye.ai'' answers 200. | **Noted, no change.** The page names ZoomEye in a list of query targets and makes no uptime or URL claim about it. Recorded here so a later tightening of the "still operating" check does not read the 521 as a shutdown. | | P3.3 | ''www.zoomeye.org'' answers HTTP 521 with an ''X-Via-JSL'' header (Knownsec's own bot challenge), while ''zoomeye.ai'' answers 200. | **Noted, no change.** The page names ZoomEye in a list of query targets and makes no uptime or URL claim about it. Recorded here so a later tightening of the "still operating" check does not read the 521 as a shutdown. |
  
-==== Pass 4 — generic (''fable'') ====+==== Pass 4 — generic (fable) ====
  
 **It returned after the "did not return" note above had already been written and **It returned after the "did not return" note above had already been written and
Line 458: Line 496:
 0. FOLD COVERAGE — every category=network-scanner name must be decided 0. FOLD COVERAGE — every category=network-scanner name must be decided
 ============================================================================== ==============================================================================
-category='network-scanner' used/produced tuples: 742+category='network-scanner' used/produced tuples: 741
 unmapped strings: 0 unmapped strings: 0
 HAND entries: 173, matched: 173, stale: 0 HAND entries: 173, matched: 173, stale: 0
Line 478: Line 516:
 corpus (7 venues, 2010–2026)                                5859    100% corpus (7 venues, 2010–2026)                                5859    100%
 SCAN — studyTypes 'network-scan-or-probe'                   930     15.9% SCAN — studyTypes 'network-scan-or-probe'                   930     15.9%
-ACTIVE — names an active-scan instrument (page population)  242     4.1% of corpus +ACTIVE — names an active-scan instrument (page population)  241     4.1% of corpus 
-  … of those, inside SCAN                                   233     25.1% of SCAN+  … of those, inside SCAN                                   232     24.9% of SCAN
   … of those, outside SCAN                                  9       3.7% of ACTIVE   … of those, outside SCAN                                  9       3.7% of ACTIVE
 SCAN papers naming ANY category='network-scanner' tool      396     42.6% SCAN papers naming ANY category='network-scanner' tool      396     42.6%
Line 485: Line 523:
 PUBLISHED_CORPUS 5859 PUBLISHED_CORPUS 5859
 PUBLISHED_SCAN 930 PUBLISHED_SCAN 930
-PUBLISHED_ACTIVE 242 +PUBLISHED_ACTIVE 241 
-PUBLISHED_ACTIVE_IN_SCAN 233 +PUBLISHED_ACTIVE_IN_SCAN 232 
-PUBLISHED_ACTIVE_IN_SCAN_PCT 25.1%+PUBLISHED_ACTIVE_IN_SCAN_PCT 24.9%
 PUBLISHED_ACTIVE_OUTSIDE 9 PUBLISHED_ACTIVE_OUTSIDE 9
 PUBLISHED_NAMES_NS 396 PUBLISHED_NAMES_NS 396
 PUBLISHED_NO_NS 534 57.4% PUBLISHED_NO_NS 534 57.4%
  
-category-restricted membership would give 228; the any-category rule adds 14 +category-restricted membership would give 227; the any-category rule adds 14 
-PUBLISHED_NS_ONLY 228+PUBLISHED_NS_ONLY 227
   +CCS/2015/iris-vetting-private-api-abuse-in-ios-applications  Iris[program-analysis]   +CCS/2015/iris-vetting-private-api-abuse-in-ios-applications  Iris[program-analysis]
   +IMC/2016/entropy-ip-uncovering-structure-in-ipv6-addresses  Entropy/IP[other]   +IMC/2016/entropy-ip-uncovering-structure-in-ipv6-addresses  Entropy/IP[other]
Line 514: Line 552:
 kind               membership?  Papers  Share of 930  routed to kind               membership?  Papers  Share of 930  routed to
 -----------------  -----------  ------  ------------  ---------------------------- -----------------  -----------  ------  ------------  ----------------------------
-active-scan        YES          178     19.1%+active-scan        YES          177     19.0%
 dataset                         97      10.4%         design:existing_datasets dataset                         97      10.4%         design:existing_datasets
 topology                        94      10.1%         design:ip_classification topology                        94      10.1%         design:ip_classification
Line 543: Line 581:
 Family                kind              Papers  Share of ACTIVE  distinct spellings Family                kind              Papers  Share of ACTIVE  distinct spellings
 --------------------  ----------------  ------  ---------------  ------------------ --------------------  ----------------  ------  ---------------  ------------------
-ZMap                  active-scan       95      39.3%            10 +ZMap                  active-scan       94      39.0%            10 
-nmap                  active-scan       45      18.6%            10 +nmap                  active-scan       45      18.7%            10 
-ZGrab                 grabber           32      13.2%            7 +ZGrab                 grabber           32      13.3%            7 
-custom scanner        active-scan       25      10.3%            21 +custom scanner        active-scan       25      10.4%            21 
-ping                  reachability      18      7.4%             7+ping                  reachability      18      7.5%             7
 XMap                  active-scan       16      6.6%             3 XMap                  active-scan       16      6.6%             3
-TLS banner grabbers   grabber           11      4.5%             8+TLS banner grabbers   grabber           11      4.6%             8
 OONI                  censorship-probe  7       2.9%             3 OONI                  censorship-probe  7       2.9%             3
 Geneva                censorship-probe  6       2.5%             1 Geneva                censorship-probe  6       2.5%             1
Line 572: Line 610:
 families named by exactly one paper: 37 — 6Graph, 6Sense, 6Tree, AmpMap, BreadCrumb, CnCHunter, dMAP (DPI Mapper), EAST, ERIS, exitmap, forwarders-based scanner, gateway checker, gQUIC-module, ICMP_Sonar, ike-scan, IRBlock, IRLscanner, JARM, LanDscAPe, LFP, Lumscan, Mint, modified ntpdedup, Monocle, nc, Netcat, node probing program, onesixtyone, onion-grab, OSAVRoute, PLCScan, Python script, quicgrabber, RAT-Scan, smbmap, TMC, WhatWeb families named by exactly one paper: 37 — 6Graph, 6Sense, 6Tree, AmpMap, BreadCrumb, CnCHunter, dMAP (DPI Mapper), EAST, ERIS, exitmap, forwarders-based scanner, gateway checker, gQUIC-module, ICMP_Sonar, ike-scan, IRBlock, IRLscanner, JARM, LanDscAPe, LFP, Lumscan, Mint, modified ntpdedup, Monocle, nc, Netcat, node probing program, onesixtyone, onion-grab, OSAVRoute, PLCScan, Python script, quicgrabber, RAT-Scan, smbmap, TMC, WhatWeb
 PUBLISHED_ONEOFF_FAMILIES 37 PUBLISHED_ONEOFF_FAMILIES 37
-PUBLISHED_FAM_ZMAP 95+PUBLISHED_FAM_ZMAP 94
 PUBLISHED_FAM_NMAP 45 PUBLISHED_FAM_NMAP 45
 PUBLISHED_FAM_ZGRAB 32 PUBLISHED_FAM_ZGRAB 32
Line 582: Line 620:
  
  
-ZMap|ZGrab|Masscan|nmap, used or produced: 144 corpus-wide, 140 inside SCAN (the roadmap row said 143) +ZMap|ZGrab|Masscan|nmap, used or produced: 143 corpus-wide, 139 inside SCAN (the roadmap row said 143) 
-PUBLISHED_CORE_FOUR_ALL 144 +PUBLISHED_CORE_FOUR_ALL 143 
-PUBLISHED_CORE_FOUR_SCAN 140+PUBLISHED_CORE_FOUR_SCAN 139
 ZMap spellings: TCP Options module for ZMap | ZGrab/ZMap | ZMap | ZMap-based script | ZMap6 | ZMapv6 | Zmap | zmap | zmap2 | zmap6 ZMap spellings: TCP Options module for ZMap | ZGrab/ZMap | ZMap | ZMap-based script | ZMap6 | ZMapv6 | Zmap | zmap | zmap2 | zmap6
 PUBLISHED_ZMAP_SPELLINGS 10 PUBLISHED_ZMAP_SPELLINGS 10
-ACTIVE papers whose scanner is home-grown: 45 (18.6%)+ACTIVE papers whose scanner is home-grown: 45 (18.7%)
   = generic 'custom scanner' string:                    25   = generic 'custom scanner' string:                    25
   + a one-paper name the paper itself PRODUCED:         20   + a one-paper name the paper itself PRODUCED:         20
   - overlap:                                            0   - overlap:                                            0
   (the other 17 one-paper families are third-party tools only this corpus's one paper used)   (the other 17 one-paper families are third-party tools only this corpus's one paper used)
-PUBLISHED_HOMEGROWN 45 18.6%+PUBLISHED_HOMEGROWN 45 18.7%
 PUBLISHED_HOMEGROWN_CUSTOM 25 PUBLISHED_HOMEGROWN_CUSTOM 25
 PUBLISHED_HOMEGROWN_PRODUCED 20 PUBLISHED_HOMEGROWN_PRODUCED 20
Line 605: Line 643:
 2014–2017   45             27 (60.0%)  4 (8.9%)    8 (17.8%)   0 (0.0%)    1 (2.2%)  7 (15.6%)       2 (4.4%) 2014–2017   45             27 (60.0%)  4 (8.9%)    8 (17.8%)   0 (0.0%)    1 (2.2%)  7 (15.6%)       2 (4.4%)
 2018–2021   55             21 (38.2%)  9 (16.4%)   15 (27.3%)  0 (0.0%)    0 (0.0%)  5 (9.1%)        3 (5.5%) 2018–2021   55             21 (38.2%)  9 (16.4%)   15 (27.3%)  0 (0.0%)    0 (0.0%)  5 (9.1%)        3 (5.5%)
-2022–2024   86             25 (29.1%)  9 (10.5%)   13 (15.1%)  10 (11.6%)  3 (3.5%)  6 (7.0%)        9 (10.5%)+2022–2024   85             24 (28.2%)  9 (10.6%)   13 (15.3%)  10 (11.8%)  3 (3.5%)  6 (7.1%)        9 (10.6%)
 2025–2026*  44             21 (47.7%)  10 (22.7%)  4 (9.1%)    6 (13.6%)   0 (0.0%)  4 (9.1%)        1 (2.3%) 2025–2026*  44             21 (47.7%)  10 (22.7%)  4 (9.1%)    6 (13.6%)   0 (0.0%)  4 (9.1%)        1 (2.3%)
  
Line 623: Line 661:
 2020  404     71    12      7 2020  404     71    12      7
 2021  379     65    14      5 2021  379     65    14      5
-2022  546     70    25      10+2022  546     70    24      9
 2023  719     79    30      7 2023  719     79    30      7
 2024  690     96    31      8 2024  690     96    31      8
Line 641: Line 679:
 NDSS     701     117   16.7%                34      4.9% NDSS     701     117   16.7%                34      4.9%
 PETS     510     49    9.6%                 8       1.6% PETS     510     49    9.6%                 8       1.6%
-USENIX   1410    199   14.1%                69      4.9%+USENIX   1410    199   14.1%                68      4.8%
 WWW      843     50    5.9%                 11      1.3% WWW      843     50    5.9%                 11      1.3%
  
Line 647: Line 685:
 6. WHAT A SCAN PAPER REPORTS — schema fields, denominator ACTIVE and SCAN 6. WHAT A SCAN PAPER REPORTS — schema fields, denominator ACTIVE and SCAN
 ============================================================================== ==============================================================================
-Field                           ACTIVE (242)  share  SCAN (930)  share+Field                           ACTIVE (241)  share  SCAN (930)  share
 ------------------------------  ------------  -----  ----------  ----- ------------------------------  ------------  -----  ----------  -----
-vantage location                135           55.8%  487         52.4% +vantage location                134           55.6%  487         52.4% 
-vantage infrastructure          165           68.2%  612         65.8% +vantage infrastructure          164           68.0%  612         65.8% 
-any used/produced tool version  116           47.9%  401         43.1%+any used/produced tool version  115           47.7%  401         43.1%
 version of the SCANNER itself   20            8.3%   20          2.2% version of the SCANNER itself   20            8.3%   20          2.2%
-own artifact URL                145           59.9%  506         54.4% +own artifact URL                144           59.8%  506         54.4% 
-ethics review outcome           92            38.0%  290         31.2% +ethics review outcome           92            38.2%  290         31.2% 
-notified affected parties       184           76.0%  560         60.2% +notified affected parties       184           76.3%  560         60.2% 
-harm mitigation described       209           86.4%  700         75.3% +harm mitigation described       208           86.3%  700         75.3% 
-robots.txt                      11            4.5%   22          2.4% +robots.txt                      11            4.6%   22          2.4% 
-temporal span start             193           79.8%  656         70.5%+temporal span start             192           79.7%  656         70.5%
  
 ACTIVE papers with NO ethics record at all: 7 (2.9%) — not counted as stated, not counted as a sentinel ACTIVE papers with NO ethics record at all: 7 (2.9%) — not counted as stated, not counted as a sentinel
Line 664: Line 702:
 PUBLISHED_NO_ETHICS_RECORD 7 2.9% PUBLISHED_NO_ETHICS_RECORD 7 2.9%
 PUBLISHED_NO_ARTIFACT_RECORD 3 1.2% PUBLISHED_NO_ARTIFACT_RECORD 3 1.2%
-PUBLISHED_REPORT_VANTAGE_LOCATION 135 55.8% | SCAN 487 52.4% +PUBLISHED_REPORT_VANTAGE_LOCATION 134 55.6% | SCAN 487 52.4% 
-PUBLISHED_REPORT_VANTAGE_INFRASTRUCTURE 165 68.2% | SCAN 612 65.8% +PUBLISHED_REPORT_VANTAGE_INFRASTRUCTURE 164 68.0% | SCAN 612 65.8% 
-PUBLISHED_REPORT_ANY_USED_PRODUCED_TOOL_VERSION 116 47.9% | SCAN 401 43.1%+PUBLISHED_REPORT_ANY_USED_PRODUCED_TOOL_VERSION 115 47.7% | SCAN 401 43.1%
 PUBLISHED_REPORT_VERSION_OF_THE_SCANNER_ITSELF 20 8.3% | SCAN 20 2.2% PUBLISHED_REPORT_VERSION_OF_THE_SCANNER_ITSELF 20 8.3% | SCAN 20 2.2%
-PUBLISHED_REPORT_OWN_ARTIFACT_URL 145 59.9% | SCAN 506 54.4% +PUBLISHED_REPORT_OWN_ARTIFACT_URL 144 59.8% | SCAN 506 54.4% 
-PUBLISHED_REPORT_ETHICS_REVIEW_OUTCOME 92 38.0% | SCAN 290 31.2% +PUBLISHED_REPORT_ETHICS_REVIEW_OUTCOME 92 38.2% | SCAN 290 31.2% 
-PUBLISHED_REPORT_NOTIFIED_AFFECTED_PARTIES 184 76.0% | SCAN 560 60.2% +PUBLISHED_REPORT_NOTIFIED_AFFECTED_PARTIES 184 76.3% | SCAN 560 60.2% 
-PUBLISHED_REPORT_HARM_MITIGATION_DESCRIBED 209 86.4% | SCAN 700 75.3% +PUBLISHED_REPORT_HARM_MITIGATION_DESCRIBED 208 86.3% | SCAN 700 75.3% 
-PUBLISHED_REPORT_ROBOTS_TXT 11 4.5% | SCAN 22 2.4% +PUBLISHED_REPORT_ROBOTS_TXT 11 4.6% | SCAN 22 2.4% 
-PUBLISHED_REPORT_TEMPORAL_SPAN_START 193 79.8% | SCAN 656 70.5%+PUBLISHED_REPORT_TEMPORAL_SPAN_START 192 79.7% | SCAN 656 70.5%
  
 ============================================================================== ==============================================================================
 7. FULL-TEXT PROBES over ACTIVE — a loose upper bound and a tight estimate 7. FULL-TEXT PROBES over ACTIVE — a loose upper bound and a tight estimate
 ============================================================================== ==============================================================================
-PUBLISHED_PROBE_STATES_ITS_OWN_PROBE_RATE_OR_RATE_LIMIT_LOOSE 125 51.7% +PUBLISHED_PROBE_STATES_ITS_OWN_PROBE_RATE_OR_RATE_LIMIT_LOOSE 124 51.5% 
-PUBLISHED_PROBE_STATES_ITS_OWN_PROBE_RATE_OR_RATE_LIMIT_TIGHT 82 33.9% +PUBLISHED_PROBE_STATES_ITS_OWN_PROBE_RATE_OR_RATE_LIMIT_TIGHT 81 33.6% 
-PUBLISHED_PROBE_HONOURS_A_BLOCKLIST_EXCLUSION_LIST_LOOSE 104 43.0% +PUBLISHED_PROBE_HONOURS_A_BLOCKLIST_EXCLUSION_LIST_LOOSE 103 42.7% 
-PUBLISHED_PROBE_HONOURS_A_BLOCKLIST_EXCLUSION_LIST_TIGHT 89 36.8% +PUBLISHED_PROBE_HONOURS_A_BLOCKLIST_EXCLUSION_LIST_TIGHT 88 36.5% 
-PUBLISHED_PROBE_OFFERS_AN_OPT_OUT_LOOSE 74 30.6% +PUBLISHED_PROBE_OFFERS_AN_OPT_OUT_LOOSE 74 30.7% 
-PUBLISHED_PROBE_OFFERS_AN_OPT_OUT_TIGHT 70 28.9% +PUBLISHED_PROBE_OFFERS_AN_OPT_OUT_TIGHT 70 29.0% 
-PUBLISHED_PROBE_SOURCE_ADDRESS_HYGIENE_DEDICATED_IPS_RDNS_PTR_WHOIS_WEB_PAGE__LOOSE 168 69.4% +PUBLISHED_PROBE_SOURCE_ADDRESS_HYGIENE_DEDICATED_IPS_RDNS_PTR_WHOIS_WEB_PAGE__LOOSE 167 69.3% 
-PUBLISHED_PROBE_SOURCE_ADDRESS_HYGIENE_DEDICATED_IPS_RDNS_PTR_WHOIS_WEB_PAGE__TIGHT 113 46.7% +PUBLISHED_PROBE_SOURCE_ADDRESS_HYGIENE_DEDICATED_IPS_RDNS_PTR_WHOIS_WEB_PAGE__TIGHT 112 46.5% 
-PUBLISHED_PROBE_ABUSE_COMPLAINTS_RECEIVED_OR_HANDLED_LOOSE 58 24.0% +PUBLISHED_PROBE_ABUSE_COMPLAINTS_RECEIVED_OR_HANDLED_LOOSE 58 24.1% 
-PUBLISHED_PROBE_ABUSE_COMPLAINTS_RECEIVED_OR_HANDLED_TIGHT 45 18.6%+PUBLISHED_PROBE_ABUSE_COMPLAINTS_RECEIVED_OR_HANDLED_TIGHT 45 18.7%
 Practice                                                           loose probe (upper bound)  first-person probe Practice                                                           loose probe (upper bound)  first-person probe
 -----------------------------------------------------------------  -------------------------  ------------------ -----------------------------------------------------------------  -------------------------  ------------------
-states its own probe rate or rate limit                            125 (51.7%)                82 (33.9%) +states its own probe rate or rate limit                            124 (51.5%)                81 (33.6%) 
-honours a blocklist / exclusion list                               104 (43.0%)                89 (36.8%) +honours a blocklist / exclusion list                               103 (42.7%)                88 (36.5%) 
-offers an opt-out                                                  74 (30.6%)                 70 (28.9%) +offers an opt-out                                                  74 (30.7%)                 70 (29.0%) 
-source-address hygiene (dedicated IPs, rDNS/PTR, WHOIS, web page)  168 (69.4%)                113 (46.7%) +source-address hygiene (dedicated IPs, rDNS/PTR, WHOIS, web page)  167 (69.3%)                112 (46.5%) 
-abuse complaints received or handled                               58 (24.0%)                 45 (18.6%)+abuse complaints received or handled                               58 (24.1%)                 45 (18.7%)
  
 Neither column is a population. The loose regex fires on any sentence in Neither column is a population. The loose regex fires on any sentence in
Line 703: Line 741:
 the measured precision. the measured precision.
  
-ACTIVE papers naming an IRB / ethics board: 55 (22.7%) [loose, no precision measured] +ACTIVE papers naming an IRB / ethics board: 55 (22.8%) [loose, no precision measured] 
-ACTIVE papers citing Durumeric / Partridge-Allman / Menlo / "good Internet citizen": 173 (71.5%) [loose] +ACTIVE papers citing Durumeric / Partridge-Allman / Menlo / "good Internet citizen": 172 (71.4%) [loose] 
-PUBLISHED_IRB 55 22.7% +PUBLISHED_IRB 55 22.8% 
-PUBLISHED_GOODPRACTICE 173 71.5%+PUBLISHED_GOODPRACTICE 172 71.4%
  
 ============================================================================== ==============================================================================
Line 712: Line 750:
 ============================================================================== ==============================================================================
  
---- own probe rate: 82 first-person hits of 242 ACTIVE; pinned sample of 12+--- own probe rate: 81 first-person hits of 241 ACTIVE; pinned sample of 12
     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 84 long     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 84 long
     other    CCS/2015/a-search-engine-backed-by-internet-wide-scanning     other    CCS/2015/a-search-engine-backed-by-internet-wide-scanning
Line 726: Line 764:
     own      USENIX/2024/6sense-internet-wide-ipv6-scanning-and-its-security-applications     own      USENIX/2024/6sense-internet-wide-ipv6-scanning-and-its-security-applications
     own      USENIX/2025/exposing-and-circumventing-sni-based-quic-censorship-of-the-great-firewall-of-ch     own      USENIX/2025/exposing-and-circumventing-sni-based-quic-censorship-of-the-great-firewall-of-ch
-    hit list 82 now vs 84 at draw time — drift 2.4% +    hit list 81 now vs 84 at draw time — drift 3.6% 
-    sample positions in the sorted hit list: 0, 7, 14, 21, 28, 34, 41, 48, 55, 62, 69, 76 (spread 76 of 82) +    sample positions in the sorted hit list: 0, 7, 14, 21, 28, 34, 41, 48, 55, 62, 68, 75 (spread 75 of 81) 
-    precision 5/12; 82 x 5/12 = about 34 papers (14.0% of ACTIVE) +    precision 5/12; 81 x 5/12 = about 34 papers (14.1% of ACTIVE) 
-PUBLISHED_PRECISION_OWN_PROBE_RATE 5/12 -> ~34 14.0%+PUBLISHED_PRECISION_OWN_PROBE_RATE 5/12 -> ~34 14.1%
  
---- own blocklist / exclusion: 89 first-person hits of 242 ACTIVE; pinned sample of 12+--- own blocklist / exclusion: 88 first-person hits of 241 ACTIVE; pinned sample of 11
     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 90 long     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 90 long
     own      CCS/2018/practical-state-recovery-attacks-against-legacy-rng-implementations     own      CCS/2018/practical-state-recovery-attacks-against-legacy-rng-implementations
Line 744: Line 782:
     own      USENIX/2014/an-internet-wide-view-of-internet-wide-scanning     own      USENIX/2014/an-internet-wide-view-of-internet-wide-scanning
     own      USENIX/2018/quack-scalable-remote-measurement-of-application-layer-censorship     own      USENIX/2018/quack-scalable-remote-measurement-of-application-layer-censorship
-    other    USENIX/2022/spoki-unveiling-a-new-wave-of-scanners-through-a-reactive-network-telescope +    hit list 88 now vs 90 at draw time — drift 2.2% 
-    hit list 89 now vs 90 at draw time — drift 1.1% +    sample positions in the sorted hit list: 0, 7, 14, 21, 28, 35, 42, 48, 55, 62, 69 (spread 69 of 88) 
-    sample positions in the sorted hit list: 0, 7, 14, 21, 28, 35, 42, 48, 55, 62, 69, 76 (spread 76 of 89) +    precision 6/11; 88 x 6/11 = about 48 papers (19.9% of ACTIVE) 
-    precision 6/12; 89 x 6/12 = about 45 papers (18.6% of ACTIVE) +PUBLISHED_PRECISION_OWN_BLOCKLIST_EXCLUSION 6/11 -> ~48 19.9%
-PUBLISHED_PRECISION_OWN_BLOCKLIST_EXCLUSION 6/12 -> ~45 18.6%+
  
---- own opt-out offer: 70 first-person hits of 242 ACTIVE; pinned sample of 10+--- own opt-out offer: 70 first-person hits of 241 ACTIVE; pinned sample of 10
     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 69 long     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 69 long
     own      CCS/2015/a-search-engine-backed-by-internet-wide-scanning     own      CCS/2015/a-search-engine-backed-by-internet-wide-scanning
Line 764: Line 801:
     hit list 70 now vs 69 at draw time — drift 1.4%     hit list 70 now vs 69 at draw time — drift 1.4%
     sample positions in the sorted hit list: 0, 6, 12, 18, 24, 31, 37, 43, 49, 55 (spread 55 of 70)     sample positions in the sorted hit list: 0, 6, 12, 18, 24, 31, 37, 43, 49, 55 (spread 55 of 70)
-    precision 9/10; 70 x 9/10 = about 63 papers (26.0% of ACTIVE) +    precision 9/10; 70 x 9/10 = about 63 papers (26.1% of ACTIVE) 
-PUBLISHED_PRECISION_OWN_OPT_OUT_OFFER 9/10 -> ~63 26.0%+PUBLISHED_PRECISION_OWN_OPT_OUT_OFFER 9/10 -> ~63 26.1%
  
---- own source-address hygiene: 113 first-person hits of 242 ACTIVE; pinned sample of 10+--- own source-address hygiene: 112 first-person hits of 241 ACTIVE; pinned sample of 10
     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 114 long     sample drawn on 2026-09-10 as every-k-th of a hit list that was then 114 long
     own      CCS/2015/a-search-engine-backed-by-internet-wide-scanning     own      CCS/2015/a-search-engine-backed-by-internet-wide-scanning
Line 779: Line 816:
     other    USENIX/2021/lzr-identifying-unexpected-internet-services     other    USENIX/2021/lzr-identifying-unexpected-internet-services
     own      USENIX/2024/6sense-internet-wide-ipv6-scanning-and-its-security-applications     own      USENIX/2024/6sense-internet-wide-ipv6-scanning-and-its-security-applications
-    hit list 113 now vs 114 at draw time — drift 0.9% +    hit list 112 now vs 114 at draw time — drift 1.8% 
-    sample positions in the sorted hit list: 0, 11, 22, 33, 44, 55, 66, 77, 88, 99 (spread 99 of 113) +    sample positions in the sorted hit list: 0, 11, 22, 33, 44, 55, 66, 77, 88, 98 (spread 98 of 112) 
-    precision 6/10; 113 x 6/10 = about 68 papers (28.1% of ACTIVE) +    precision 6/10; 112 x 6/10 = about 67 papers (27.8% of ACTIVE) 
-PUBLISHED_PRECISION_OWN_SOURCE_ADDRESS_HYGIENE 6/10 -> ~68 28.1%+PUBLISHED_PRECISION_OWN_SOURCE_ADDRESS_HYGIENE 6/10 -> ~67 27.8%
  
 Practice                    first-person probe  hand-read precision  point estimate Practice                    first-person probe  hand-read precision  point estimate
 --------------------------  ------------------  -------------------  -------------- --------------------------  ------------------  -------------------  --------------
-own probe rate              82 (33.9%)          5/12                 ~34 (14.0%) +own probe rate              81 (33.6%)          5/12                 ~34 (14.1%) 
-own blocklist / exclusion   89 (36.8%)          6/12                 ~45 (18.6%) +own blocklist / exclusion   88 (36.5%)          6/11                 ~48 (19.9%) 
-own opt-out offer           70 (28.9%)          9/10                 ~63 (26.0%) +own opt-out offer           70 (29.0%)          9/10                 ~63 (26.1%) 
-own source-address hygiene  113 (46.7%)         6/10                 ~68 (28.1%)+own source-address hygiene  112 (46.5%)         6/10                 ~67 (27.8%)
  
 The point estimate is probe count x sample precision. It is an estimate on a The point estimate is probe count x sample precision. It is an estimate on a
Line 802: Line 839:
 ---------------------------------------------  ------------  ------  ----- ---------------------------------------------  ------------  ------  -----
 mentions IPv6 anywhere                         SCAN 930      281     30.2% mentions IPv6 anywhere                         SCAN 930      281     30.2%
-mentions IPv6 anywhere                         ACTIVE 242    108     44.6%+mentions IPv6 anywhere                         ACTIVE 241    107     44.4%
 names an IPv6-targeting instrument in tools[]  SCAN 930      11      1.2% names an IPv6-targeting instrument in tools[]  SCAN 930      11      1.2%
 names an IPv6-targeting instrument in tools[]  corpus 5,859  11      0.2% names an IPv6-targeting instrument in tools[]  corpus 5,859  11      0.2%
Line 810: Line 847:
 discusses aliased prefixes / dealiasing        SCAN 930      10      1.1% discusses aliased prefixes / dealiasing        SCAN 930      10      1.1%
 PUBLISHED_V6_SCAN 281 30.2% PUBLISHED_V6_SCAN 281 30.2%
-PUBLISHED_V6_ACTIVE 108 44.6%+PUBLISHED_V6_ACTIVE 107 44.4%
 PUBLISHED_V6_INSTR_SCAN 11 PUBLISHED_V6_INSTR_SCAN 11
 PUBLISHED_V6_INSTR_ALL 11 PUBLISHED_V6_INSTR_ALL 11
Line 860: Line 897:
 Population  N     classification[].target == 'ip-address'  share Population  N     classification[].target == 'ip-address'  share
 ----------  ----  ---------------------------------------  ----- ----------  ----  ---------------------------------------  -----
-ACTIVE      242   76                                       31.4%+ACTIVE      241   75                                       31.1%
 SCAN        930   213                                      22.9% SCAN        930   213                                      22.9%
 corpus      5859  295                                      5.0% corpus      5859  295                                      5.0%
-PUBLISHED_IPCLS_ACTIVE 76 31.4%+PUBLISHED_IPCLS_ACTIVE 75 31.1%
 PUBLISHED_IPCLS_SCAN 213 22.9% PUBLISHED_IPCLS_SCAN 213 22.9%
 PUBLISHED_IPCLS_CORPUS 295 5.0% PUBLISHED_IPCLS_CORPUS 295 5.0%
  
-distinct raw resourceName strings on ACTIVE ip-address classifications: 113 (free text; folded on design:ip_classification, not here)+distinct raw resourceName strings on ACTIVE ip-address classifications: 110 (free text; folded on design:ip_classification, not here)
     5 MaxMind     5 MaxMind
     4 MaxMind GeoLite2     4 MaxMind GeoLite2
Line 889: Line 926:
 ACTIVE posters: 4 (1.7%); SCAN posters: 34 (3.7%) ACTIVE posters: 4 (1.7%); SCAN posters: 34 (3.7%)
 ACTIVE records of <=4 pages: 6 (2.5%) ACTIVE records of <=4 pages: 6 (2.5%)
-vantage location stated: all ACTIVE 55.8%, excluding <=4-page records 56.4%+vantage location stated: all ACTIVE 55.6%, excluding <=4-page records 56.2%
 PUBLISHED_ACTIVE_POSTERS 4 PUBLISHED_ACTIVE_POSTERS 4
-PUBLISHED_VANTAGE_FULLONLY 56.4%+PUBLISHED_VANTAGE_FULLONLY 56.2%
  
 ============================================================================== ==============================================================================
 12. MEASURED RESULTS available for the page (detection[].prevalence on ACTIVE) 12. MEASURED RESULTS available for the page (detection[].prevalence on ACTIVE)
 ============================================================================== ==============================================================================
-ACTIVE papers with at least one detection[].prevalence: 241 (99.6%) +ACTIVE papers with at least one detection[].prevalence: 240 (99.6%) 
-PUBLISHED_ACTIVE_PREVALENCE 241 99.6%+PUBLISHED_ACTIVE_PREVALENCE 240 99.6%
  
 ============================================================================== ==============================================================================
Line 1010: Line 1047:
   41.5 / 0.97 = 42.8   41.5 / 0.97 = 42.8
       the page's own arithmetic reconciling scan_budget.py's theoretical 1 GbE figure with the ZMap paper's measured 45-minute ceiling       the page's own arithmetic reconciling scan_budget.py's theoretical 1 GbE figure with the ZMap paper's measured 45-minute ceiling
-  174 / 56 = 3.1 
-      the page's own arithmetic: cites-the-norm over named-an-IRB, both from the report 
   16 CIDR entries; 592,708,864 removed (13.8%); 3,702,258,432 in scope   16 CIDR entries; 592,708,864 removed (13.8%); 3,702,258,432 in scope
       conf/blocklist.conf at tag v4.4.0, computed by pages/scan_budget.py       conf/blocklist.conf at tag v4.4.0, computed by pages/scan_budget.py
Line 1068: Line 1103:
   30-fold / 2-3   30-fold / 2-3
       ratios inside quoted sentences       ratios inside quoted sentences
 +
 +==============================================================================
 +E. DERIVED ARITHMETIC (recomputed from out/scan/rep.txt, not described)
 +==============================================================================
 +  OK   cites-the-norm over named-an-IRB: PUBLISHED_GOODPRACTICE=172 / PUBLISHED_IRB=55 = 3.127, page states 3.1
  
 RESULT: OK RESULT: OK
Line 1865: Line 1905:
   'USENIX/2014/an-internet-wide-view-of-internet-wide-scanning': 'own', // "only 208 organizations have requested that we exclude their networks from our scans" — 208, checked against paper.pdf with pypdf; a first read of a narrow context window misread it as 908   'USENIX/2014/an-internet-wide-view-of-internet-wide-scanning': 'own', // "only 208 organizations have requested that we exclude their networks from our scans" — 208, checked against paper.pdf with pypdf; a first read of a narrow context window misread it as 908
   'USENIX/2018/quack-scalable-remote-measurement-of-application-layer-censorship': 'own', // "respecting an IP blacklist shared with other scanning research"   'USENIX/2018/quack-scalable-remote-measurement-of-application-layer-censorship': 'own', // "respecting an IP blacklist shared with other scanning research"
-  'USENIX/2022/spoki-unveiling-a-new-wave-of-scanners-through-a-reactive-network-telescope': 'other', // analysis-time exclusion of known scan projects+  // DROPPED 2026-09-17, was 'other' ("analysis-time exclusion of known scan 
 +  // projects"). The reading still stands, but the paper left ACTIVE when its 
 +  // only membership tuple — a ZMap run over a closed veth loop — was 
 +  // suppressed (see scripts/tool_use_overrides.mjs), so it is no longer a hit 
 +  // and the pinned-sample guard rejected it. The sample is 11, not 12.
 }; };
 const OPT_VERDICT = { const OPT_VERDICT = {
Line 1972: Line 2016:
   );   );
   const namesNS = SCAN.filter((p) =>   const namesNS = SCAN.filter((p) =>
-    p.tools.some((tool) => DROVE.has(tool.usedOrMentioned) && tool.category === 'network-scanner')+    p.tools.some((tool) => DROVE.has(tool.usedOrMentioned) && tool.category === 'network-scanner' 
 +      && !notRun(p, tool.name))
   );   );
   t(['Population', 'Papers', 'Share'], [   t(['Population', 'Papers', 'Share'], [
Line 2430: Line 2475:
 //                                 naming either is in ACTIVE by construction //                                 naming either is in ACTIVE by construction
 //                                 and the two counts are ALSO corpus-wide. Only //                                 and the two counts are ALSO corpus-wide. Only
-//                                 the percentage column uses ACTIVE=245.+//                                 only the percentage column on that page uses 
 +//                                 ACTIVE as a denominator; this script prints none.
 // //
 // So the populations are identical and the 1-paper gap was never a population // So the populations are identical and the 1-paper gap was never a population
Line 2720: Line 2766:
 ============================================================================== ==============================================================================
  
-dns_fold 'ZMap / XMap'                                        111 +dns_fold 'ZMap / XMap'                                        110 
-scan_fold 'ZMap'                                              95+scan_fold 'ZMap'                                              94
 scan_fold 'XMap'                                              16 scan_fold 'XMap'                                              16
   papers naming both                                          0   papers naming both                                          0
-scan_fold ZMap U XMap                                         111+scan_fold ZMap U XMap                                         110
 symmetric difference                                          0 symmetric difference                                          0
  
Line 2731: Line 2777:
 symmetric difference                                          0 symmetric difference                                          0
  
-PUBLISHED_ZMAP_FAMILY_UNION 111 +PUBLISHED_ZMAP_FAMILY_UNION 110 
-PUBLISHED_ZMAP 95+PUBLISHED_ZMAP 94
 PUBLISHED_XMAP 16 PUBLISHED_XMAP 16
 PUBLISHED_ZGRAB 32 PUBLISHED_ZGRAB 32
Line 2762: Line 2808:
 // //
 // THE RULE APPLIED, written before the entries below: // THE RULE APPLIED, written before the entries below:
-//   suppress when the paper DID NOT RUN the tool (it fingerprinted it, or read +//   (a) suppress when the paper DID NOT RUN the tool — it fingerprinted it, or 
-//   someone else's output). Do NOT suppress when the paper ran the tool but +//       read someone else's output; and 
-//   aimed it somewhere unusual — its own honeypot, its own telescope, a lab +//   (b) suppress when the packets NEVER LEFT THE HOST onto the public Internet: 
-//   rig. Those are recorded as named borderlines on the provenance page, not +//       a closed local loop or a synthetic load generator. 
-//   removed, because "the target was ours" is a different claim from "we never +//   Do NOT suppress when the paper ran the tool and the packets did cross the 
-//   sent the packet" and relitigating it per paper has no stopping rule.+//   Internet, even if they were aimed somewhere unusual — its own honeypot, its 
 +//   own hosts, a cloud VM it controls. "The target was ours" is a different 
 +//   claim from "no packet was sent", and relitigating the former per paper has 
 +//   no stopping rule. 
 +// 
 +//   Clause (b) was NOT in the rule when the first entries were written. It was 
 +//   added on 2026-09-17 after a review pass read USENIX 2022 Spoki and found a 
 +//   ZMap run that clause (a) alone would have kept. Recording that here rather 
 +//   than back-dating the rule: the rule was incomplete, and one published 
 +//   figure was wrong by one paper because of it.
 // //
 // Key is `venue/year/slug|toolName`, exactly as the extraction spells both. // Key is `venue/year/slug|toolName`, exactly as the extraction spells both.
Line 2786: Line 2841:
   ['IMC/2024/have-you-syn-me-characterizing-ten-years-of-internet-scanning|Unicorn',   ['IMC/2024/have-you-syn-me-characterizing-ten-years-of-internet-scanning|Unicorn',
     'telescope fingerprint reference, not a scan the authors ran'],     'telescope fingerprint reference, not a scan the authors ran'],
 +  // USENIX 2022, "Spoki: Unveiling a New Wave of Scanners through a Reactive
 +  // Network Telescope". Clause (b). The authors DID run ZMap, but only as a
 +  // packet generator inside their own machine: "A local pair of virtual
 +  // Ethernet interfaces route packets between the packet source and Spoki. We
 +  // use ZMap to generate TCP SYN packets, passing the MAC address of the
 +  // destination interface along with a probing rate and a range of IP
 +  // addresses to use as a source." The address range is a synthetic SOURCE
 +  // prefix for load generation; nothing is probed. Verified in
 +  // data/fulltext/2022/USENIX/spoki-.../paper.cols.txt on 2026-09-17.
 +  // This tuple was Spoki's only route into ACTIVE, so the paper leaves it.
 +  ['USENIX/2022/spoki-unveiling-a-new-wave-of-scanners-through-a-reactive-network-telescope|ZMap',
 +    'closed veth loop on one host for a throughput benchmark; no packet reaches the Internet'],
 ]); ]);
  
Line 3968: Line 4035:
  
 <bibtex bibliography></bibtex> <bibtex bibliography></bibtex>
 +
 +===== Markup sweep, 2026-09-17 =====
 +
 +Mechanical rendering repair only: a fresh live raw/XHTML export of 188 pages was checked with ''check_wrap.mjs'' and ''check_typography.mjs''. Affected plugin tags, CLI flags and heading markup were repaired; no figures or substantive prose were changed. The resulting source and rendered DOM were re-checked after saving.
  
provenance/programming/internet_scanning.1789611254.txt.gz · Last modified: by karel.kubicek.claude