{
  "catalogue": "Data Protection Exposures",
  "schema_version": "2.0",
  "generated": "2026-07-26",
  "base_url": "https://totaledigitalewaarborging.nl/register",
  "count": 43,
  "licence": "CC BY 4.0",
  "entries": [
    {
      "id": "DPE-2026-0001",
      "name": "Tracking before consent",
      "family": "consent",
      "summary": "A tag fires before the consent question has been answered.",
      "mechanism": {
        "what": "On page load, requests go to a measurement or advertising party at a moment when the visitor has not been able to make a choice. There may be a banner or there may not be; either way something was measured before anything was asked. An identifier is usually set at the same time, making the visitor recognisable on a later visit.",
        "why_it_matters": "Consent that arrives after the processing is not consent for that processing. Someone opening a page about an illness, a legal conflict or a benefit claim has already signalled that to a third party, and the option not to do so never existed.",
        "common_causes": [
          "tag hardcoded in the page rather than behind the consent gate",
          "consent tool blocks cookie placement but not script or container loading",
          "tag added through a dashboard by a team that does not know about the gate"
        ],
        "not_this": "If the tag fires but refusing changes nothing, that is Refusal without effect: this entry is about the moment, that one about the effect of the choice. Both can be present at once and they are separate faults, because an operator can fix one and leave the other."
      },
      "detection": {
        "indicator": "A request to a third-party host carrying an identifier parameter or setting an identifier cookie, timestamped before the consent event. Absent a consent event, the whole capture qualifies.",
        "method": "network-with-identifier",
        "qod": 95,
        "capture_requirements": [
          "clean profile; a warm one may carry earlier consent",
          "no interaction: nothing accepted, refused or dismissed",
          "record the country the capture egressed from; consent flows are often geo-targeted"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The measurement host is a first-party CNAME to the target domain.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "Still an exposure, but not third-party by host. Needs DNS resolution at capture time."
        },
        {
          "condition": "The request carries no identifier and sets no cookie.",
          "checkable": "automated",
          "if_true": "weaken",
          "note": "There is traffic, but the inference about personal data is weaker."
        },
        {
          "condition": "Consent was granted in an earlier session on the same profile.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The tag only fired because the capture clicked something.",
          "checkable": "automated",
          "if_true": "drop"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "repro/frontrun/MANUAL.md",
            "expect": "measurement requests visible before touching the banner"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0001 as present, with the detail behind it"
          },
          {
            "tier": "bookmarklet",
            "path": "repro/bookmarklet/frontrun.bookmarklet.txt"
          },
          {
            "tier": "script",
            "path": "repro/frontrun/frontrun.mjs",
            "expect": "at least one request to a measurement host before interaction, plus an identifier cookie"
          }
        ],
        "public_scanners": [
          "urlscan.io",
          "webbkoll",
          "blacklight"
        ]
      },
      "legal": {
        "provisions": [
          "nl-tw-11-7a",
          "eu-gdpr-6-1-a"
        ],
        "caselaw": [
          "cjeu-planet49"
        ],
        "rebuttals": [
          {
            "objection": "Analytics falls under the strictly-necessary exemption.",
            "answer": "The exemption covers what is necessary for a service the user asked for. Audience measurement is necessary for the operator, not for the visitor. Where the analytics party also uses the data for its own purposes, the argument fails entirely."
          },
          {
            "objection": "The servers are in the EU.",
            "answer": "That answers a different question. This fault is about the moment, not the destination. An entry can be present with the recipient squarely inside the EEA."
          },
          {
            "objection": "It was one oversight, since fixed.",
            "answer": "Testable. Archived source shows how long the tag was there. An unbroken run of years is not an oversight, and it cannot be repaired retroactively."
          },
          {
            "objection": "Our consent tool handles this.",
            "answer": "Measure it rather than assume it. A tool that blocks cookie placement may leave container loading untouched."
          }
        ]
      },
      "related": [
        "DPE-2026-0002",
        "DPE-2026-0003",
        "DPE-2026-0005"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "tracking-before-consent",
      "name_nl": "Meten voor de toestemmingsvraag",
      "summary_nl": "Een tag vuurt voordat de toestemmingsvraag is beantwoord.",
      "in_practice": {
        "dpia": "Verify that no measurement request leaves before consent is recorded, rather than accepting a statement that tags are 'consent-gated'.",
        "procurement": "On delivery, a capture in the no-interaction state shows no requests to third-party measurement hosts and no identifier cookies.",
        "complaint": "A HAR of the no-interaction state, the timestamp of the consent event, and the falsifier list worked through.",
        "audit_question": "Show me a network capture of the homepage before anyone clicks the banner.",
        "audit_question_nl": "Laat een netwerkopname zien van de homepage voordat iemand de banner aanraakt.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Analytics valt onder de uitzondering voor noodzakelijke cookies.",
        "answer_nl": "De uitzondering geldt voor wat nodig is voor een dienst die de bezoeker vroeg. Publieksmeting is nodig voor u, niet voor hem."
      }
    },
    {
      "id": "DPE-2026-0002",
      "name": "Refusal without effect",
      "family": "consent",
      "summary": "Refusing consent does not change what leaves the browser.",
      "mechanism": {
        "what": "The site asks for consent and registers the refusal, but the tags that the refusal should stop do not sit behind the gate. The screen confirms the choice; the wire shows the same traffic as before.",
        "why_it_matters": "A refusal that changes nothing makes the right to withhold and to withdraw consent a formality. The visitor believes they have decided something and they have not.",
        "common_causes": [
          "tags hardcoded rather than gated",
          "consent tool blocks cookies but not the loading of scripts or containers",
          "banner is informational and wired to nothing"
        ],
        "not_this": "If nothing was asked before the tag fired, that is Tracking before consent. If no refusal option is offered at all, that is No refusal option."
      },
      "detection": {
        "indicator": "Set comparison: the third-party hosts contacted after an explicitly registered refusal are equal to, or a superset of, those contacted without any interaction. There is no third reading.",
        "method": "differential",
        "qod": 97,
        "capture_requirements": [
          "two separate captures, each with a fresh profile",
          "read the consent state back after clicking refuse; an unregistered click measures a failed click, not a hollow refusal",
          "identical conditions otherwise: same page, same window, same country"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The refusal was not registered.",
          "checkable": "automated",
          "if_true": "drop",
          "note": "The most important one: it turns a finding into a measurement error."
        },
        {
          "condition": "The banner does block, but later than the capture window.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The surviving requests are strictly necessary for a service the visitor asked for.",
          "checkable": "not-from-capture",
          "if_true": "reclassify",
          "note": "A judgement per host. Never excluded automatically; an entry may be cited with this untested as long as that is stated."
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0002 as present, with the detail behind it"
          }
        ],
        "public_scanners": [
          "urlscan.io",
          "webbkoll"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a",
          "nl-tw-11-7a"
        ],
        "caselaw": [
          "cjeu-planet49"
        ],
        "rebuttals": [
          {
            "objection": "The banner is there, so the visitor has a choice.",
            "answer": "The choice exists on screen and not on the wire. Consent requires an active act of the user; an act without effect is not such an act."
          },
          {
            "objection": "This is analytics, which needs no consent.",
            "answer": "Then the banner should not have listed it, and there would be no refusal to honour. A party cannot both treat something as consent-bound and ignore the refusal."
          }
        ]
      },
      "related": [
        "DPE-2026-0001",
        "DPE-2026-0004"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "refusal-without-effect",
      "name_nl": "Weigeren zonder effect",
      "summary_nl": "Weigeren verandert niet wat de browser verlaat.",
      "in_practice": {
        "dpia": "Verify that refusing changes the outgoing traffic, rather than accepting that a consent tool is installed.",
        "procurement": "On delivery, the set of third-party hosts contacted after refusal is empty of measurement hosts, demonstrated by two captures.",
        "complaint": "Two HARs, no-interaction and refused, plus the read-back consent state proving the refusal registered.",
        "audit_question": "Show me two captures, one where the visitor refused, and tell me the difference.",
        "audit_question_nl": "Laat twee opnames zien, een waarin de bezoeker weigerde, en vertel me het verschil.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Er staat toch een banner.",
        "answer_nl": "De keuze bestaat op het scherm en niet op de lijn. Dat is precies het verwijt."
      }
    },
    {
      "id": "DPE-2026-0003",
      "name": "No refusal option",
      "family": "consent",
      "summary": "The consent dialogue offers acceptance and no way to refuse.",
      "mechanism": {
        "what": "The banner presents an accept control, and refusing requires either leaving the site or navigating a path that does not lead to a working refusal.",
        "why_it_matters": "A choice with one option is not a choice. Consent must be freely given, and it is not free if the only way out is to leave.",
        "common_causes": [
          "banner template with a single call to action",
          "refusal hidden behind a settings layer that does not save",
          "closing the banner counted as acceptance"
        ],
        "not_this": "If a refusal option exists but does nothing, that is Refusal without effect. Here the option is absent."
      },
      "detection": {
        "indicator": "No refusal affordance in the banner DOM: no control whose action registers a negative consent state, at any layer reachable from the first screen.",
        "method": "static-source",
        "qod": 60,
        "capture_requirements": [
          "inspect every layer of the dialogue, not only the first screen",
          "dismissing by clicking away is not a refusal; check what state it writes"
        ],
        "attribution": [
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "A refusal exists on a second layer of the dialogue.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The site sets no consent-bound technology at all, so no refusal is required.",
          "checkable": "automated",
          "if_true": "drop"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0003 as present, with the detail behind it"
          }
        ],
        "public_scanners": [
          "urlscan.io"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a"
        ],
        "caselaw": [
          "cjeu-planet49"
        ],
        "rebuttals": [
          {
            "objection": "Visitors can refuse in their browser settings.",
            "answer": "Consent is sought by the controller and must be refusable where it is sought. Delegating that to the browser does not discharge it."
          }
        ]
      },
      "related": [
        "DPE-2026-0002"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "no-refusal-option",
      "name_nl": "Geen weigeroptie",
      "summary_nl": "De toestemmingsdialoog biedt accepteren en geen manier om te weigeren.",
      "in_practice": {
        "dpia": "Verify that a refusal control exists and writes a negative state, rather than that a banner is present.",
        "procurement": "The consent dialogue offers refusal at the same level as acceptance, verifiable from the first screen.",
        "complaint": "A screenshot of every layer of the dialogue and the consent state written by each control.",
        "audit_question": "Where in the banner does someone say no, and what does that store?",
        "audit_question_nl": "Waar in de banner zegt iemand nee, en wat slaat die knop op?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wie niet wil, kan het in zijn browser uitzetten.",
        "answer_nl": "Toestemming wordt door u gevraagd en moet dus bij u geweigerd kunnen worden."
      }
    },
    {
      "id": "DPE-2026-0004",
      "name": "Maximum cookie lifetime",
      "family": "retention",
      "summary": "An identifier cookie is set for the maximum lifetime a browser accepts, before the question is answered.",
      "mechanism": {
        "what": "At page load, before any consent interaction, a cookie is placed with a lifetime at or near the ceiling the browser permits, currently 399 days in Chromium-based browsers.",
        "why_it_matters": "The visitor is recognisable for over a year on the basis of a decision they were never given. Storage limitation requires a term tied to the purpose, not to the technical maximum.",
        "common_causes": [
          "default retention of the measurement setup left untouched",
          "cookie placed outside the consent gate, so the term was never considered"
        ],
        "not_this": "If the cookie is set only after consent, this is a retention question and not this entry. The pre-consent placement is what makes it a fault here."
      },
      "detection": {
        "indicator": "A Set-Cookie with max-age at or above 34128000 seconds (399 days), or an equivalent Expires, issued before the consent event.",
        "method": "network-with-identifier",
        "qod": 95,
        "capture_requirements": [
          "clean profile",
          "no interaction",
          "read Set-Cookie headers, not only the cookie jar"
        ],
        "attribution": [
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The cookie is strictly necessary for a service the visitor requested.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The lifetime is set by the browser, not by the server.",
          "checkable": "automated",
          "if_true": "drop"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "bookmarklet",
            "path": "repro/bookmarklet/frontrun.bookmarklet.txt"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0004 as present, with the detail behind it"
          }
        ],
        "public_scanners": [
          "urlscan.io",
          "webbkoll"
        ]
      },
      "legal": {
        "provisions": [
          "nl-tw-11-7a",
          "eu-gdpr-6-1-a"
        ],
        "caselaw": [
          "cjeu-planet49"
        ],
        "rebuttals": [
          {
            "objection": "399 days is the industry default.",
            "answer": "A default is not a purpose. Storage limitation asks what term the purpose requires, and the browser ceiling is not an answer to that question."
          }
        ]
      },
      "related": [
        "DPE-2026-0001"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "maximum-cookie-lifetime",
      "name_nl": "Maximale bewaartermijn",
      "summary_nl": "Een identifier-cookie krijgt de maximale bewaartermijn die een browser aanvaardt, voordat de vraag is beantwoord.",
      "in_practice": {
        "dpia": "Verify the actual lifetime of identifiers set before consent, rather than the retention table in the document.",
        "procurement": "No identifier is stored with a lifetime beyond what the stated purpose requires, and none before consent.",
        "complaint": "The Set-Cookie headers from the pre-consent capture, with lifetimes.",
        "audit_question": "What is the longest-lived cookie you set before anyone has chosen anything?",
        "audit_question_nl": "Wat is de langstlevende cookie die u zet voordat iemand iets heeft gekozen?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "399 dagen is de standaard in de markt.",
        "answer_nl": "Een standaardinstelling is geen doel. De vraag is welke termijn het doel vraagt."
      }
    },
    {
      "id": "DPE-2026-0005",
      "name": "Session recording",
      "family": "data",
      "summary": "The session itself is recorded, not merely the page view.",
      "mechanism": {
        "what": "A session-recording script captures behaviour inside the page: mouse movement, scrolling, clicks and often keystrokes in form fields, replayable afterwards as a film of the visit.",
        "why_it_matters": "This is a different order of collection from counting page views. What someone typed and then deleted, where they hesitated, which field they returned to: none of that is needed to run a website, and all of it is revealing.",
        "common_causes": [
          "recording script loaded outside the consent gate",
          "field masking left off, so entered text is captured too"
        ],
        "not_this": "Ordinary page-view analytics is not this entry. The distinguishing feature is capture of in-page behaviour."
      },
      "detection": {
        "indicator": "A request to a session-recording endpoint of a recording vendor, carrying a site identifier, at page load.",
        "method": "network-with-identifier",
        "qod": 95,
        "capture_requirements": [
          "clean profile",
          "no interaction",
          "note whether field masking is active; unmasked input raises the stakes considerably"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The vendor processes only aggregated data without session capture.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "Recording starts only after consent is granted.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "All input fields are masked at source.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0005 as present, with the detail behind it"
          }
        ],
        "public_scanners": [
          "blacklight",
          "urlscan.io"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a",
          "nl-tw-11-7a"
        ],
        "rebuttals": [
          {
            "objection": "The recording servers are in the EU.",
            "answer": "Where the recording is stored says nothing about whether it should have been made. Location is a separate question from lawfulness of collection."
          }
        ]
      },
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "session-recording",
      "name_nl": "Sessieopname",
      "summary_nl": "De sessie zelf wordt opgenomen, niet alleen de paginaweergave.",
      "in_practice": {
        "dpia": "Verify whether in-page behaviour is captured and whether input fields are masked, rather than treating it as analytics.",
        "procurement": "No session recording is active before consent, and where used, input masking is enabled and demonstrated.",
        "complaint": "A capture showing the recording endpoint contacted at load, and whether field masking was active.",
        "audit_question": "Is anything recording mouse movement or keystrokes, and from what moment?",
        "audit_question_nl": "Wordt er muisbeweging of toetsaanslag opgenomen, en vanaf welk moment?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Het is alleen om de gebruikservaring te verbeteren.",
        "answer_nl": "Vraag of de opname invoervelden meeneemt. Dat verschil is groot en wordt zelden uit zichzelf genoemd."
      }
    },
    {
      "id": "DPE-2026-0006",
      "name": "User input to third parties",
      "family": "data",
      "summary": "What the visitor typed or looked for reaches a third party.",
      "mechanism": {
        "what": "A search term, form field or URL path that reveals intent is passed to an analytics or advertising party, usually as a parameter or as part of a page title.",
        "why_it_matters": "The content of a query says far more than the fact of a visit. A search on a health site, a benefits portal or a legal service is close to a statement about the person, and it leaves in plain text.",
        "common_causes": [
          "query string included in the page URL that analytics reports verbatim",
          "form values passed into event parameters",
          "page titles constructed from user input"
        ],
        "not_this": "An identifier alone is not this entry; that is ordinary tracking. What matters here is that the content itself travels."
      },
      "detection": {
        "indicator": "A value entered or searched by the visitor appears verbatim, or trivially encoded, in a request to a host under a different registrable domain.",
        "method": "network-observed",
        "qod": 90,
        "capture_requirements": [
          "use a distinctive search term so it can be found unambiguously in the capture",
          "check both query parameters and POST bodies"
        ],
        "attribution": [
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The value is hashed or truncated beyond recovery before leaving.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The receiving host is a processor under a documented agreement, self-hosted.",
          "checkable": "not-from-capture",
          "if_true": "reclassify"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ],
        "public_scanners": [
          "urlscan.io"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "We do not send personal data, only the page URL.",
            "answer": "If the URL contains what the visitor typed, then the URL is the personal data. The container does not change the content."
          }
        ]
      },
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "user-input-to-third-parties",
      "name_nl": "Invoer naar derden",
      "summary_nl": "Wat de bezoeker intypte of zocht, bereikt een derde partij.",
      "in_practice": {
        "dpia": "Verify that user-entered values do not travel to third parties, rather than that 'only page URLs' are shared.",
        "procurement": "No value entered or searched by a user appears in a request to a party outside the processing chain.",
        "complaint": "A capture using a distinctive search term, showing where that term reappears.",
        "audit_question": "Type a nonsense word into the search box and show me every request containing it.",
        "audit_question_nl": "Typ een onzinwoord in het zoekveld en laat me elk verzoek zien waar het in staat.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij sturen geen persoonsgegevens, alleen de pagina-URL.",
        "answer_nl": "Staat wat de bezoeker intypte in die URL, dan is de URL het persoonsgegeven."
      }
    },
    {
      "id": "DPE-2026-0007",
      "name": "Device fingerprinting",
      "family": "data",
      "summary": "The device is recognised by its characteristics, without any stored identifier.",
      "mechanism": {
        "what": "Scripts read properties that together make a device distinctive: time zone, screen metrics, fonts, canvas or WebGL rendering, enumerated navigator fields. No cookie is stored, so cookie controls do not touch it.",
        "why_it_matters": "Recognition without storage escapes exactly the controls people are told to use. Clearing cookies and refusing consent leave the technique untouched.",
        "common_causes": [
          "anti-fraud or bot-detection library that also serves marketing",
          "advertising script with built-in fingerprinting"
        ],
        "not_this": "Reading a time zone to localise a page is not this entry. The distinguishing feature is enumeration of multiple properties by a third party."
      },
      "detection": {
        "indicator": "Calls to canvas, WebGL, font enumeration, time zone or navigator property enumeration originating from a script under a different registrable domain, before consent.",
        "method": "network-observed",
        "qod": 90,
        "capture_requirements": [
          "hook the property reads through the debugging protocol; a HAR alone does not show them",
          "record which script initiated each read"
        ],
        "attribution": [
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The properties are read by a first-party script, not a third party.",
          "checkable": "automated",
          "if_true": "reclassify"
        },
        {
          "condition": "The reads serve a functional purpose such as localisation or accessibility.",
          "checkable": "not-from-capture",
          "if_true": "weaken",
          "note": "Purpose cannot be established from a capture. The entry establishes the reading, not the intent."
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0007 as present, with the detail behind it"
          }
        ],
        "public_scanners": [
          "blacklight"
        ]
      },
      "legal": {
        "provisions": [
          "nl-tw-11-7a",
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "We set no cookies.",
            "answer": "The cookie provision covers storing and reading information on the device, not only cookies. Reading device characteristics for recognition is within its scope."
          }
        ]
      },
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "device-fingerprinting",
      "name_nl": "Apparaatherkenning",
      "summary_nl": "Het apparaat wordt herkend aan zijn kenmerken, zonder dat er iets is opgeslagen.",
      "in_practice": {
        "dpia": "Verify whether device characteristics are read by third parties, rather than checking only for cookies.",
        "procurement": "No third-party script enumerates device characteristics for recognition purposes before consent.",
        "complaint": "A trace of property reads with the initiating script per read.",
        "audit_question": "What reads the canvas, the fonts or the time zone, and who does it belong to?",
        "audit_question_nl": "Wat leest de canvas, de lettertypen of de tijdzone uit, en van wie is dat?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij zetten geen cookies.",
        "answer_nl": "De cookiebepaling gaat over opslaan en uitlezen op het apparaat, niet alleen over cookies."
      }
    },
    {
      "id": "DPE-2026-0008",
      "name": "Third-party hosted form",
      "family": "chain",
      "summary": "A form that looks like part of the site is hosted by a third party that profiles on its own account.",
      "mechanism": {
        "what": "A signup, contact or newsletter form lives on a domain belonging to a marketing platform. The visitor believes they are dealing with the site; the platform sets its own identifiers and builds its own record.",
        "why_it_matters": "The visitor cannot see who they are actually handing data to. Interest categories ticked on such a form become a profile at a party the person never chose.",
        "common_causes": [
          "marketing platform hosting the form on a vendor subdomain",
          "embedded form in an iframe from another registrable domain"
        ],
        "not_this": "A processor hosting a form under the controller's own domain and instructions is not this entry."
      },
      "detection": {
        "indicator": "Set-Cookie from a host under a different registrable domain than the site that linked to the form, at page load and before any submission.",
        "method": "network-with-identifier",
        "qod": 95,
        "capture_requirements": [
          "never submit the form; establish the fields, not the processing after sending",
          "record the fields offered, since that shows what profile would be built"
        ],
        "attribution": [
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The cookies are strictly necessary to operate the form.",
          "checkable": "not-from-capture",
          "if_true": "weaken"
        },
        {
          "condition": "The form domain is a CNAME under the controller's own domain, operated as a processor.",
          "checkable": "manual",
          "if_true": "reclassify"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ],
        "public_scanners": [
          "urlscan.io",
          "webbkoll"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-44",
          "eu-gdpr-6-1-a"
        ],
        "caselaw": [
          "cjeu-fashion-id"
        ],
        "rebuttals": [
          {
            "objection": "That is our supplier's platform, not our site.",
            "answer": "Fashion ID holds that a controller who arranges for visitor data to reach a third party is jointly responsible for that collection and transmission. Linking to the form is arranging it."
          }
        ]
      },
      "related": [
        "DPE-2026-0009"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "third-party-hosted-form",
      "name_nl": "Formulier bij een derde",
      "summary_nl": "Een formulier dat bij de site lijkt te horen, staat bij een derde die voor eigen rekening profileert.",
      "in_practice": {
        "dpia": "Verify who actually hosts each form and what it sets, rather than treating a supplier form as an internal one.",
        "procurement": "Forms are served from the controller's own domain, or the third-party host sets nothing before submission.",
        "complaint": "A capture of the form page at load, showing the host and the cookies it sets.",
        "audit_question": "When someone fills in your contact form, whose domain are they on?",
        "audit_question_nl": "Als iemand uw contactformulier invult, op wiens domein staat hij dan?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Dat is het platform van onze leverancier, niet onze site.",
        "answer_nl": "Wie regelt dat bezoekersgegevens bij een derde belanden, is daarvoor medeverantwoordelijk."
      }
    },
    {
      "id": "DPE-2026-0009",
      "name": "Third-party resource loading",
      "family": "transfer",
      "summary": "A resource loaded straight from a third party makes every page view a transfer.",
      "mechanism": {
        "what": "A font, script library or image is loaded directly from an external provider instead of being served by the site. Each page view sends the visitor's IP address, and often more, to that provider.",
        "why_it_matters": "It needs no consent interaction to establish and no tracking intent to occur. It happens on the first byte, to every visitor, including those who refuse everything.",
        "common_causes": [
          "CDN link copied from documentation",
          "theme or template that references external fonts by default"
        ],
        "not_this": "This entry is about the mechanism of loading, not about the destination country. Where the data goes is a separate axis; a hotlink within the EEA is still a hotlink."
      },
      "detection": {
        "indicator": "A subresource request to a host under a different registrable domain, present in the initial document, issued without any interaction.",
        "method": "network-observed",
        "qod": 90,
        "capture_requirements": [
          "capture from a clean profile with no interaction",
          "establish the destination separately; do not infer it from the vendor's headquarters"
        ],
        "attribution": [
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The resource is served locally through a proxy or self-hosted copy.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The request carries no data capable of identifying the visitor.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "An IP address reaches the provider in any case; that is the core of the German Google Fonts ruling."
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "bookmarklet",
            "path": "repro/bookmarklet/frontrun.bookmarklet.txt"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0009 as present, with the detail behind it"
          }
        ],
        "public_scanners": [
          "urlscan.io",
          "webbkoll",
          "webpagetest"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-44",
          "eu-gdpr-6-1-a"
        ],
        "caselaw": [
          "lg-muenchen-google-fonts",
          "cjeu-fashion-id"
        ],
        "rebuttals": [
          {
            "objection": "An IP address is not personal data here.",
            "answer": "The Munich ruling on Google Fonts treats hotlinking a provider resource as a transfer of personal data, precisely because the IP reaches the provider."
          },
          {
            "objection": "Our hosting is in the Netherlands.",
            "answer": "Storage location and loaded components are different things. The transfer runs through what the page pulls in, not through where it is stored."
          }
        ]
      },
      "related": [
        "DPE-2026-0008"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "third-party-resource-loading",
      "name_nl": "Externe bron inladen",
      "summary_nl": "Een bron die rechtstreeks van een derde wordt geladen, maakt van elke paginaweergave een doorgifte.",
      "in_practice": {
        "dpia": "Verify which external resources the page loads on first byte, rather than reviewing only the tracking section.",
        "procurement": "All fonts, scripts and libraries are served from the controller's own infrastructure.",
        "complaint": "A capture of the initial document with every subresource host listed.",
        "audit_question": "Which hosts does the page contact before any script of yours has run?",
        "audit_question_nl": "Welke hosts benadert de pagina voordat een script van u heeft gedraaid?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Onze hosting staat in Nederland.",
        "answer_nl": "Waar het staat en wat de pagina inlaadt zijn twee dingen. De doorgifte loopt via het inladen."
      }
    },
    {
      "id": "DPE-2026-0010",
      "name": "Undisclosed recipient",
      "family": "transparency",
      "summary": "A recipient of personal data is missing from the party's own privacy statement.",
      "mechanism": {
        "what": "Measurement shows data going to a party that the published privacy statement does not mention, or the statement asserts something the traffic contradicts, such as that no personal data is processed or that all recipients are inside the EEA.",
        "why_it_matters": "The statement is the one place a person can check what happens to their data. If it is wrong, informed consent is impossible by construction, and every other control rests on nothing.",
        "common_causes": [
          "statement not updated when the measurement setup changed",
          "tags added by a team that does not maintain the statement"
        ],
        "not_this": "This is not about whether the processing was lawful. It is about the gap between the measurement and the party's own account of it."
      },
      "detection": {
        "indicator": "Set difference: recipients observed in the capture minus recipients named in the privacy statement of the same date is non-empty. Both sources belong to the party; the researcher only does the arithmetic.",
        "method": "document-comparison",
        "qod": 97,
        "capture_requirements": [
          "use the statement as it stood on the measurement date, from an archive",
          "search the whole statement and any cookie overview, not just the recipients list"
        ],
        "attribution": [
          "document-diff",
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The recipient is named elsewhere in the statement or in a linked cookie overview.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The statement was updated outside the measured window.",
          "checkable": "manual",
          "if_true": "drop"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ],
        "public_scanners": [
          "wayback",
          "urlscan.io"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "The statement is generic on purpose.",
            "answer": "Article 13 requires the recipients or categories of recipients. A statement that omits a category entirely is not generic but incomplete."
          }
        ]
      },
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "undisclosed-recipient",
      "name_nl": "Niet-vermelde ontvanger",
      "summary_nl": "Een ontvanger van persoonsgegevens ontbreekt in de eigen privacyverklaring van de partij.",
      "in_practice": {
        "dpia": "Compare the measured recipients against the recipients named in the published privacy statement of the same date.",
        "procurement": "Every party receiving personal data is named in the published statement, verified against a capture on delivery.",
        "complaint": "A capture of recipients plus the archived statement of that date, and the set difference between them.",
        "audit_question": "Name every party that receives data, then let me check that against the traffic.",
        "audit_question_nl": "Noem elke partij die gegevens ontvangt, dan leg ik dat naast het verkeer.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "De verklaring is bewust algemeen gehouden.",
        "answer_nl": "De wet vraagt de ontvangers of categorieen ervan. Een categorie die ontbreekt is niet algemeen maar onvolledig."
      }
    },
    {
      "id": "DPE-2026-0011",
      "name": "Tag loaded outside the source",
      "family": "method",
      "summary": "Tags fire from a container while appearing nowhere in the page source.",
      "mechanism": {
        "what": "A tag manager loads measurement or advertising tags at runtime. The identifiers of those tags are not in the delivered HTML, so reading the source suggests they are gone while the traffic shows otherwise.",
        "why_it_matters": "Mostly a methodological trap rather than a harm in itself, and that is why it is catalogued. A researcher who checks only the source concludes that tracking stopped when it did not. It also means the operator can change what runs without any change to the site.",
        "common_causes": [
          "tags migrated from hardcoded to container-managed",
          "marketing team with dashboard access and no deployment"
        ],
        "not_this": "Not every container is this entry. It applies when a tag observed in traffic cannot be found in the delivered source."
      },
      "detection": {
        "indicator": "A property or measurement identifier present in network traffic and absent from the fetched HTML document. A set comparison, not an observation.",
        "method": "differential",
        "qod": 97,
        "capture_requirements": [
          "fetch and retain the HTML document in the same capture",
          "search for the full identifier and for split forms; dynamic assembly would otherwise be missed"
        ],
        "attribution": [
          "cdp-initiator",
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The identifier is present in the source but assembled dynamically.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The initiator is another script rather than the container.",
          "checkable": "automated",
          "if_true": "reclassify"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          },
          {
            "tier": "script",
            "path": "repro/web/check.mjs",
            "expect": "the run reports DPE-2026-0011 as present, with the detail behind it"
          }
        ],
        "public_scanners": [
          "urlscan.io"
        ]
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "We removed the tracking; it is not in our code.",
            "answer": "Absence from the source is not absence from the traffic. The container is the reliable indicator, and its version history shows what ran when."
          }
        ]
      },
      "related": [
        "DPE-2026-0001"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "applies_to": [
        "web"
      ],
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "tag-loaded-outside-source",
      "name_nl": "Tag buiten de broncode",
      "summary_nl": "Tags vuren vanuit een container terwijl ze nergens in de broncode staan.",
      "in_practice": {
        "dpia": "Verify what fires at runtime rather than reading the page source, and require the container version history.",
        "procurement": "The supplier delivers the tag container version history alongside the site, so what ran when is auditable.",
        "complaint": "A capture showing an identifier in traffic that is absent from the fetched HTML.",
        "audit_question": "Which tags does your container load that are not in the source, and who can change them?",
        "audit_question_nl": "Welke tags laadt uw container die niet in de broncode staan, en wie mag die wijzigen?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij hebben de tracking verwijderd, het staat niet in onze code.",
        "answer_nl": "Afwezig in de broncode is niet afwezig in het verkeer. De container is de betrouwbare indicator."
      }
    },
    {
      "id": "DPE-2026-0012",
      "name": "Device telemetry without function",
      "family": "telemetry",
      "applies_to": [
        "firmware",
        "iot",
        "network-device",
        "vehicle"
      ],
      "summary": "A device contacts a server abroad without any function that requires it.",
      "not_a_vulnerability": "Nothing is exploitable and nothing is broken. The device does what its builder intended, and the objection is to that intention. A vulnerability register has no place to put this, which is why it has gone unrecorded.",
      "mechanism": {
        "what": "Firmware opens connections to hosts that serve no function the owner asked for: a fixed endpoint contacted at boot, at intervals, or on every state change. The payload may be status, configuration, usage patterns or an identifier of the device or its owner.",
        "why_it_matters": "The owner bought a device, not a subscription to being observed. Unlike a website there is no browser to inspect it with, no consent dialogue, and often no way to switch it off without breaking the product. The traffic continues for the life of the device, which for a router or a car is a decade.",
        "common_causes": [
          "vendor telemetry enabled by default with no setting to disable it",
          "chipset SDK contacting the chip maker rather than the device brand",
          "update or time service pointed at a fixed host in the vendor's home jurisdiction"
        ],
        "not_this": "A firmware update check against the vendor is expected behaviour and not this entry. What distinguishes it is traffic without a function the owner asked for, or a destination that has nothing to do with the product."
      },
      "detection": {
        "indicator": "Outbound connections from the device to hosts that persist when every user-facing function is idle, established from a network capture at the gateway rather than from the device itself.",
        "method": "network-observed",
        "qod": 90,
        "capture_requirements": [
          "capture upstream of the device, on the router or an inline tap; the device cannot be trusted to report its own traffic",
          "idle baseline first: leave the device untouched and record what it does anyway",
          "record firmware version and region setting; behaviour frequently differs per region",
          "establish the destination by address and routing, never by where the vendor is headquartered"
        ],
        "attribution": [
          "process-trace",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "The traffic serves a function the owner enabled, such as remote access or cloud backup.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The endpoint is a content delivery network fronting a service in another jurisdiction.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "Where an operator is based says nothing about where the data goes. Establish the destination, not the origin of the company."
        },
        {
          "condition": "The connection carries no data beyond what is needed to check for updates.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The behaviour can be switched off in the interface and was left on.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "Still relevant if it is on by default, but it changes the finding from cannot to did not."
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "repro/homecall/MANUAL.md",
            "expect": "connections to hosts unrelated to any function the owner enabled, while the device sits idle"
          }
        ],
        "public_scanners": []
      },
      "legal": {
        "provisions": [
          "eu-gdpr-44",
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "This is anonymous diagnostic data.",
            "answer": "A device identifier tied to a household is not anonymous, and diagnostics that report usage patterns describe the people using it. Establish what is in the payload before accepting the label."
          },
          {
            "objection": "It is in the terms and conditions.",
            "answer": "Consent must be specific and freely given. A term buried in a document accepted once at setup, with no way to refuse and keep the product working, is neither."
          },
          {
            "objection": "The servers belong to our chip supplier, not to us.",
            "answer": "The party placing the product on the market chose that component. Responsibility for what a shipped device does is not transferred by subcontracting it."
          }
        ]
      },
      "related": [
        "DPE-2026-0013"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "device-telemetry-without-function",
      "name_nl": "Apparaat belt naar huis",
      "summary_nl": "Een apparaat zoekt contact met een server in het buitenland zonder functie die dat vraagt.",
      "in_practice": {
        "dpia": "Verify what the device contacts while idle, rather than accepting the telemetry section of the manual.",
        "procurement": "The device contacts no host that serves no function the owner enabled, demonstrated by an idle capture.",
        "complaint": "An idle capture at the gateway, with firmware version and region, and the destinations established by routing.",
        "audit_question": "Unplug everything it does and tell me what it still talks to.",
        "audit_question_nl": "Zet alles uit wat het doet en vertel me waar het dan nog mee praat.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Dat is anonieme diagnostiek.",
        "answer_nl": "Een apparaatnummer dat aan een huishouden hangt is niet anoniem. Vraag wat er in het bericht zit."
      }
    },
    {
      "id": "DPE-2026-0013",
      "name": "Bundled component collection",
      "family": "telemetry",
      "applies_to": [
        "mobile-app",
        "desktop",
        "firmware"
      ],
      "summary": "A bundled component collects on its own account, alongside the function the app performs.",
      "not_a_vulnerability": "The component works exactly as documented by its maker. There is no flaw to fix, only a decision to include it, and vulnerability registers have nowhere to record a decision.",
      "mechanism": {
        "what": "An application ships a third-party library that, beyond the service it provides to the app, gathers device identifiers, installed applications, location or contacts and sends them to its own infrastructure. The developer may not have read what it does.",
        "why_it_matters": "The user chose the app, not the passenger. The collection continues in the background, is invisible in the interface, and often reaches parties that trade in the data rather than use it.",
        "common_causes": [
          "analytics or advertising SDK with collection enabled by default",
          "monetisation library added for revenue rather than function",
          "component inherited from a framework or a white-label build"
        ],
        "not_this": "A processor library operating strictly on the developer's instructions is not this entry. The distinguishing feature is collection on the component's own account."
      },
      "detection": {
        "indicator": "Outbound requests from the application to hosts of a bundled component, carrying device or user identifiers, at moments unrelated to any user action in that app.",
        "method": "network-with-identifier",
        "qod": 95,
        "capture_requirements": [
          "intercept on the device with a trusted proxy; certificate pinning may need addressing and that fact belongs in the write-up",
          "start from a fresh install and record what happens before the first screen is dismissed",
          "list the bundled components statically as well, so traffic can be matched to a component"
        ],
        "attribution": [
          "process-trace",
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The traffic serves the function the user invoked.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The identifiers are resettable and not tied to the device permanently.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The component is configured to collect nothing and the traffic is a heartbeat only.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ],
        "public_scanners": []
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a",
          "eu-gdpr-44"
        ],
        "caselaw": [
          "cjeu-fashion-id"
        ],
        "rebuttals": [
          {
            "objection": "The SDK is the supplier's responsibility.",
            "answer": "The developer decided to ship it. Fashion ID holds that arranging for data to reach a third party makes you jointly responsible for that reaching."
          },
          {
            "objection": "We only use it for crash reporting.",
            "answer": "Then the traffic should be limited to crashes. Establish what the payload contains when nothing has crashed."
          }
        ]
      },
      "related": [
        "DPE-2026-0012",
        "DPE-2026-0008"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "bundled-component-collection",
      "name_nl": "Meeliftende component",
      "summary_nl": "Een meegeleverd onderdeel verzamelt voor eigen rekening, naast wat de app zelf doet.",
      "in_practice": {
        "dpia": "Inventory the bundled components and what each contacts, rather than reviewing only the application's own code.",
        "procurement": "The supplier delivers a component inventory listing every bundled library and the hosts it contacts.",
        "complaint": "A static inventory plus a capture from a fresh install before the first screen is dismissed.",
        "audit_question": "List every third-party library you ship and what each one sends home.",
        "audit_question_nl": "Noem elke bibliotheek van derden die u meelevert en wat elk daarvan naar huis stuurt.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Die SDK is de verantwoordelijkheid van de leverancier.",
        "answer_nl": "U hebt hem meegeleverd. Dat maakt u medeverantwoordelijk voor wat er daardoor vertrekt."
      }
    },
    {
      "id": "DPE-2026-0014",
      "name": "No working off switch",
      "family": "consent",
      "applies_to": [
        "firmware",
        "iot",
        "vehicle",
        "mobile-app"
      ],
      "summary": "The setting that would stop the collection does not exist, or does not survive.",
      "not_a_vulnerability": "Nothing is broken from the builder's point of view. The absence of an off switch is a product decision, and there is no security register that records product decisions.",
      "mechanism": {
        "what": "A device or application collects data with no control to prevent it, or with a control that resets on update, on reboot or after a period, so the collection resumes without the owner doing anything.",
        "why_it_matters": "Consent that cannot be withdrawn is not consent. On a device this bites harder than on a website, because the owner cannot walk away from something they paid for and installed in their home or their car.",
        "common_causes": [
          "setting absent from the interface entirely",
          "preference stored in volatile configuration and lost on firmware update",
          "regional default reapplied after an update"
        ],
        "not_this": "If a control exists and holds, this entry does not apply, however buried the control is. The distinguishing feature is that it is missing or does not survive."
      },
      "detection": {
        "indicator": "Collection continues after the control is set to off, or the control returns to on after a reboot or update, established by capturing before and after.",
        "method": "differential",
        "qod": 97,
        "capture_requirements": [
          "capture with the control on, then off, then again after a reboot and after an update",
          "record the firmware version at each step; a reset on update is a different finding from a reset on reboot"
        ],
        "attribution": [
          "process-trace"
        ]
      },
      "falsifiers": [
        {
          "condition": "The control exists elsewhere, for instance in a companion app or a web interface.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The remaining traffic is strictly necessary to operate the device.",
          "checkable": "manual",
          "if_true": "reclassify"
        },
        {
          "condition": "The reset was caused by a factory reset performed during testing.",
          "checkable": "manual",
          "if_true": "drop"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "repro/deadend/MANUAL.md",
            "expect": "identical outbound traffic with the control on and off, or the control reverting after a reboot"
          }
        ],
        "public_scanners": []
      },
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "The device cannot function without it.",
            "answer": "Then say so, and establish it. Necessity is a claim that can be tested by disabling the traffic and seeing what stops working."
          }
        ]
      },
      "related": [
        "DPE-2026-0002",
        "DPE-2026-0003",
        "DPE-2026-0012"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "slug": "no-working-off-switch",
      "name_nl": "Geen werkende uitschakeling",
      "summary_nl": "De instelling die het verzamelen zou stoppen bestaat niet, of overleeft geen herstart.",
      "in_practice": {
        "dpia": "Verify that the control that stops collection exists and survives a reboot and an update.",
        "procurement": "Any collection beyond what is strictly necessary can be switched off, and the setting survives updates.",
        "complaint": "Captures with the control on, off, and again after a reboot and an update.",
        "audit_question": "Turn it off, restart it, update it, and show me it is still off.",
        "audit_question_nl": "Zet het uit, herstart het, werk het bij, en laat zien dat het nog steeds uit staat.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Zonder dit werkt het apparaat niet.",
        "answer_nl": "Noodzaak is te toetsen: blokkeer het verkeer en kijk wat er stukgaat."
      }
    },
    {
      "id": "DPE-2026-0015",
      "name": "Bid request broadcast",
      "slug": "bid-request-broadcast",
      "name_nl": "Biedverzoek naar veel partijen tegelijk",
      "family": "chain",
      "applies_to": [
        "web",
        "mobile-app"
      ],
      "summary": "One page view is offered to many bidding parties at once, each receiving the context and an identifier.",
      "not_a_vulnerability": "Nothing is exploited and nothing is broken. Broadcasting the request is how the auction is designed to work; the objection is to the design. There is no defect to patch, which is why no vulnerability register has a place for it.",
      "mechanism": {
        "what": "An advertising slot is auctioned in the moment the page or screen loads. To collect bids, the request is sent out in parallel to a set of bidding parties, each copy carrying the same material: what is being viewed, an identifier for the device or the person, and usually coarse location and device characteristics. Losing bidders receive the same copy as the winner and keep it.",
        "why_it_matters": "The person sees one advertisement and does not see that the occasion for it was distributed to dozens of companies, most of which they will never encounter. What is being viewed can itself be sensitive: a page about a diagnosis, a debt, a lawyer. Once broadcast, the copy cannot be recalled, and the number of holders makes any later exercise of rights impractical.",
        "common_causes": [
          "header bidding configured with a long list of bidders, each added without a separate assessment",
          "an exchange forwarding the request onward to further partners after receiving it",
          "the same identifier passed to every bidder, so the copies are joinable across recipients"
        ],
        "not_this": "A single third-party resource loaded from one party is Third-party resource loading. What distinguishes this entry is multiplicity: the same view, with the same identifier, delivered to many parties in one load. It is also not Undisclosed recipient, which is about a gap in a document; here the fault stands even if every bidder is named."
      },
      "detection": {
        "indicator": "Within one page or screen load, requests to two or more hosts under different registrable domains that each carry the same identifier value together with the address or title of what is being viewed. In an application the same finding takes the form of one auction request whose body carries the device advertising identifier, coarse location and network operator in a single payload. The count of distinct receiving domains is the finding.",
        "method": "network-with-identifier",
        "qod": 90,
        "capture_requirements": [
          "clean profile; a warm profile carries identifiers from earlier auctions and inflates the recipient set",
          "capture per consent mode separately: no interaction, refused, accepted. Bidder lists differ per mode and a single capture describes only that mode",
          "record the exit country; bidder configuration is frequently region-dependent",
          "keep the raw capture: the recipient count is only checkable against the full request list"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The identifier differs per recipient and no shared value connects the copies.",
          "checkable": "automated",
          "if_true": "weaken",
          "note": "Still a broadcast of the context, but the copies are not trivially joinable."
        },
        {
          "condition": "The requests are made server-side and the observed hosts are one intermediary, not the bidders.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "A server-side auction is not visible from the client. The finding then concerns the one recipient that is observable, and the onward set has to be established from the party's own documentation."
        },
        {
          "condition": "The capture shows only the accepted state, and refusing yields no such requests.",
          "checkable": "automated",
          "if_true": "weaken",
          "note": "With consent registered first this is a different discussion; the broadcast itself remains the fault, the consent question does not."
        },
        {
          "condition": "The requests carry no identifier and no address of what is being viewed.",
          "checkable": "automated",
          "if_true": "drop"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a",
          "eu-gdpr-5-1-c",
          "eu-gdpr-26"
        ],
        "rebuttals": [
          {
            "objection": "The bid request is anonymous.",
            "answer": "It carries an identifier that is stable enough to bid against, which is the entire point of sending it. A value that lets a party recognise the same device tomorrow is not anonymous."
          },
          {
            "objection": "Consent was collected in the consent framework.",
            "answer": "Test what the person was actually told: how many recipients, named or as a list behind a link, and whether refusing removes them. A framework signal travelling alongside the request says nothing about whether the choice was informed or effective."
          },
          {
            "objection": "Losing bidders discard the data.",
            "answer": "That is a statement about their internal handling, not something the sender can demonstrate. The sending is measurable, the discarding is not."
          }
        ]
      },
      "related": [
        "DPE-2026-0009",
        "DPE-2026-0010",
        "DPE-2026-0016"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there",
        "participation; a party authorised in a declaration file is not thereby a party that received anything. Only an observed request establishes that",
        "completeness; a browser or device capture sees the first recipient. What that recipient forwards onward is not visible from it, so any count is a lower bound"
      ],
      "in_practice": {
        "dpia": "Verify how many parties receive a copy of one page view and whether that list is fixed, rather than accepting that 'an advertising partner' is engaged.",
        "procurement": "The supplier states the complete list of parties receiving a bid request, the list is capped, and it is verifiable from a capture on delivery.",
        "complaint": "A HAR per consent mode, the list of distinct receiving domains, and the shared identifier value that connects the copies.",
        "audit_question": "How many companies receive a copy when one visitor opens one page, and who decides that list?",
        "audit_question_nl": "Hoeveel bedrijven krijgen een kopie als een bezoeker een pagina opent, en wie bepaalt die lijst?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij delen niets, wij verkopen alleen advertentieruimte.",
        "answer_nl": "Bij een veiling gaat het verzoek naar alle deelnemers tegelijk. Vraag om de lijst met wie mag meebieden."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een paginaweergave gaat tegelijk naar veel biedende partijen, elk met de context en een identifier."
    },
    {
      "id": "DPE-2026-0016",
      "name": "Identifier synchronisation between parties",
      "slug": "identifier-synchronisation",
      "name_nl": "Identificatiemerken uitwisselen",
      "family": "chain",
      "applies_to": [
        "web",
        "mobile-app"
      ],
      "summary": "Two parties exchange each other's identifier so their separate records of the same person can be joined.",
      "not_a_vulnerability": "Nothing is broken and nothing is exploited. The exchange is a deliberate feature that both parties built and both benefit from, which is exactly why it has no place in a vulnerability register.",
      "mechanism": {
        "what": "One party calls the other and passes its own identifier for the visitor in the request; the other answers, sets or reads its own identifier, and returns the pairing. Usually this runs as a short chain of redirects or invisible image requests at page load. Afterwards each party can translate its own identifier into the other's.",
        "why_it_matters": "Two separate records become one. Data collected in one place, under one story about what it is for, can from that moment be matched with data collected somewhere else entirely. The person cannot see this happen, and deleting a cookie at one party does not undo the mapping already stored at the other.",
        "common_causes": [
          "a match or sync endpoint invoked automatically when a tag loads",
          "a chain of redirects in which each hop appends its own identifier to the query string",
          "an audience or measurement partner integrated by activating a template that includes the exchange",
          "a match performed between servers, so no cookie is set in the browser at all and a cookie-based audit reports the parties as absent"
        ],
        "not_this": "Passing an identifier to one recipient for that recipient's own use is ordinary tracking. What distinguishes this entry is the exchange: the value of party A appears in a request to party B, and the purpose of that request is the pairing rather than any content."
      },
      "detection": {
        "indicator": "A request to a host under one registrable domain whose URL, body or redirect location contains, verbatim or trivially encoded, an identifier value that another registrable domain set as a cookie or returned in the same capture. The match of the two values is the finding, and it holds equally where no cookie is set anywhere and the value only travels in the requests.",
        "method": "network-with-identifier",
        "qod": 92,
        "capture_requirements": [
          "clean profile, so every identifier observed was minted during this capture and its origin is known",
          "follow redirect chains fully; the pairing is often in an intermediate 302 that a summary view collapses",
          "record cookie values as set, so the later match is against a value with a known source",
          "capture per consent mode; the exchange frequently only runs in the accepted state"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The matching value is a page identifier, campaign code or cache buster rather than a per-visitor identifier.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "Compare across two clean profiles: a value that differs per profile is per-visitor, a value that is identical is not."
        },
        {
          "condition": "Both hosts belong to the same registrable domain or the same declared processor.",
          "checkable": "manual",
          "if_true": "reclassify"
        },
        {
          "condition": "The exchange only occurs after consent was registered.",
          "checkable": "automated",
          "if_true": "weaken",
          "note": "It changes the consent question, not the joining itself."
        },
        {
          "condition": "The value passed is a per-recipient pseudonym that the receiving party cannot map back.",
          "checkable": "not-from-capture",
          "if_true": "weaken",
          "note": "Cannot be settled from the capture. It is a question for the operator, and it belongs in the request for comment."
        },
        {
          "condition": "The identifier field in the exchange contains an unresolved template placeholder rather than a value.",
          "checkable": "automated",
          "if_true": "drop",
          "note": "An attempted exchange and a completed one are different findings. Report the completed one only where the field carries an actual value."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-26",
          "eu-gdpr-6-1-a",
          "nl-tw-11-7a"
        ],
        "caselaw": [
          "cjeu-fashion-id"
        ],
        "rebuttals": [
          {
            "objection": "This is purely technical plumbing between suppliers.",
            "answer": "Deciding to make two datasets joinable is a decision about the purpose and the means. That the mechanism is a redirect does not make it a technicality."
          },
          {
            "objection": "The identifiers are pseudonymous.",
            "answer": "Pseudonymous data is personal data under the regulation, and the entire purpose of the exchange is to keep recognising the same person across contexts."
          },
          {
            "objection": "Users can delete their cookies.",
            "answer": "Deleting a cookie at one party does not remove the mapping already stored at the other. The exchange survives the deletion."
          }
        ]
      },
      "related": [
        "DPE-2026-0015",
        "DPE-2026-0009",
        "DPE-2026-0010"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify whether any recipient receives an identifier belonging to another recipient, rather than assessing each recipient in isolation.",
        "procurement": "No party in the chain receives an identifier issued by another party, demonstrated by a capture in which no identifier value appears across two registrable domains.",
        "complaint": "A HAR with the redirect chain intact, the cookie value as set by the first party, and the request to the second party containing that same value.",
        "audit_question": "Does any of your partners receive an identifier that another partner issued, and where is the arrangement between them?",
        "audit_question_nl": "Krijgt een van uw partners een identifier die een andere partner heeft uitgegeven, en waar staat die afspraak?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij wisselen geen gegevens uit met andere partijen.",
        "answer_nl": "Vraag naar de koppeling van identifiers tussen partijen, ook de vorm die niet via cookies loopt."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Twee partijen wisselen elkaars identifier uit, zodat hun aparte dossiers over dezelfde persoon te koppelen zijn."
    },
    {
      "id": "DPE-2026-0017",
      "name": "Statutory identification number to a third party",
      "slug": "statutory-identification-number",
      "name_nl": "Wettelijk persoonsnummer naar een derde",
      "family": "data",
      "applies_to": [
        "mobile-app",
        "web",
        "api"
      ],
      "summary": "A number a state assigns for identification is transmitted to a party that has no statutory task requiring it.",
      "not_a_vulnerability": "Nothing is exploited. The number is read from a document or a field the person supplied, exactly as the builder intended, and forwarded by design. A vulnerability register has no place for a transfer that works correctly.",
      "mechanism": {
        "what": "A system reads a national identification number, either from a field the person fills in, from the machine-readable zone or chip of an identity document, or from a record it already holds, and sends it onward to a party that performs no task for which a state assigned that number. The number frequently travels as part of a larger blob, such as raw document data, rather than as a labelled field.",
        "why_it_matters": "This number is the key that joins registers which are meant to stay apart. Unlike a cookie it cannot be reset, it is the same number for a lifetime, and once a private party holds it, every later dataset can be matched on it. In much of the EEA private use is restricted precisely because of that property.",
        "common_causes": [
          "a document or chip read in full and uploaded as a whole, with the number inside it",
          "an onboarding flow that asks for the number because a form template contained the field",
          "an identifier reused as an internal customer key after it entered the system for another purpose"
        ],
        "not_this": "A party with a statutory task that requires the number, such as a tax or healthcare body, is not this entry. Nor is a check that returns only a yes or no derived from the number. The distinguishing feature is that the number itself reaches a party for which no statute provides."
      },
      "detection": {
        "indicator": "A request body or upload containing a value that satisfies the structural check for the national identification number in question, sent to a host operated by a party other than the one with the statutory task. Where the number is embedded in raw document data, the finding is the presence of that field within the payload.",
        "method": "network-with-identifier",
        "qod": 88,
        "capture_requirements": [
          "use your own document and your own account; this is the one place where a measurement must never involve someone else's identity",
          "capture the payload, not only the request line; the number is usually in the body or in a binary blob",
          "note where the number came from: typed field, machine-readable zone, chip file, or already held by the system",
          "record the moment in the flow at which it is sent, since sending before any service is requested is a separate question from sending at the point of a check"
        ],
        "attribution": [
          "process-trace",
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The receiving party performs the statutory task for which the number exists.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The value is not the statutory number but a structurally similar one, such as a customer or document number.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "Apply the checksum or structural rule for that country before claiming anything."
        },
        {
          "condition": "The number is transmitted only to a processor acting for the party with the statutory task, under its instructions.",
          "checkable": "not-from-capture",
          "if_true": "reclassify"
        },
        {
          "condition": "The person entered the number themselves in a free-text field with no prompt for it.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "Different finding: the system does not ask for it but does forward it."
        }
      ],
      "legal": {
        "provisions": [
          "nl-uavg-46",
          "eu-gdpr-5-1-c",
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "The person consented to identity verification.",
            "answer": "Consent to being identified is not consent to a specific number reaching a specific party, and where national law restricts use of the number, consent does not lift that restriction."
          },
          {
            "objection": "We do not use the number, it merely passes through.",
            "answer": "Receiving is processing. If it is not used, it did not need to be sent, which is the finding rather than a defence."
          },
          {
            "objection": "It was inside the document data, we did not ask for it.",
            "answer": "Reading a document in full is a choice about what to read. The number is in the payload either way, and the party that built the read decided its scope."
          }
        ]
      },
      "related": [
        "DPE-2026-0018",
        "DPE-2026-0006"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify which fields actually leave during identification, byte for byte, rather than the field list in the supplier's description.",
        "procurement": "No national identification number leaves the controller's own environment, demonstrated on delivery by a capture of a complete onboarding.",
        "complaint": "The captured payload with the number located in it, the structural check that confirms what it is, and the point in the flow at which it was sent.",
        "audit_question": "Show me every field that leaves during identification, including what is inside the document data you upload.",
        "audit_question_nl": "Laat elk veld zien dat vertrekt bij identificatie, inclusief wat er in de documentgegevens zit die u uploadt.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij hebben dat nummer nodig om iemand te identificeren.",
        "answer_nl": "Vraag welke wettelijke taak dat vereist. Zonder die taak mag het nummer niet."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een nummer dat de overheid toekent voor identificatie gaat naar een partij zonder wettelijke taak die het vraagt."
    },
    {
      "id": "DPE-2026-0018",
      "name": "Identity document read beyond the check",
      "slug": "identity-document-beyond-check",
      "name_nl": "Document verder uitgelezen dan de controle",
      "family": "data",
      "applies_to": [
        "mobile-app",
        "web",
        "api"
      ],
      "summary": "An identity check captures the whole document where the question it answers needs a fraction of it.",
      "not_a_vulnerability": "Nothing is exploited and nothing fails. The reader captures what it was built to capture; the objection is to that scope, not to a defect in it.",
      "mechanism": {
        "what": "To answer a narrow question, such as whether someone is over eighteen or whether a name matches, the system photographs or chip-reads the document in full and transmits everything it obtained: the complete machine-readable zone, the portrait image, the security object, the document number, the nationality. The relying party frequently receives, and needs, only a yes or no.",
        "why_it_matters": "The person shows a document to answer one question and hands over a permanent dossier instead: a face image usable for recognition, numbers that never change, and a nationality that was nobody's business. The gap between what was asked and what was taken is invisible at the moment it happens, because the interaction looks like holding a card against a phone.",
        "common_causes": [
          "a verification component that reads all available data groups because the reader supports them",
          "the whole capture uploaded for server-side processing, with the narrowing done afterwards",
          "an image retained as proof of the check rather than the result of the check",
          "the comparison performed by a remote service, so the image travels even where the device could do it"
        ],
        "not_this": "An ordinary identity check, where a person shows a document and a human or a system compares it, is not this entry. Nor is a chip read that stays on the device and yields only a derived answer. The distinguishing feature is that material beyond what the question needs leaves the device."
      },
      "detection": {
        "indicator": "The upload during a check contains fields or files beyond those needed for the stated question: a portrait image or a complete machine-readable zone where the result exposed to the relying party is a single attribute or a boolean. The comparison between what was transmitted and what the result contains is the finding.",
        "method": "network-with-identifier",
        "qod": 85,
        "capture_requirements": [
          "your own document only, on a device you control",
          "capture the payload of the upload, not only its size; the finding is which fields are in it",
          "record what the relying party receives back, since the gap between the two is the measurement",
          "note whether the narrowing happens on the device or after the upload; only the first avoids the transfer"
        ],
        "attribution": [
          "process-trace",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "The relying party needs the full data set for a task set out in law, such as a statutory identification duty.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "All processing happens on the device and only the derived answer leaves it.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The extra fields are needed to verify the authenticity of the document itself.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "Authenticity checking can require the security object. That justifies reading it, not retaining it, and the two are separate questions."
        },
        {
          "condition": "The person was offered a check that reads less and chose the wider one.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-9-1",
          "eu-gdpr-13"
        ],
        "rebuttals": [
          {
            "objection": "We need the document to establish that the person is who they claim.",
            "answer": "That is the question, and the question can be answered with the answer rather than the source material. Reading in full and narrowing afterwards is a design choice, and the transfer has already happened by then."
          },
          {
            "objection": "The portrait is only used for the comparison.",
            "answer": "A face image processed for unique identification is a special category regardless of how briefly it is used. Use and category are separate questions."
          },
          {
            "objection": "The consent screen explained it.",
            "answer": "Test that. Compare the field list the person was shown with the field list in the payload; where the second is longer, the explanation was not of this processing."
          },
          {
            "objection": "The comparison has to happen in the cloud.",
            "answer": "That is a build decision, not a necessity: comparison on the device is demonstrably possible. Where it happens remotely, the sample leaves and the transfer question follows it."
          }
        ]
      },
      "related": [
        "DPE-2026-0017",
        "DPE-2026-0010",
        "DPE-2026-0028"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify which data groups the reader actually extracts and transmits, against the single question the check exists to answer.",
        "procurement": "The check returns a derived attribute and the source material stays on the device, demonstrated on delivery by a capture of one complete check.",
        "complaint": "The captured upload with its field list, the answer the relying party received, and the difference between them.",
        "audit_question": "What question does this check answer, and what exactly leaves the phone in order to answer it?",
        "audit_question_nl": "Welke vraag beantwoordt deze controle, en wat verlaat het toestel precies om die te beantwoorden?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij bewaren het document niet.",
        "answer_nl": "Bewaren en versturen zijn verschillende vragen. Vraag wat er vertrekt om de controle uit te voeren."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een identiteitscontrole legt het hele document vast waar de vraag aan een fractie genoeg had."
    },
    {
      "id": "DPE-2026-0019",
      "name": "Special-category data in an event",
      "slug": "special-category-in-event",
      "name_nl": "Bijzondere gegevens in een gebeurtenis",
      "family": "data",
      "applies_to": [
        "web",
        "mobile-app"
      ],
      "summary": "An event sent to a third party reveals health, belief or sexuality through its name, path or parameters.",
      "not_a_vulnerability": "Nothing is exploited. The event is defined by the builder and fires as intended; what it discloses is a consequence of how it was named and what was attached to it.",
      "mechanism": {
        "what": "A measurement or advertising component sends structured events. The event name, the address of the screen or page it fired on, or a parameter attached to it corresponds to something the person did that falls in a special category: a symptom logged, a condition read about, a support group opened, a triage question answered. No free text is needed; the label alone carries the meaning.",
        "why_it_matters": "The person filled in a questionnaire or read a page, not a disclosure form. What reaches the recipient is a categorised fact about their health, belief or sexuality, attached to an identifier, in a stream built to be joined with other streams. Unlike a sentence in a message, a labelled event is immediately machine-usable.",
        "common_causes": [
          "automatic screen or page tracking, where the address itself names the subject",
          "event names copied from internal feature names that describe what the feature is for",
          "a site-search integration that forwards the typed term as the event name and again as a search keyword",
          "content published under a third party's platform, so its measurement stack receives the path as well"
        ],
        "not_this": "Text the person typed appearing verbatim in a request is User input to third parties. Here nothing typed needs to travel: the name of the event or the address of the screen is enough. Ordinary page-view measurement on a neutral page is also not this entry; what makes it one is that the value maps to a special category."
      },
      "detection": {
        "indicator": "A request to a host under a different registrable domain containing an event name, screen address or parameter value that corresponds to a special category, alongside an identifier. The correspondence must be readable from the value itself, not inferred from context.",
        "method": "network-with-identifier",
        "qod": 88,
        "capture_requirements": [
          "clean profile and your own account; perform only actions you are willing to have recorded",
          "walk one specific path deliberately and note it, so the event stream can be matched against what was done",
          "capture per consent mode; these events frequently continue after refusal, which is a separate entry",
          "record the full request, since the meaning is often in a parameter rather than in the endpoint"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator",
          "process-trace"
        ]
      },
      "falsifiers": [
        {
          "condition": "The value is an opaque identifier that does not itself disclose the category.",
          "checkable": "automated",
          "if_true": "weaken",
          "note": "An opaque code the recipient can resolve through a catalogue it also holds is not opaque in practice, but that has to be established separately."
        },
        {
          "condition": "The recipient is a processor bound to the controller's instructions and does not use the data for its own purposes.",
          "checkable": "not-from-capture",
          "if_true": "reclassify",
          "note": "This one bites more often than expected: the recipient is sometimes the party that built the application. The category still travelled, and the finding narrows rather than disappears."
        },
        {
          "condition": "The event fires on a general page whose address happens to contain a word that reads as a category.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The events only start after explicit consent that named this category.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-9-1",
          "eu-gdpr-6-1-a",
          "eu-gdpr-5-1-c"
        ],
        "rebuttals": [
          {
            "objection": "We do not send health data, only usage statistics.",
            "answer": "The category follows from the content of the message, not from the label on the pipeline. An event named after a symptom is data about health however the stream is described internally."
          },
          {
            "objection": "The data is pseudonymous.",
            "answer": "It travels with an identifier, which is what makes it useful to the recipient. The prohibition in the regulation is not lifted by pseudonymisation."
          },
          {
            "objection": "The recipient is in the EU.",
            "answer": "That answers a different question. A special category reaching a party that has no role in the care or the service is the finding, wherever that party sits."
          }
        ]
      },
      "related": [
        "DPE-2026-0006",
        "DPE-2026-0002",
        "DPE-2026-0010"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify the actual event names and screen addresses that leave, against the categories the assessment claims are not processed.",
        "procurement": "No event name, screen address or parameter transmitted to a third party discloses a special category, verified from a capture of a representative walkthrough.",
        "complaint": "A capture of a deliberate walkthrough, the events it produced, and the mapping from each value to the action that caused it.",
        "audit_question": "Print the list of event names you send outside the organisation and read it out loud.",
        "audit_question_nl": "Druk de lijst af met namen van gebeurtenissen die u naar buiten stuurt, en lees hem hardop voor.",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij versturen geen medische gegevens.",
        "answer_nl": "De naam van een gebeurtenis of een pagina kan het al verraden, zonder dat iemand iets intypt."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een gebeurtenis naar een derde verraadt gezondheid, geloof of seksualiteit via zijn naam, pad of parameters."
    },
    {
      "id": "DPE-2026-0020",
      "name": "Third party under a first-party subdomain",
      "slug": "third-party-under-first-party-subdomain",
      "name_nl": "Derde partij onder een eigen subdomein",
      "family": "chain",
      "applies_to": [
        "web",
        "api"
      ],
      "summary": "A subdomain of the site's own domain resolves to a third party, so its collection reads as the site's own.",
      "not_a_vulnerability": "Nothing is exploited and no control is broken. The alias is configured deliberately, usually to keep a measurement working, and the system resolves it exactly as intended.",
      "mechanism": {
        "what": "A host under the site's own registrable domain is aliased in the domain name system to infrastructure operated by a measurement or advertising party. To the browser the requests and the cookies are first-party: they survive third-party cookie restrictions, they get first-party lifetimes, and blocklists that work on domain names do not match. The party at the other end is unchanged.",
        "why_it_matters": "Every tool the person has to see who is collecting on a page reports the site itself. A visitor who checks, a researcher who scans by domain, and a browser that limits third parties all reach the same wrong conclusion, and the conclusion is wrong by construction rather than by accident.",
        "common_causes": [
          "a measurement supplier offering a first-party endpoint as a way of surviving browser restrictions",
          "an alias configured once by whoever manages the domain, with no record in the tag inventory",
          "a collection endpoint on the site's own domain that forwards onward between servers, where the recipients are no longer visible to the browser at all"
        ],
        "not_this": "A resource served from a delivery network under the operator's own contract is not this entry: nothing collects there on its own account. Third-party resource loading is the opposite case, where the third party is visible as a third party. Here the recipient is a third party while presenting as the first."
      },
      "detection": {
        "indicator": "A host under the site's own registrable domain whose name resolves through an alias chain to a name in a domain operated by another party, and which sets or receives an identifier cookie. The alias chain as resolved at capture time is the finding.",
        "method": "network-with-identifier",
        "qod": 92,
        "capture_requirements": [
          "resolve the name at capture time and record the full chain, not only the address; the alias is the evidence and it can be removed later",
          "resolve from the same country the capture ran in, since answers are frequently location-dependent",
          "record the cookie attributes, because first-party scope and lifetime are half of what makes this worth reporting",
          "note that a domain-based blocklist will not have matched, so an earlier clean scan says nothing"
        ],
        "attribution": [
          "har-pageref",
          "document-diff"
        ]
      },
      "falsifiers": [
        {
          "condition": "The alias points at infrastructure the operator itself controls, such as a delivery network under its own contract, and nothing collects there.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The receiving party acts strictly as a processor and the endpoint serves only the operator's own measurement.",
          "checkable": "not-from-capture",
          "if_true": "reclassify",
          "note": "The transparency question survives that: the person still cannot see who is at the other end."
        },
        {
          "condition": "The privacy statement names the subdomain and the party behind it.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "No identifier is set or transmitted on that host.",
          "checkable": "automated",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-a",
          "eu-gdpr-13",
          "nl-tw-11-7a"
        ],
        "caselaw": [
          "cjeu-fashion-id"
        ],
        "rebuttals": [
          {
            "objection": "It is our own subdomain, so it is first-party data.",
            "answer": "First-party is a browser concept, not a legal one. Who receives the data is established by where the name resolves, and that is measurable."
          },
          {
            "objection": "We did it for measurement accuracy, not to evade anything.",
            "answer": "The effect is the same whatever the motive: the recipient becomes invisible to the visitor and to every domain-based control. Motive is not measurable, effect is."
          },
          {
            "objection": "A scan of our site shows no trackers.",
            "answer": "A scan that works on domain names cannot see this by design. That is the finding, not a rebuttal of it."
          }
        ]
      },
      "related": [
        "DPE-2026-0001",
        "DPE-2026-0009",
        "DPE-2026-0010"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify where each collection endpoint on your own domain actually resolves, rather than treating own-domain traffic as internal.",
        "procurement": "No host under the buyer's domain resolves to a party outside the processing chain, verifiable from the name resolution on delivery.",
        "complaint": "The resolution chain as recorded at capture time, the cookie set on that host with its attributes, and the requests sent to it.",
        "audit_question": "Which of your own subdomains resolve to somebody else, and who put those aliases there?",
        "audit_question_nl": "Welke van uw eigen subdomeinen wijzen naar iemand anders, en wie heeft die verwijzingen gezet?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Dat subdomein is van onszelf.",
        "answer_nl": "Vraag waar het naartoe wijst. Een eigen naam kan naar een derde resolven."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een subdomein van de site zelf wijst naar een derde, zodat diens verzameling leest als die van de site."
    },
    {
      "id": "DPE-2026-0021",
      "name": "Probing the visitor's own device",
      "slug": "probing-the-visitors-own-device",
      "name_nl": "De pagina tast je eigen apparaat af",
      "family": "data",
      "applies_to": [
        "web",
        "desktop"
      ],
      "summary": "A page reaches into the visitor's own machine or local network to see what is installed there.",
      "not_a_vulnerability": "Nothing is broken into. The probe uses ordinary requests that any page may make, and the software it looks for answers as designed. The objection is that the page is looking at all.",
      "mechanism": {
        "what": "While the page is open, requests go to the loopback address or to addresses on the visitor's own network, on a fixed set of ports and paths. What answers, how fast it answers, and whether it answers at all tells the sender which software is installed or which devices are present. The result is a characteristic of the machine that no interface exposes and the visitor never offered.",
        "why_it_matters": "This is not the page describing itself, it is the page describing the visitor's equipment. The properties found are stable, they say something about the person, and the visitor has no way to see it happen: nothing appears on screen, and blocking it requires knowing it is there.",
        "common_causes": [
          "a fraud or device-recognition component checking for locally installed software",
          "a payment or checkout integration probing for a local helper application",
          "a component that enumerates the local network to recognise a returning environment"
        ],
        "not_this": "Reading properties the browser exposes about itself, such as fonts or a canvas rendering, is Device fingerprinting. What distinguishes this entry is that the traffic leaves the page and addresses the visitor's own machine or network, which the browser does not present as a property at all."
      },
      "detection": {
        "indicator": "Requests from the page to a loopback address or to addresses in the visitor's own network range, on a fixed set of ports or paths, present in the capture. Where they occur in every consent mode, that is part of the same observation.",
        "method": "network-observed",
        "qod": 92,
        "capture_requirements": [
          "clean profile, and a capture that records requests which never leave the machine; many tools filter loopback traffic by default",
          "capture per consent mode, since the finding is stronger where the probe runs after refusal as well",
          "record the port set and the paths, because that is what makes the purpose identifiable",
          "check the page's own content security policy: a policy that permits the loopback range is corroboration from the site's own configuration"
        ],
        "attribution": [
          "cdp-initiator",
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "The probe is part of a function the visitor started, such as a local card reader or signing application they chose to use.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The traffic is generated by an extension or by software the visitor installed, not by the page.",
          "checkable": "automated",
          "if_true": "drop",
          "note": "Attribute through the initiator chain, and repeat in a clean profile with no extensions."
        },
        {
          "condition": "The probe only runs after an explicit action by the visitor.",
          "checkable": "automated",
          "if_true": "weaken"
        },
        {
          "condition": "Every probe fails and nothing about the result is transmitted onward.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "Under the terminal-equipment provision the reading itself is the act, so this weakens rather than removes the finding."
        }
      ],
      "legal": {
        "provisions": [
          "nl-tw-11-7a",
          "eu-gdpr-6-1-a",
          "eu-gdpr-5-1-c"
        ],
        "rebuttals": [
          {
            "objection": "It is for fraud prevention.",
            "answer": "That is a purpose, and it has to be stated, limited and justified against a scan of the visitor's own machine. It is not a reason the visitor cannot be told."
          },
          {
            "objection": "We only check whether a helper application is running.",
            "answer": "Then say so, at the moment it happens, and stop when the visitor refuses. Whether the check is narrow is measurable from the port set in the capture."
          },
          {
            "objection": "No personal data is collected.",
            "answer": "The provision on terminal equipment attaches to reading from the device, whether or not the result is personal data. And what software someone runs is a characteristic of that person."
          }
        ]
      },
      "related": [
        "DPE-2026-0007",
        "DPE-2026-0002"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify whether any component addresses the visitor's own machine or network, and in which consent states it does so.",
        "procurement": "No page issues requests to the visitor's loopback address or local network, demonstrated by a capture that includes loopback traffic.",
        "complaint": "A capture including loopback requests, the port and path set, the consent state per capture, and the content security policy of the page.",
        "audit_question": "Does anything on this page talk to the visitor's own computer, and on which ports?",
        "audit_question_nl": "Praat er iets op deze pagina met de computer van de bezoeker zelf, en op welke poorten?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Dat is een beveiligingscontrole.",
        "answer_nl": "Vraag welke poorten en welke software er wordt gezocht, en wat er met die uitkomst gebeurt."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een pagina tast de eigen machine of het thuisnetwerk van de bezoeker af om te zien wat daar draait."
    },
    {
      "id": "DPE-2026-0022",
      "name": "Reporting interval that reveals occupancy",
      "slug": "reporting-interval-reveals-occupancy",
      "name_nl": "Meetinterval dat aanwezigheid verraadt",
      "family": "telemetry",
      "applies_to": [
        "iot",
        "firmware",
        "network-device"
      ],
      "summary": "A device reports its measurements so often, and so identifiably, that the series shows when the home is empty.",
      "not_a_vulnerability": "Nothing is exploited and nothing is broken. The device reports at the interval its builder chose, and the interval is the objection rather than a defect in it.",
      "mechanism": {
        "what": "A device that measures something in a building sends a timestamped series to a remote service, each record carrying a permanent device identifier. The interval is fine, typically minutes, and the series is kept. The stated function, such as showing yield or consumption in an application, would work at a far coarser interval and without a permanent identifier per record.",
        "why_it_matters": "Consumption and production at a five-minute resolution is a presence calendar. Waking, leaving, returning, holidays and an empty house are readable straight from the curve, by anyone holding the series, for as long as they hold it. The occupants never see the series, cannot change the interval, and did not buy a presence sensor.",
        "common_causes": [
          "a fixed upload interval in the firmware, chosen for the vendor's dashboard rather than for the owner",
          "a permanent serial included in every record, so the series is a per-household history rather than an aggregate",
          "the series retained indefinitely because storage is cheap and no retention was configured"
        ],
        "not_this": "A device contacting a server with no function behind it is Device telemetry without function. Here the reporting has a function; what makes it this entry is the granularity, the permanent identifier per record, and the recipient being someone other than the party delivering the service the owner contracted for."
      },
      "detection": {
        "indicator": "A capture at the gateway shows a timestamped measurement series leaving the device at an interval of fifteen minutes or shorter, each record carrying a stable device identifier, addressed to a party other than the one delivering the contracted service. Interval, identifier and recipient are all readable from the capture.",
        "method": "network-observed",
        "qod": 85,
        "capture_requirements": [
          "capture at the gateway or an inline tap, never on the device",
          "capture long enough to establish the interval rather than infer it: a full day at minimum, and a multi-day window if a daily cycle matters",
          "record firmware version and region; interval and destination both change between builds",
          "record whether the interval is configurable in the interface, since a setting that exists changes the finding from cannot to did not"
        ],
        "attribution": [
          "process-trace",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "The recipient is the party delivering the metered service, and the interval follows from that service or from a regulated metering function.",
          "checkable": "manual",
          "if_true": "reclassify"
        },
        {
          "condition": "The records carry no stable identifier and cannot be assembled into a per-device series.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The owner can set the interval, and the observed interval was chosen rather than imposed.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The series is aggregated before transmission, so no fine-grained curve leaves the building.",
          "checkable": "manual",
          "if_true": "drop"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-6-1-a",
          "eu-gdpr-44"
        ],
        "rebuttals": [
          {
            "objection": "It is technical measurement data, not personal data.",
            "answer": "It is measurement data about one building, tied to one device, held as a history. Presence and absence of the people in it are derivable from that series, which is what makes it data about them."
          },
          {
            "objection": "The user wants to see it in the app.",
            "answer": "Then the interval serves the display, and the display is the test: whether the fine series has to leave the building, and whether it has to be kept, are separate questions from whether it is shown."
          },
          {
            "objection": "Nobody analyses it that way.",
            "answer": "The finding is that the data supports it and is held by a party the occupants have no relationship with. What is done with it today is not a property of the data."
          }
        ]
      },
      "related": [
        "DPE-2026-0012",
        "DPE-2026-0014",
        "DPE-2026-0023"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify the actual upload interval and the identifier in each record, against the interval the stated function needs.",
        "procurement": "The device reports at an interval no finer than the contracted service requires, and the fine-grained series stays in the building, demonstrated by a capture at the gateway.",
        "complaint": "A gateway capture spanning at least a day, with the interval, the per-record identifier and the destination, plus the firmware version.",
        "audit_question": "How often does this thing report, and can I tell from that data when the house was empty?",
        "audit_question_nl": "Hoe vaak rapporteert dit ding, en kan ik daaraan zien wanneer het huis leeg was?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Het zijn alleen meetwaarden, geen persoonsgegevens.",
        "answer_nl": "Vraag naar het interval en of elke meting hetzelfde nummer draagt. Een reeks per kwartier toont aanwezigheid."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een apparaat rapporteert zo vaak en zo herkenbaar dat de reeks laat zien wanneer het huis leeg is."
    },
    {
      "id": "DPE-2026-0023",
      "name": "Presence revealed by an automatic reply",
      "slug": "presence-by-automatic-reply",
      "name_nl": "Aanwezigheid via een automatisch antwoord",
      "family": "data",
      "applies_to": [
        "mobile-app",
        "api",
        "desktop",
        "iot"
      ],
      "summary": "A system answers an unsolicited signal by itself, and the answer discloses whether someone is there.",
      "not_a_vulnerability": "Nothing is exploited and no control is circumvented. The automatic answer is a feature, sent over the intended channel and within the intended protocol; that it also reports presence is a property of the design.",
      "mechanism": {
        "what": "Someone sends an ordinary, unrequested signal to an address belonging to a person: a message, a call setup, a lookup, a notification. The receiving system answers on its own, below the level at which the person is involved, and the answer or its absence is observable to the sender. Repeating it produces a timeline of when the device was on, awake, connected or nearby.",
        "why_it_matters": "The person is not told, sees nothing and has no record. Encryption of the content does not help, because the fact and the timing of the answer are the signal. A pattern of such answers describes sleep, work, travel and who is in the same place at the same time, and the exposure survives every setting the person can reach.",
        "common_causes": [
          "a delivery or read confirmation generated by the client before any human sees the message",
          "a fetch of a link preview triggered by receipt rather than by opening",
          "a status or availability field that any party may query",
          "a silent notification that reaches the device and produces an observable acknowledgement"
        ],
        "not_this": "A status a person deliberately publishes is not this entry. Nor is the content of the message, which may be perfectly protected. The distinguishing feature is that the answer is automatic, unrequested, and invisible on the receiving side."
      },
      "detection": {
        "indicator": "A stimulus sent to your own second account or device produces an observable response, with no notification on the receiving side, whose presence or timing changes with the state of that device. Establishing it requires repeating the stimulus while varying only the device state.",
        "method": "differential",
        "qod": 85,
        "capture_requirements": [
          "only your own accounts and your own devices, on both ends; probing someone else's device is outside the method",
          "vary one state at a time: powered off, screen off, application in the background, application open",
          "record the receiving side too, to establish that nothing was shown there",
          "run the same stimulus with the relevant privacy settings on and off, since the finding is often that they change nothing"
        ],
        "attribution": [
          "process-trace"
        ]
      },
      "falsifiers": [
        {
          "condition": "The response is also produced when the device is off, meaning it comes from a server rather than from the device.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "Then it says something about the account, not about presence, which is a different and weaker finding."
        },
        {
          "condition": "The receiving side is notified of the stimulus.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "The person can then see it happening, which removes the invisibility that defines this entry."
        },
        {
          "condition": "A setting reachable by the person suppresses the response, and it holds.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The response requires a prior relationship, such as an accepted contact, which the sender cannot obtain unilaterally.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-13",
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "No content is exposed, the encryption holds.",
            "answer": "The finding is not about content. Whether someone is awake, at home or beside a particular person is personal data, and it travels outside the encrypted payload."
          },
          {
            "objection": "The user can switch off confirmations.",
            "answer": "Test it. Where the setting suppresses the visible indicator but the underlying answer still leaves the device, the setting addresses the interface and not the disclosure."
          },
          {
            "objection": "This is theoretical.",
            "answer": "It is measurable on your own devices, repeatedly, with a stated state per run. That is the opposite of theoretical, and the measurement needs nobody else's account."
          }
        ]
      },
      "related": [
        "DPE-2026-0012",
        "DPE-2026-0014"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify which signals the system answers without user action and what those answers disclose about the state of the device.",
        "procurement": "No unrequested signal from an arbitrary party produces a response that discloses device or user state, demonstrated on delivery.",
        "complaint": "A log of stimuli and responses with the device state per run, the setting state per run, and evidence that nothing was shown on the receiving side.",
        "audit_question": "What does this system answer all by itself, to someone the user never agreed to hear from?",
        "audit_question_nl": "Wat beantwoordt dit systeem uit zichzelf, aan iemand van wie de gebruiker nooit iets wilde horen?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Het systeem antwoordt alleen op een geldige aanvraag.",
        "answer_nl": "Vraag wie zo'n aanvraag kan sturen en of de gebruiker daarvan weet."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een systeem antwoordt uit zichzelf op een ongevraagd signaal, en dat antwoord verraadt of er iemand is."
    },
    {
      "id": "DPE-2026-0024",
      "name": "Recognition of every passer-by",
      "slug": "recognition-of-every-passer-by",
      "name_nl": "Iedereen die passeert wordt herkend",
      "family": "data",
      "applies_to": [
        "iot",
        "firmware",
        "network-device",
        "vehicle"
      ],
      "summary": "A recognition system records everyone it sees, while its purpose concerns only the ones it is looking for.",
      "not_a_vulnerability": "Nothing is exploited. The system records what it was built to record and the comparison works as intended; the objection is that the recording covers everyone rather than the matches.",
      "mechanism": {
        "what": "A camera or sensor reads a characteristic that identifies a person or a vehicle, compares it against a list, and stores a record of the reading whether or not it matched. The stored record includes the identifying value, the time and the location. The purpose stated for the system concerns only the matches, but the storage covers every passage.",
        "why_it_matters": "Someone who is on no list, suspected of nothing and asked for nothing acquires a location history held by a party they have no relationship with. Combined over several sites, the non-matches alone reconstruct movements. The person cannot know a record exists, and in most deployments there is nothing at the location that says so.",
        "common_causes": [
          "everything logged for later evidential use, rather than the comparison result alone",
          "a retention period set once for the whole system instead of separately for matches and non-matches",
          "readings kept to demonstrate that the system works, in the form of the readings themselves"
        ],
        "not_this": "Comparing against a list and discarding non-matches immediately is not this entry, however extensive the comparison. Nor is a camera that records images without recognising anything. The distinguishing feature is that identifying values of non-matches are retained."
      },
      "detection": {
        "indicator": "Records of readings that produced no match exist after the comparison, established from the system's configuration, its export, its retention schedule, or from an access request that returns your own passage while you are on no list.",
        "method": "document-comparison",
        "qod": 78,
        "capture_requirements": [
          "state the source of the finding: configuration, documented retention schedule, export, or an access request on your own data",
          "record the date of the document, since retention schedules change and a finding attaches to a version",
          "distinguish the recognition system from the camera it runs on; retention is often configured separately for each",
          "keep matches and non-matches apart throughout; conflating them is what makes this finding collapse"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "Non-matching readings are discarded within the comparison, with nothing retained beyond a count.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "What is retained is not linkable to a person or a vehicle, such as a count or a coarse category.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "A statute expressly provides for retaining non-matching readings for a stated period.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "The retention is then provided for, which changes the question to whether the practice stays inside it."
        },
        {
          "condition": "The retention observed is shorter than the configured maximum.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-5-1-e",
          "eu-gdpr-13",
          "nl-sv-126jj"
        ],
        "rebuttals": [
          {
            "objection": "The readings are deleted automatically.",
            "answer": "After how long, and established how. A period longer than the comparison itself means the non-matches were stored, which is the finding."
          },
          {
            "objection": "Nobody looks at the non-matches.",
            "answer": "Retention is processing whether or not anyone looks. The question of who may look afterwards is separate and, over years, unknowable in advance."
          },
          {
            "objection": "There is a sign at the entrance.",
            "answer": "Check what it says. A notice that a camera is present is not information that an identifying characteristic is read, compared and stored, and it rarely names the controller or the retention."
          }
        ]
      },
      "related": [
        "DPE-2026-0012",
        "DPE-2026-0018"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify what happens to a reading that does not match, separately from what happens to one that does.",
        "procurement": "Readings that produce no match are discarded within the comparison, demonstrated from the delivered configuration and the export.",
        "complaint": "The retention configuration or schedule with its date, and where possible the answer to an access request showing your own non-matching passage.",
        "audit_question": "I am on no list and I drove past. What do you have about me, and for how long?",
        "audit_question_nl": "Ik sta op geen enkele lijst en ik reed langs. Wat heeft u over mij, en hoe lang?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij bewaren alleen treffers.",
        "answer_nl": "Vraag hoe lang de niet-treffers blijven staan. Daar zit het verschil."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een herkenningssysteem legt iedereen vast die het ziet, terwijl het doel alleen over de gezochten gaat."
    },
    {
      "id": "DPE-2026-0025",
      "name": "Transaction data outside the payment chain",
      "slug": "transaction-data-outside-chain",
      "name_nl": "Transactiegegevens buiten de betaalketen",
      "family": "chain",
      "applies_to": [
        "web",
        "mobile-app",
        "firmware",
        "iot"
      ],
      "summary": "Details of a payment reach parties that play no part in executing it.",
      "not_a_vulnerability": "Nothing is exploited and no payment fails. The forwarding is configured deliberately, usually to measure how well something sells, and the system performs it correctly.",
      "mechanism": {
        "what": "At the moment a payment is initiated or confirmed, the system reports it to parties outside the chain that executes it: what was bought, the amount, an order reference, and an identifier for the customer or the device. In a browser or an app this is a measurement or advertising component; at a terminal or till it is a reporting integration alongside the payment path. The same shape occurs outside retail: a public body reporting each step of a transaction, with a case reference and a status, to a marketing or analytics party.",
        "why_it_matters": "What someone buys is among the most revealing records there is, from medicines to political membership dues. A payment involves the payer, the merchant and the parties that move the money; everyone else is an addition the person cannot see, at a moment when they are concentrating on paying rather than on who is watching.",
        "common_causes": [
          "a purchase event sent to an advertising component to attribute a campaign",
          "basket contents included in an analytics event because the template offered the field",
          "a loyalty or reporting integration in a till system that forwards line items",
          "funnel steps of a payment or application flow reported to an analytics party, keyed to a long-lived identifier"
        ],
        "not_this": "Parties that execute the payment, such as the acquirer, the scheme or the issuer, are not this entry. Nor is an internal record kept by the merchant. The distinguishing feature is a recipient with no role in executing the payment receiving what was bought or what it cost, tied to an identifier."
      },
      "detection": {
        "indicator": "At payment confirmation, a request to a host under a registrable domain belonging to neither the merchant nor a party in the payment chain, carrying the amount, an order reference or item identifiers together with a customer or device identifier.",
        "method": "network-with-identifier",
        "qod": 88,
        "capture_requirements": [
          "your own purchase, your own means of payment; never someone else's transaction",
          "capture through to the confirmation screen, since the reporting frequently fires only there",
          "record which parties belong to the payment chain before judging the rest, so the boundary is drawn before the finding",
          "for a terminal or till, capture at the gateway rather than on the device"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator",
          "process-trace"
        ]
      },
      "falsifiers": [
        {
          "condition": "The recipient is part of the payment chain, such as an acquirer, gateway or fraud-prevention party under contract for that purpose.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The transmitted event carries no identifier and no line detail, only that a purchase occurred.",
          "checkable": "automated",
          "if_true": "weaken"
        },
        {
          "condition": "The recipient acts strictly as a processor for the merchant and does not use the data for its own purposes.",
          "checkable": "not-from-capture",
          "if_true": "reclassify"
        },
        {
          "condition": "The reporting only fires after consent was registered and refusing removes it.",
          "checkable": "automated",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-6-1-a",
          "eu-gdpr-5-1-c",
          "eu-gdpr-9-1"
        ],
        "rebuttals": [
          {
            "objection": "It is only an order total, not personal data.",
            "answer": "It travels with an identifier and an order reference, which is what makes it usable. Amount plus identifier plus time is a record about a person."
          },
          {
            "objection": "We need it to measure our advertising.",
            "answer": "That is a purpose for the merchant, not a role in the payment. It has to stand on its own basis, and the person has to be able to refuse it without failing to pay."
          },
          {
            "objection": "The item description is generic.",
            "answer": "Test it against the actual payload. Where the line detail names the product, the objection is answered by the capture."
          }
        ]
      },
      "related": [
        "DPE-2026-0009",
        "DPE-2026-0020",
        "DPE-2026-0010"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify which parties receive a message at the moment of payment, and which of them execute the payment.",
        "procurement": "At payment confirmation no party outside the payment chain receives the amount, the order reference or line detail, demonstrated by a capture of one complete purchase.",
        "complaint": "A capture from basket to confirmation, the list of recipients at confirmation, and the payment chain named separately.",
        "audit_question": "Who receives a message when a customer pays, and which of those actually move the money?",
        "audit_question_nl": "Wie krijgt bericht als een klant betaalt, en wie daarvan verplaatst het geld werkelijk?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Dat is nodig om de betaling te verwerken.",
        "answer_nl": "Vraag wie in die lijst het geld daadwerkelijk verplaatst, en wie niet."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Gegevens over een betaling bereiken partijen die geen rol spelen in het uitvoeren ervan."
    },
    {
      "id": "DPE-2026-0026",
      "name": "Recipient attributed by a spoofable header",
      "slug": "recipient-attributed-by-header",
      "name_nl": "Ontvanger toegeschreven op een spoofbare header",
      "family": "method",
      "applies_to": [
        "web",
        "mobile-app"
      ],
      "summary": "A finding names the page that caused a request on the basis of a header that anything can set.",
      "not_a_vulnerability": "This is a fault in a measurement rather than in a system. Nothing is exploited and no party is at fault; the finding is wrong, and it is wrong in a way that survives review because the number it produces looks plausible.",
      "mechanism": {
        "what": "A capture is turned into a claim about which page sent data to which recipient. The link between page and request is taken from the referring header in the request, or from the order in which requests appear. Both are unreliable: the header can be set by whatever issued the request, measurement instrumentation routinely rewrites it, and ordering breaks as soon as a capture spans more than one page.",
        "why_it_matters": "The party named as a recipient may never have received anything from that page, and the party that did receive something disappears from the finding. A published measurement that cannot survive this objection damages the case it was meant to support and, worse, the next one by the same researcher.",
        "common_causes": [
          "traffic attributed by referring header because it is the field that is always present",
          "one capture spanning several pages, with requests from a later page counted against an earlier one",
          "navigation to another site during the capture, whose traffic is then counted against the target",
          "a redirect chain collapsed to its final host, so the intermediate recipients vanish"
        ],
        "not_this": "A recipient that is genuinely present but not named in the privacy statement is Undisclosed recipient, a fault in the system. This entry is about the finding: the recipient may not belong to the page at all."
      },
      "detection": {
        "indicator": "Re-attributing the same capture through the page reference recorded in it, or through the initiator chain, produces a different set of recipients per page than attribution by referring header. The difference between the two sets is the fault.",
        "method": "differential",
        "qod": 95,
        "capture_requirements": [
          "the raw capture must be retained with its page reference intact; a summarised recipient list cannot be re-attributed",
          "record every navigation during the capture, including redirects away from the target",
          "keep one capture per page where feasible, so attribution does not depend on reconstruction",
          "state which attribution route was used in the publication itself"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "Attribution was already done through the page reference or the initiator chain.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The capture contains exactly one page load and no navigation, so there is nothing to confuse.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "Both routes yield the same recipient set for the page in question.",
          "checkable": "automated",
          "if_true": "drop",
          "note": "The finding then stands on the stronger route, and saying so is worth a sentence in the publication."
        },
        {
          "condition": "The raw capture no longer exists and the attribution cannot be redone.",
          "checkable": "not-from-capture",
          "if_true": "weaken",
          "note": "The finding cannot be repaired, only repeated. Report it as unverifiable rather than as sound."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-2"
        ],
        "rebuttals": [
          {
            "objection": "The header is what the browser sends, so it is authoritative.",
            "answer": "It is what the issuing party chose to send. Instrumentation rewrites it as a matter of routine, and a field that anything may set cannot establish who caused a request."
          },
          {
            "objection": "The finding was correct anyway.",
            "answer": "Then it survives re-attribution, which costs one pass over the capture you already have. Doing it is cheaper than defending it later."
          },
          {
            "objection": "Nobody checks this.",
            "answer": "The party you named will, and it is the first thing their technical people will look at."
          }
        ]
      },
      "related": [
        "DPE-2026-0010",
        "DPE-2026-0027",
        "DPE-2026-0028"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify how the assessment's supporting measurement attributed traffic to pages before relying on its recipient list.",
        "procurement": "Measurements delivered by a supplier state their attribution route, and the raw capture is delivered with them.",
        "complaint": "The raw capture, the attribution route used, and the recipient list produced by that route rather than a summary.",
        "audit_question": "How do you know that this request came from that page?",
        "audit_question_nl": "Hoe weet u dat dit verzoek van die pagina kwam?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Het staat in de referer.",
        "answer_nl": "Die is te vervalsen en meetsoftware doet dat standaard. Vraag om de pageref of de initiator-keten."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een bevinding wijst de veroorzakende pagina aan op basis van een header die iedereen kan zetten."
    },
    {
      "id": "DPE-2026-0027",
      "name": "Country attributed from a stale database",
      "slug": "country-from-stale-database",
      "name_nl": "Land bepaald met een verouderde database",
      "family": "method",
      "applies_to": [
        "web",
        "mobile-app",
        "iot",
        "firmware"
      ],
      "summary": "A transfer claim rests on an address-to-country lookup that no longer matches the assignment.",
      "not_a_vulnerability": "A fault in a measurement, not in a system. Nothing was attacked and no party misbehaved; the conclusion about where data went is simply not supported by the source it was drawn from.",
      "mechanism": {
        "what": "A finding states that data left for a particular country. The country came from a lookup table mapping addresses to locations. Such tables are snapshots: address blocks are reassigned, providers move ranges between regions, and hosting shifts between sites. A table built before the measurement can place a current address in a country it left, in either direction.",
        "why_it_matters": "The transfer question is the one most likely to be contested, and it is the one where a wrong answer is easiest to demonstrate. A single misplaced address lets the other party dismiss the whole measurement without addressing the rest of it.",
        "common_causes": [
          "a lookup database shipped with a tool and never updated",
          "the country of the operating company used instead of the destination of the traffic",
          "a content delivery front end resolved to one country while the origin sits elsewhere",
          "the country recorded at analysis time rather than at capture time, with the reassignment in between"
        ],
        "not_this": "Genuinely sending data to a third country is a fault of the system, and the transfer provisions address it. This entry is about the claim: the destination attributed may not be where the data went."
      },
      "detection": {
        "indicator": "Resolving the same addresses again with a lookup source built after the measurement date yields a different country for at least one host in the finding. Alternatively, the build date of the source used precedes the measurement date.",
        "method": "differential",
        "qod": 90,
        "capture_requirements": [
          "record the addresses as resolved at capture time, not only the host names; a name resolves differently later",
          "record the build date and version of the lookup source, and publish it with the finding",
          "resolve from the same country the capture ran in, since resolution is frequently location-dependent",
          "keep the routing evidence for any host on which the transfer claim rests"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "The lookup source was built after the measurement and re-resolution yields the same country.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The destination is established by routing or by a statement from the party rather than by a lookup table.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The finding does not depend on the country at all.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "Many findings stand regardless of destination. Where the country is decoration, remove it rather than defend it."
        },
        {
          "condition": "Only hosts irrelevant to the claim changed country on re-resolution.",
          "checkable": "automated",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-44",
          "eu-gdpr-5-2"
        ],
        "rebuttals": [
          {
            "objection": "The tool said so.",
            "answer": "The tool consulted a table with a build date. Publish that date, and re-resolve if it precedes the measurement."
          },
          {
            "objection": "The company is American, so the data goes to America.",
            "answer": "Where a company is based says nothing about where the traffic lands, and the reverse holds too. The destination is measurable; the origin of the company is not the measurement."
          },
          {
            "objection": "It resolves to that country from here.",
            "answer": "Then say from where and when you resolved it. That is a fact about your measurement, and stating it is what makes it checkable."
          }
        ]
      },
      "related": [
        "DPE-2026-0026",
        "DPE-2026-0028",
        "DPE-2026-0012"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify how the destination country in a supporting measurement was established, and with a source of which date.",
        "procurement": "Any transfer statement is supported by addresses resolved at the stated date, with the version of the lookup source named.",
        "complaint": "The addresses as resolved at capture time, the version and build date of the lookup source, and the routing evidence for the hosts the claim rests on.",
        "audit_question": "Which database told you that this address is in that country, and when was it built?",
        "audit_question_nl": "Welke database zei dat dit adres in dat land ligt, en van wanneer is die?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Volgens onze database ligt dat adres daar.",
        "answer_nl": "Vraag van wanneer die database is. Adresblokken wisselen van land."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een doorgifteclaim rust op een adres-naar-landtabel die niet meer klopt met de toewijzing."
    },
    {
      "id": "DPE-2026-0028",
      "name": "Presence in a binary taken for sending",
      "slug": "presence-taken-for-sending",
      "name_nl": "Aanwezigheid in de binary telt als verzending",
      "family": "method",
      "applies_to": [
        "mobile-app",
        "desktop",
        "firmware"
      ],
      "summary": "A finding treats a component compiled into a package as proof that it transmits.",
      "not_a_vulnerability": "A fault in a measurement. Nothing is exploited and the package may be entirely innocent of what the finding says; the evidence simply does not reach as far as the conclusion.",
      "mechanism": {
        "what": "Analysis of a package finds the strings, classes or endpoints of a collecting component and the finding reports that the product sends data to that party. Packages routinely carry code that is never reached: pulled in through a dependency, kept for a build variant for another market, or left behind after a feature was removed. Presence establishes what could run, not what did.",
        "why_it_matters": "Naming a recipient that never received anything is the mistake that ends an investigation. It is also the mistake that makes the genuine findings in the same report unusable, because a single overreach lets everything else be dismissed as the same kind of claim.",
        "common_causes": [
          "a string or class match reported as a data flow",
          "a component present for a build variant distributed in another region",
          "an endpoint constant compiled in with no code path that reaches it",
          "a dependency that arrived through another dependency and is never initialised"
        ],
        "not_this": "A component that does transmit on its own account is Bundled component collection, a fault of the system. This entry is the step before it: the evidence shows presence and the claim asserts sending."
      },
      "detection": {
        "indicator": "The finding rests on static analysis alone, and a dynamic capture of the running product shows no request to the component's endpoints during a run that exercises the relevant functionality. Presence in the package with no observed traffic is the fault in the claim.",
        "method": "static-source",
        "qod": 85,
        "capture_requirements": [
          "label every finding by evidence level, keeping present-in-package strictly apart from observed-sending",
          "record the package version and its source, since components differ per build variant and per market",
          "run the dynamic check from a cold start on a clean device, since much of it fires only at first launch",
          "state what the dynamic check could not see, including traffic that pinning or a protected channel kept out of view"
        ],
        "attribution": [
          "process-trace",
          "document-diff"
        ]
      },
      "falsifiers": [
        {
          "condition": "A dynamic capture shows requests to the component's endpoints.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "The finding then stands as an observed transmission and should be reported as one."
        },
        {
          "condition": "The finding already states that it establishes presence only.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "Presence is a legitimate finding when labelled as such. This entry is about the leap, not about static analysis."
        },
        {
          "condition": "A code path is shown to reach the component under conditions the capture did not cover, such as a login or a region.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The component transmits over a channel the capture could not observe.",
          "checkable": "not-from-capture",
          "if_true": "weaken",
          "note": "Absence of observed traffic is then not evidence of absence, and the finding has to say so."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-2"
        ],
        "rebuttals": [
          {
            "objection": "The library is in there, so it does something.",
            "answer": "Packages carry code that is never reached. What it does is a question for a capture, and until then the finding is about the package rather than about a transmission."
          },
          {
            "objection": "Dynamic measurement is too hard for this product.",
            "answer": "Then report presence as presence. A weaker finding that holds is worth more than a strong one that is withdrawn."
          },
          {
            "objection": "Other researchers report it the same way.",
            "answer": "The party you name will not accept that, and neither will a supervisory authority reading a report where one claim is over-reached."
          }
        ]
      },
      "related": [
        "DPE-2026-0013",
        "DPE-2026-0026",
        "DPE-2026-0027"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify whether a supporting analysis established transmission or only presence, and treat the two as different statements.",
        "procurement": "Findings delivered by a supplier label each one as observed transmission or as presence in the package, with the method that established it.",
        "complaint": "The package version, the static evidence, and a dynamic capture of a cold start with a statement of what it could not observe.",
        "audit_question": "Did you see this component send anything, or did you see that it is in the package?",
        "audit_question_nl": "Hebt u dit onderdeel iets zien versturen, of hebt u gezien dat het in het pakket zit?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Het zit in de app, dus het verstuurt.",
        "answer_nl": "In het pakket zitten en verzenden zijn twee dingen. Vraag om de opname."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een bevinding ziet een onderdeel in een pakket aan voor bewijs dat het ook verzendt."
    },
    {
      "id": "DPE-2026-0029",
      "name": "Failed capture read as a clean result",
      "slug": "failed-capture-read-as-clean",
      "name_nl": "Mislukte meting telt als schoon resultaat",
      "family": "method",
      "applies_to": [
        "web",
        "mobile-app",
        "iot",
        "firmware"
      ],
      "summary": "A measurement that did not work is reported as a subject that does nothing.",
      "not_a_vulnerability": "A fault in a measurement, not in a system. Nobody is at fault except the measurement, and the party that ends up described as clean may be anything but.",
      "mechanism": {
        "what": "A capture produces little or no traffic and the conclusion drawn is that the subject collects little or nothing. In fact the run failed: the interception was refused by a pinned connection, the environment was detected, the session was too short, the page never rendered its heavier components because too many captures ran at once, or the traffic arrived but no request bodies were readable. Nothing distinguishes an empty result from a clean subject unless validity is established separately from content.",
        "why_it_matters": "A false negative is published as reassurance, and reassurance is harder to withdraw than an accusation. It also breaks comparison: a set in which some runs failed silently ranks the subjects by how well they were measured rather than by what they do.",
        "common_causes": [
          "many captures run in parallel, starving the heavier components so they never execute",
          "interception blocked on exactly the channel that carries the sensitive payload, while other channels decrypt normally",
          "a capture from an address the subject treats differently, so a different version of the subject was measured",
          "a session that ends before behaviour that fires on scroll, on login or after a delay",
          "an extraction pattern narrower than the field names in use, so present values are counted as absent"
        ],
        "not_this": "A subject that genuinely does nothing observable is a negative finding worth publishing. This entry is about the step before it: whether the run was capable of showing the thing it reports as absent."
      },
      "detection": {
        "indicator": "A control run of the same subject, in isolation and with the same behaviour performed, produces traffic that the original run does not. Alternatively the capture itself fails a validity check: components present in the delivered code produced no traffic at all, or the capture contains flows but no readable request bodies.",
        "method": "differential",
        "qod": 90,
        "capture_requirements": [
          "record run validity separately from run content: did traffic arrive, was it readable, did the session last long enough, was visitor-like behaviour performed",
          "record concurrency, since parallel captures compete for the same resources and heavy subjects lose",
          "keep an idle baseline of the measurement environment, so traffic belonging to the platform is not charged to the subject",
          "state each negative as a count over valid runs, never as 'not seen'"
        ],
        "attribution": [
          "process-trace",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "A control run in isolation produces the same empty result.",
          "checkable": "automated",
          "if_true": "drop",
          "note": "The negative then stands, and it stands much more strongly for having been tested."
        },
        {
          "condition": "The run passed an explicit validity check recorded at the time.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The subject is known to behave differently for the measurement environment, and that was recorded.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "Recording it converts a false negative into a stated limit, which is a legitimate finding."
        },
        {
          "condition": "The absence claimed is about a behaviour that had never been observed in the subject even when measurement worked.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "Establish how often it occurred while present before claiming it stopped. A behaviour that fires in half of sessions needs several runs before a single clean one means anything."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-2"
        ],
        "rebuttals": [
          {
            "objection": "We measured and found nothing.",
            "answer": "Say how many valid runs that was, and what would have shown up had it been there. A count over valid runs is a finding; 'nothing seen' is not."
          },
          {
            "objection": "The scan is automated, so it is consistent.",
            "answer": "Consistent failure is still failure. Automation makes an invalid run cheap to repeat, which is how a whole set acquires the same blind spot."
          },
          {
            "objection": "The subject cleaned up after our questions.",
            "answer": "Possibly, and that is worth establishing properly: compare against the party's own machine-readable configuration rather than against the absence of traffic in one run."
          }
        ]
      },
      "related": [
        "DPE-2026-0026",
        "DPE-2026-0027",
        "DPE-2026-0028"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify that a supporting measurement recorded its own validity before accepting a statement that nothing was found.",
        "procurement": "Measurements delivered by a supplier report the number of valid runs behind every negative statement.",
        "complaint": "The number of valid runs, what the run was capable of observing, and a control run of the same subject in isolation.",
        "audit_question": "How do you know your measurement would have seen it if it had been there?",
        "audit_question_nl": "Hoe weet u dat uw meting het gezien zou hebben als het er was geweest?",
        "complaint_nl": "Een opname of uitdraai die laat zien wat er werkelijk gebeurt, met de datum erbij en het land van waaruit is gemeten.",
        "objection_nl": "Wij hebben gemeten en niets gevonden.",
        "answer_nl": "Vraag hoe u weet dat de meting het gezien zou hebben. Een mislukte opname lijkt op een schone."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ],
      "summary_nl": "Een meting die niet werkte, wordt gerapporteerd als een onderwerp dat niets doet."
    },
    {
      "id": "DPE-2026-0030",
      "name": "Open tracking in an email",
      "slug": "open-tracking-in-email",
      "name_nl": "Openen van een bericht wordt gemeten",
      "family": "data",
      "applies_to": [
        "web",
        "mobile-app",
        "desktop"
      ],
      "summary": "A message reports back when it was opened, through a resource fetched on rendering whose address identifies the recipient.",
      "summary_nl": "Een bericht meldt terug wanneer het geopend is, via een bron die bij het weergeven wordt opgehaald en de ontvanger aanwijst.",
      "not_a_vulnerability": "Nothing is exploited and nothing is broken. The message does exactly what the sending platform was configured to make it do, and the objection is to that configuration.",
      "mechanism": {
        "what": "The message body references a remote resource: a one-pixel image, a background image, a font, a stylesheet. Its address carries a value unique to the recipient. Displaying the message makes the client fetch it, which tells the measuring party the time of opening, the client, the operating system and the network the reader was on, and it repeats on every later opening. The resource is chosen so that nothing appears on screen, so the reader has no cue that anything happened.",
        "why_it_matters": "Reading is not an act the reader performs towards the sender. Here it becomes one: the sender learns when a message was read, how often, from where and on which device, and from a series of those the reader's daily rhythm, time zone, holidays and whether a message was forwarded. The reader learns none of it and was asked nothing, because there is no moment in a message at which anything can be asked.",
        "common_causes": [
          "open measurement enabled by default per campaign in the sending platform",
          "a decorative remote image whose address carries the recipient token anyway",
          "a read receipt implemented as an image fetch because the protocol offers no other route",
          "a template inherited between campaigns, with the measurement in it"
        ],
        "not_this": "A resource loaded by a web page is Third-party resource loading; there the fetch belongs to a page and the address is the same for everyone. What distinguishes this entry is that rendering a message triggers the fetch and that the address singles out one recipient. A visible image with an address identical for every recipient is not this entry."
      },
      "detection": {
        "indicator": "The same mailing, received at two addresses under your control, contains remote resource references whose path or query differs between the two copies while the message is otherwise identical. The per-recipient difference in the address is the fault. An address identical in both copies is not.",
        "method": "differential",
        "qod": 95,
        "capture_requirements": [
          "two addresses you control, both subscribed to the same mailing, compared on the raw source of the message rather than on the rendered view",
          "record the state of remote content blocking in the client used, because it decides whether the fetch happens, not whether the address identifies you",
          "keep the message as received, headers included; a forwarded copy may have been rewritten on the way",
          "send a second mailing to the same two addresses, so a value that varies per send can be told apart from one that varies per recipient"
        ],
        "attribution": [
          "document-diff"
        ]
      },
      "falsifiers": [
        {
          "condition": "The remote resource addresses are identical in both copies, so nothing in them singles out a recipient.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The differing value varies per send rather than per recipient, shown by the second mailing to the same two addresses.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The resource is served from the sender's own domain and no other party receives the fetch.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "Still open tracking, but only the sender learns it. The number of parties changes, the mechanism does not."
        },
        {
          "condition": "The recipient asked for a delivery or read confirmation and can see the same record.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The client fetches every remote resource in advance through a proxy, for every message, whether opened or not.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "The address still identifies the recipient; what it reports about the moment of reading becomes unreliable. That is a limit on the inference, not on the finding."
        }
      ],
      "legal": {
        "provisions": [
          "nl-tw-11-7a",
          "eu-gdpr-6-1-a",
          "eu-gdpr-13"
        ],
        "rebuttals": [
          {
            "objection": "We only look at aggregate open rates.",
            "answer": "The address fetched is unique per recipient, which is what makes the aggregate possible in the first place. Which rows are looked at is a choice made after the fact and can change tomorrow; the record is there either way."
          },
          {
            "objection": "The recipient subscribed.",
            "answer": "Subscribing is agreement to receive the message, not to being observed while reading it. The two are separately askable, and a platform can send without measuring."
          },
          {
            "objection": "We need it for deliverability.",
            "answer": "Deliverability is measured from bounces and complaints, which the mail protocol reports without touching the reader. Whether a message was opened adds nothing to it."
          },
          {
            "objection": "Most clients block images anyway.",
            "answer": "Then the measurement fails for those readers and works for the rest. What the message was built to do is the finding, not the success rate."
          }
        ]
      },
      "related": [
        "DPE-2026-0009",
        "DPE-2026-0031"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify from the raw source of a sent message which remote addresses it contains and whether they differ per recipient, instead of accepting that the platform measures opens 'anonymously'.",
        "procurement": "Messages sent on the buyer's behalf contain no remote resource whose address differs per recipient, unless the recipient asked for the confirmation and can see it.",
        "complaint": "The raw source of the same mailing as received at two addresses of the complainant, with the differing addresses marked, and the date of the send.",
        "audit_question": "Show me the raw source of the last mailing, and the same mailing as it went to a second address.",
        "audit_question_nl": "Laat de ruwe bron zien van de laatste mailing, en dezelfde mailing zoals die naar een tweede adres ging.",
        "complaint_nl": "Twee ontvangen berichten in ruwe vorm, met het verschil in de adressen aangewezen, en de verzenddatum erbij.",
        "objection_nl": "Wij kijken alleen naar hoeveel mensen openen, niet naar wie.",
        "answer_nl": "Het opgehaalde adres is per ontvanger uniek, en daarom kan dat cijfer bestaan. Wat u ermee doet, verandert de vastlegging niet."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0031",
      "name": "Email address as a cross-service identifier",
      "slug": "email-address-as-identifier",
      "name_nl": "E-mailadres als sleutel tussen diensten",
      "family": "chain",
      "applies_to": [
        "web",
        "mobile-app",
        "api"
      ],
      "summary": "An address given for contact travels on, plain or hashed, so separate parties can recognise the same person.",
      "summary_nl": "Een adres dat voor contact is gegeven, gaat door naar andere partijen, plat of als hashwaarde, zodat zij dezelfde persoon herkennen.",
      "not_a_vulnerability": "Nothing leaks and nothing is broken into. The address is passed on deliberately, by design, and the design is the objection.",
      "mechanism": {
        "what": "An address the person supplied for a purpose of their own, an account, an order, a newsletter, is used as a key. It is sent to other parties in the clear or, more often, as a hash of the address in lowercase with the spaces trimmed. The hash protects nothing here: any party that already holds the address computes the same value, which is precisely why that form is used. Neither side has to exchange anything with the other, because both derive the same key from a value the person handed over once.",
        "why_it_matters": "An address is stable for years and follows the person across devices, browsers and applications. A cookie can be cleared; this cannot. It joins what someone did on one service to what they did on another, and usually to a name, because an address is rarely anonymous. It was given in order to be reached, not in order to be recognised elsewhere.",
        "common_causes": [
          "an advertising tag configured to send the address field on form submission, for audience matching",
          "a customer list uploaded from server to server for matching against a platform's own users",
          "an identity resolution component added through a tag container",
          "a login form that hashes the address in the browser and sends it onward in the same step"
        ],
        "not_this": "Text the visitor typed appearing in a request as content is User input to third parties; there the content itself is what travels. Here the address is used as a key, it may be hashed, and it may travel from a server rather than from the browser. Two parties exchanging identifiers of their own is Identifier synchronisation between parties; here no exchange is needed, because both sides can compute the same value from the address."
      },
      "detection": {
        "indicator": "A request to a host under a different registrable domain containing the address entered, or the MD5, SHA-1 or SHA-256 of that address in lowercase and trimmed, in hexadecimal or base64. Compute the hashes of the test address before measuring and search the capture for those strings.",
        "method": "network-with-identifier",
        "qod": 95,
        "capture_requirements": [
          "use an address that exists only for this measurement, so a match cannot have come from anywhere else",
          "compute the hashes in advance, including a variant without normalisation, and record which one matched",
          "search request bodies and fragments as well as query strings; matching values are usually posted rather than appended",
          "a transfer from server to server does not appear in a browser capture at all, so absence in the capture settles nothing"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The matched value is a hash of something other than the address, shown by recomputing the hash of the exact address against the captured value.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The address travelled to a party executing a step the person asked for, such as delivering the message or the order.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The recipient acts only on the operator's instruction and does not use the value to recognise the person elsewhere.",
          "checkable": "not-from-capture",
          "if_true": "weaken",
          "note": "The transfer is visible in the capture; the purpose is not. A processing agreement of the same date is what settles it."
        },
        {
          "condition": "A refusal registered in the consent state removes the request.",
          "checkable": "automated",
          "if_true": "weaken",
          "note": "The mechanism is then present but gated, which is a different finding from an ungated one and is worth stating as such."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-b",
          "eu-gdpr-6-1-a",
          "eu-gdpr-13"
        ],
        "rebuttals": [
          {
            "objection": "It is hashed, so it is not personal data.",
            "answer": "A hash of an address is a pseudonym, not anonymity: every party that holds the address computes the same value, and that is exactly why it is sent. If it did not identify, it would not work."
          },
          {
            "objection": "It is our own customer data.",
            "answer": "It is, until it leaves. The objection is not to holding the address but to using it as a key at another party, for a purpose it was not given for."
          },
          {
            "objection": "It is only for suppression, so we do not advertise to existing customers.",
            "answer": "That purpose is testable. Suppression is a list matched once; it does not require the address to travel on every form submission or every page view."
          },
          {
            "objection": "The recipient deletes it after matching.",
            "answer": "The value it matched on is the same value the person has everywhere else, so the match persists in the profile whether the input is deleted or not."
          }
        ]
      },
      "related": [
        "DPE-2026-0006",
        "DPE-2026-0016",
        "DPE-2026-0030"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify with a test address, and a search for its hashes, which parties receive it, rather than accepting that no personal data is shared with advertising partners.",
        "procurement": "No form field and no server process transmits a customer address, in any encoding, to a party that is not executing the service the person asked for.",
        "complaint": "A capture containing the hash of a test address, the hashes computed in advance, and the moment the address was entered.",
        "audit_question": "If I enter an address on your site, which parties can compute that address afterwards?",
        "audit_question_nl": "Als ik een adres invul op uw site, welke partijen kunnen dat adres daarna zelf uitrekenen?",
        "complaint_nl": "Een opname waarin de hashwaarde van een testadres voorkomt, met de vooraf berekende hashes erbij en het moment van invullen.",
        "objection_nl": "Het adres is gehasht, dus het zijn geen persoonsgegevens.",
        "answer_nl": "Iedere partij die het adres al heeft, rekent dezelfde waarde uit. Daarom werkt het als sleutel, en daarom is het herleidbaar."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0032",
      "name": "Account identity joined to a tracking profile",
      "slug": "account-identity-joined-to-profile",
      "name_nl": "Account gekoppeld aan het volgprofiel",
      "family": "chain",
      "applies_to": [
        "web",
        "mobile-app"
      ],
      "summary": "At sign-in, the operator's account identifier reaches a party that already holds a profile of the same browser.",
      "summary_nl": "Bij het inloggen gaat de accountaanduiding van de dienst naar een partij die al een profiel van dezelfde browser had.",
      "not_a_vulnerability": "Nothing is exploited. The identifier is passed on because a setting says so, and the objection is to the setting.",
      "mechanism": {
        "what": "Before sign-in a third party recognises the browser or the device by an identifier of its own. At the moment of authentication the operator hands that same party its own account identifier: a user number, a customer number, a hashed address, sometimes the address itself. From then on the profile that was pseudonymous has a name attached. Everything recorded before the sign-in and everything recorded after it, on any device where the person signs in, belongs to one identified person.",
        "why_it_matters": "The step is invisible and it cannot be undone. A profile built from browsing can be argued about as long as it is pseudonymous; once joined to an account it is a dossier about a named person. Clearing cookies no longer separates the two, because the next sign-in joins them again.",
        "common_causes": [
          "a user identifier configured as a custom dimension or user property in a measurement tag",
          "an advertising tag firing on the login event with the account identifier as a parameter",
          "an identity feature of the measurement product, enabled as soon as a user identifier is available",
          "the same identifier used in the application and in the tag, because it was the value at hand"
        ],
        "not_this": "Two third parties exchanging identifiers so their profiles can be matched is Identifier synchronisation between parties. Here the value comes from the operator itself and names the account. An operator writing its own user identifier into its own store is not this entry either: the value has to reach a party that also holds an identifier of its own for that browser."
      },
      "detection": {
        "indicator": "Differential over accounts. Sign in twice in the same browser profile with two accounts you control: a request to a host under a different registrable domain carries a value that changes with the account while that host's own identifier stays the same. The reverse check confirms it, in that the same account in a fresh profile yields the same account-dependent value against a new host identifier.",
        "method": "differential",
        "qod": 95,
        "capture_requirements": [
          "two accounts you control on the same service, plus a clean profile for the reverse check",
          "capture the authentication step and the first screen after it; the join is often made once per session",
          "record the consent state, because the join may be gated and the gate is part of the finding",
          "compare on values, not on parameter names: every product names its user identifier differently",
          "sign in twice with the same account, so a session token can be told apart from an account identifier"
        ],
        "attribution": [
          "har-pageref",
          "cdp-initiator"
        ]
      },
      "falsifiers": [
        {
          "condition": "The account-dependent value changes on every sign-in of the same account, so it identifies a session rather than an account.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The receiving host is under the operator's own registrable domain.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The receiving party holds no identifier of its own for this browser, so there is nothing to join to.",
          "checkable": "automated",
          "if_true": "weaken",
          "note": "Then the account identifier is being disclosed, which is a transfer question, without the joining that makes this entry what it is."
        },
        {
          "condition": "The recipient acts on the operator's instruction only and is barred from using the value for its own purposes.",
          "checkable": "not-from-capture",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-b",
          "eu-gdpr-6-1-a",
          "eu-gdpr-13",
          "eu-gdpr-26"
        ],
        "rebuttals": [
          {
            "objection": "We only send an internal number, not a name.",
            "answer": "The number is the join. The recipient does not need the name to know that this browser and that account are one person, and the operator can resolve the number to a name whenever it likes."
          },
          {
            "objection": "It improves measurement across devices.",
            "answer": "That is the purpose stated plainly, and it is exactly the processing nobody was asked about. A benefit to the operator is not a ground."
          },
          {
            "objection": "The person is logged in, so they know we know them.",
            "answer": "They know the operator knows them. This is about a third party, and the sign-in screen says nothing about it."
          },
          {
            "objection": "The identifier is hashed before it is sent.",
            "answer": "A hash that is stable per account works as an account identifier. What matters is that the value is the same on every visit and different per person."
          }
        ]
      },
      "related": [
        "DPE-2026-0016",
        "DPE-2026-0031"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify with two test accounts what leaves the browser at the moment of sign-in, rather than accepting that measurement is pseudonymous.",
        "procurement": "No account identifier, hashed or not, reaches a measurement or advertising party at authentication; demonstrated with two test accounts on delivery.",
        "complaint": "Two captures of the sign-in step with different accounts, the value that changes with the account marked, and the third party's own identifier shown to be constant.",
        "audit_question": "What leaves the browser at the moment someone signs in, and does anything in it change with the account?",
        "audit_question_nl": "Wat verlaat de browser op het moment dat iemand inlogt, en verandert daar iets in met het account mee?",
        "complaint_nl": "Twee opnamen van dezelfde inlogstap met verschillende accounts, met de waarde die meeverandert aangewezen.",
        "objection_nl": "Wij sturen alleen een intern nummer door, geen naam.",
        "answer_nl": "Dat nummer is juist de koppeling. De ontvanger hoeft de naam niet te kennen om te weten dat deze browser en dat account een persoon zijn."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0033",
      "name": "Sign-in requesting more than identity",
      "slug": "sign-in-beyond-identity",
      "name_nl": "Inloggen vraagt meer dan inloggen nodig heeft",
      "family": "data",
      "applies_to": [
        "web",
        "mobile-app",
        "api"
      ],
      "summary": "Signing in through another party grants access to records the sign-in does not need, in the same action.",
      "summary_nl": "Inloggen via een andere partij geeft in dezelfde handeling toegang tot gegevens die voor het inloggen niet nodig zijn.",
      "not_a_vulnerability": "Nothing is bypassed. The access is asked for openly and granted by the person, in one action with the login, and the objection is to the bundling.",
      "mechanism": {
        "what": "Signing in through an identity provider works through an authorisation request that states what is being asked for. Authentication needs an identifier and at most a verified address. The request as sent asks for more: a contact list, a calendar, a friend list, posted content, files, profile fields the service never displays. The person sees one screen and one button, so granting the login grants the rest in the same act. What was asked is readable in the address of the authorisation request itself.",
        "why_it_matters": "Most of what is granted here concerns other people as well: a contact list is data about people who were never asked anything. The grant usually outlives the session and often the account, it renews itself silently, and declining the extra parts while keeping the login is rarely offered.",
        "common_causes": [
          "a scope copied from an example in the provider's documentation",
          "one scope string for the whole application, including features this person never uses",
          "access that a removed feature needed, left in the request",
          "the broadest scope chosen during development so that nothing would fail"
        ],
        "not_this": "An identity check that reads a document more fully than the question required is Identity document read beyond the check. This entry is about a delegated authorisation: the extra access is granted rather than read, it concerns a live account elsewhere, and it stays granted after the sign-in is over."
      },
      "detection": {
        "indicator": "The scope of the authorisation request, readable in the address bar when the provider's screen appears, contains values granting access to records other than the person's identity, such as messages, contacts, calendar, files or posted content; and no control on that screen declines those values while still completing the sign-in. Both parts are read from the request and the screen as delivered.",
        "method": "network-observed",
        "qod": 90,
        "capture_requirements": [
          "read the authorisation request as sent, from the address bar or the capture, not the summary the consent screen shows",
          "record the provider, the application version and the date, because scope strings change per release",
          "try declining a single item and record what happens to the sign-in",
          "check the grant afterwards in the provider's own permissions overview, and whether it survives signing out"
        ],
        "attribution": [
          "har-pageref",
          "document-diff"
        ]
      },
      "falsifiers": [
        {
          "condition": "Every value in the scope corresponds to a feature the person invoked, and the request is made at the moment they invoke it.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "Asking at the moment of use is the fix, and where it is done this entry does not apply."
        },
        {
          "condition": "The extra items can be declined individually and the sign-in completes without them.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The provider requires the value for authentication itself and offers no narrower one.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "The fault then sits with the party that defined the scope rather than with the application that had to pick one."
        },
        {
          "condition": "The scope grants only fields the application displays back to the person immediately.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-6-1-a",
          "eu-gdpr-25"
        ],
        "rebuttals": [
          {
            "objection": "The person consented on the provider's screen.",
            "answer": "Consent has to be specific. One button that grants a login and a contact list at once is specific for neither, and the people in that contact list were asked nothing at all."
          },
          {
            "objection": "We request it but we do not use it.",
            "answer": "A grant is access. What counts is what the token permits, not what this release happens to call, and the next release does not have to ask again."
          },
          {
            "objection": "The provider designed that screen.",
            "answer": "The application chose the scope string; the screen only renders it. Narrowing it is a change in one line."
          },
          {
            "objection": "It is needed to make onboarding smooth.",
            "answer": "Convenience is a purpose of the operator. It can be offered as a step the person takes, at the moment they want it, rather than folded into the login."
          }
        ]
      },
      "related": [
        "DPE-2026-0018"
      ],
      "in_practice": {
        "dpia": "Verify the scope string of the authorisation request against the features that actually exist, rather than the description of the login integration.",
        "procurement": "The authorisation request contains only what authentication requires; access for a feature is requested when the feature is used, and can be declined separately.",
        "complaint": "The authorisation request as sent with the scope values marked, a screenshot of the consent screen of the same date, and what happened when a single item was declined.",
        "audit_question": "Read me the scope of your login request, and name the feature behind each item.",
        "audit_question_nl": "Lees me voor wat er in de scope van uw inlogverzoek staat, en noem bij elk onderdeel de functie die het gebruikt.",
        "complaint_nl": "Het inlogverzoek zoals het verstuurd is, met de gevraagde onderdelen aangewezen, en een schermafdruk van hetzelfde moment.",
        "objection_nl": "De gebruiker heeft op het scherm van de aanbieder toestemming gegeven.",
        "answer_nl": "Toestemming moet specifiek zijn. Een knop die tegelijk inloggen en een adresboek weggeeft is dat niet, en de mensen in dat adresboek is niets gevraagd."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0034",
      "name": "Logs recording content, not events",
      "slug": "logs-recording-content",
      "name_nl": "Logboek met inhoud in plaats van gebeurtenissen",
      "family": "data",
      "applies_to": [
        "web",
        "mobile-app",
        "api",
        "desktop",
        "firmware"
      ],
      "summary": "A log keeps what the person wrote or was shown, where recording that something happened would do.",
      "summary_nl": "Een logboek bewaart wat iemand invulde of te zien kreeg, terwijl vastleggen dat er iets gebeurde volstaat.",
      "not_a_vulnerability": "Nothing is broken into. The logging level is a setting, the payload is written on purpose, and the objection is to what that setting causes to be stored.",
      "mechanism": {
        "what": "Logging is set to a level that writes the payload: the body of a request, the fields of a form, the text of a message, the parameters of a query, the response returned to the person. The line then holds the content itself instead of a reference to the record it belongs to. Because logs exist for running the system rather than for the process they describe, they usually sit outside the retention schedule of that process, are readable by more people, are copied into a search or monitoring system, and are kept for as long as storage allows.",
        "why_it_matters": "Content is where the sensitive part is. A log written this way holds what someone searched for, what they wrote to a helpdesk, the contents of a report about their health or their debts, in a store that was never designed to hold it, that an access request usually never reaches, and that outlives the deletion of the record it came from.",
        "common_causes": [
          "debug logging left on after release",
          "a framework that writes full request and response bodies by default",
          "an error handler that serialises the whole object it failed on",
          "the payload written deliberately, to make support easier"
        ],
        "not_this": "Content reaching another party is User input to third parties; this entry is about the operator's own store, and content does not have to leave the organisation to be in the wrong place. A log recording that a record was opened, by whom and when, is the normal case and is not this entry."
      },
      "detection": {
        "indicator": "A value only the person could have supplied, a distinctive marker string entered into a field for this test, appears in the log records the operator returns for that session, whether through an access request, a support export or the log store itself. The line contains the value rather than a reference to where the value is kept.",
        "method": "document-comparison",
        "qod": 85,
        "capture_requirements": [
          "use a distinctive marker string entered into a field, so a match cannot have come from anywhere else",
          "ask for the log records of that session specifically; a general access request returns the process record, not the log",
          "record which store answered: application log, access log, error log, or an external search or monitoring system",
          "record the retention stated for that store separately from the retention stated for the process"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "The marker appears only in the record that is part of the process itself, not in a log.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The log line holds the value in a masked form, or a reference instead of the value.",
          "checkable": "automated",
          "if_true": "drop"
        },
        {
          "condition": "The log store falls under the same retention and access rules as the process record, and an access request reaches it.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The logging level was raised for a bounded incident and the records were destroyed when it closed.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "Checkable against the change record and the retention of the store, rather than against the recollection of the engineer."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-5-1-b",
          "eu-gdpr-5-1-e"
        ],
        "rebuttals": [
          {
            "objection": "Logs are technical data.",
            "answer": "The store is technical; the content is not. What determines the category is what the line contains, not which directory it sits in."
          },
          {
            "objection": "Nobody reads them.",
            "answer": "Access is what counts, not habit. And a log nobody reads is a log whose retention nobody watches."
          },
          {
            "objection": "We need it to debug.",
            "answer": "Then it is needed for the length of the investigation, as a reference plus the record it points to, rather than as a copy of the content kept for a year."
          },
          {
            "objection": "They are deleted after ninety days.",
            "answer": "Show where that is written for this store, and check it against the monitoring system the lines were copied into. Retention set for one store rarely follows the copy."
          }
        ]
      },
      "related": [
        "DPE-2026-0006",
        "DPE-2026-0035"
      ],
      "in_practice": {
        "dpia": "Verify with a marker string what ends up in the log stores, and check whether those stores appear in the retention schedule at all.",
        "procurement": "Logs record events and references; payload content is not written, and every log store is named in the retention schedule with a period.",
        "complaint": "The marker string, the log records returned that contain it, and the retention stated for the store that returned them.",
        "audit_question": "If I type a sentence into your form, in how many stores does that sentence exist an hour later?",
        "audit_question_nl": "Als ik een zin in uw formulier typ, in hoeveel bestanden staat die zin dan een uur later nog?",
        "complaint_nl": "De ingevoerde markeringstekst, de logregels waarin die terugkomt, en de bewaartermijn van het bestand dat ze leverde.",
        "objection_nl": "Logbestanden zijn technische gegevens.",
        "answer_nl": "Het bestand is technisch, de inhoud niet. Wat er in de regel staat bepaalt de categorie, niet waar die regel staat."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0035",
      "name": "Erasure that does not reach the backup",
      "slug": "erasure-not-reaching-backup",
      "name_nl": "Wissen dat de back-up niet bereikt",
      "family": "retention",
      "applies_to": [
        "web",
        "mobile-app",
        "api",
        "desktop"
      ],
      "summary": "A record erased on request survives in the backup and returns to the live system on a restore.",
      "summary_nl": "Een op verzoek gewist gegeven blijft in de back-up staan en komt bij een herstel weer in het systeem terug.",
      "not_a_vulnerability": "Nothing fails and nothing is attacked. The backup does what a backup does; the objection is that the erasure procedure was never designed to survive it.",
      "mechanism": {
        "what": "The erasure is carried out in the live system. Backups made before it keep the record and nothing marks it as erased. When a backup is restored, in part or in whole, the record comes back, and from that moment it is live again: indexed, exported, included in the next backup. Where no register of erasures is kept, the restore cannot even be corrected afterwards, because nobody knows what was supposed to be gone.",
        "why_it_matters": "The person was told the data was gone. It was not, and the moment it returns has nothing to do with anything they can see or ask about. The same holds for scheduled deletion: a record removed on time reappears from a backup whose cycle is longer than the period it was meant to enforce.",
        "common_causes": [
          "erasure implemented as a delete in the application, with backups outside the scope of the procedure",
          "no register of erasures, so a restore cannot re-apply what was erased",
          "a backup cycle longer than the retention period it is supposed to serve",
          "test and analysis environments refreshed from the same backup"
        ],
        "not_this": "A record kept too long in the live system is an ordinary retention finding. This entry is about the second copy: the live system is right and the store behind it is not. A log holding content is Logs recording content, not events, where the fault is what gets written rather than what fails to be removed."
      },
      "detection": {
        "indicator": "The organisation's own answer states either that backups are out of scope for erasure, or that no register of erasures exists from which a restore could be corrected. In a system you administer yourself the behavioural check settles it directly: a record erased on request is present again after a restore, with no re-application step in between.",
        "method": "document-comparison",
        "qod": 75,
        "capture_requirements": [
          "ask in writing what happens to backups on an erasure request, and keep the answer with its date",
          "ask whether a register of erasures is kept and whether it is applied after a restore, and by whom",
          "where you administer the system, test on a copy: erase, restore, look",
          "record the backup cycle and the retention period next to each other; a cycle longer than the period settles the scheduled-deletion half on its own"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "A register of erasures is kept and re-applied after every restore, and the procedure names who does it.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "Backups are encrypted per record with a key destroyed at erasure.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "The restore then returns something nobody can read, which is a defensible implementation of erasure."
        },
        {
          "condition": "Backup retention is shorter than the period after which the record would have been deleted anyway.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The erasure request was refused on a stated ground, so nothing had to be erased.",
          "checkable": "manual",
          "if_true": "drop"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-17",
          "eu-gdpr-5-1-e",
          "eu-gdpr-5-2"
        ],
        "rebuttals": [
          {
            "objection": "A backup cannot be edited, that is what makes it a backup.",
            "answer": "Nobody asks for it to be edited. What is asked is that the erasure survives a restore, which a register applied on restore achieves without touching the backup at all."
          },
          {
            "objection": "The backup is only for disaster recovery.",
            "answer": "Then the disaster is the day the erased record comes back. What the copy is for does not change what happens when it is used."
          },
          {
            "objection": "We keep no register of erasures, for privacy reasons.",
            "answer": "A list of identifiers with a date is less data than the records it stops from returning, and it is the only way the promise can be kept."
          },
          {
            "objection": "It is a rare edge case.",
            "answer": "It is measurable rather than rare: the backup cycle and the number of restores per year are both known inside the organisation."
          }
        ]
      },
      "related": [
        "DPE-2026-0004",
        "DPE-2026-0034"
      ],
      "in_practice": {
        "dpia": "Verify what happens to backups on an erasure and whether a restore re-applies past erasures, instead of recording that erasure is supported.",
        "procurement": "The supplier states in writing how an erasure survives a restore, and demonstrates it on a test restore at delivery.",
        "complaint": "The erasure confirmation, the written answer about backups, and the backup cycle set against the retention period.",
        "audit_question": "You restore last month's backup tonight. Which erased records are back tomorrow?",
        "audit_question_nl": "U zet vanavond de back-up van vorige maand terug. Welke gewiste gegevens staan er morgen weer in?",
        "complaint_nl": "De bevestiging van het wisverzoek, het schriftelijke antwoord over back-ups, en de back-upcyclus naast de bewaartermijn.",
        "objection_nl": "Een back-up kun je niet aanpassen, dat is het idee van een back-up.",
        "answer_nl": "Dat hoeft ook niet. Gevraagd is dat het wissen een herstel overleeft, en daarvoor bestaat een lijst met wisopdrachten die na herstel opnieuw wordt toegepast."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0036",
      "name": "Per-person productivity scoring at work",
      "slug": "per-person-productivity-scoring",
      "name_nl": "Productiviteitsmeting per medewerker",
      "family": "data",
      "applies_to": [
        "desktop",
        "web",
        "mobile-app"
      ],
      "summary": "Work software records activity per person per interval and turns it into a figure about that person.",
      "summary_nl": "Werksoftware legt activiteit per persoon per tijdvak vast en maakt daar een cijfer over die persoon van.",
      "not_a_vulnerability": "Nothing is exploited. The software was bought to do this, it is installed by the employer, and the objection is to what it records rather than to a defect in it.",
      "mechanism": {
        "what": "Software on the work device or in the work account records what the person does at intervals: which application is in the foreground, whether keyboard or mouse moved, how long a window was idle, how many messages or tickets were handled in an hour. The rows are attributable to a named worker and are stored per interval rather than per day. A figure follows from them, a score, a percentage or a ranking, which a manager sees and which is used in conversations about the person.",
        "why_it_matters": "Employment is a relationship in which refusing costs something, so consent is not available as a basis and necessity has to carry it. Being measured minute by minute changes what people do: it rewards visible presence over work, and it turns a break, a disability or care at home into a dip that has to be explained. The worker usually cannot see their own rows while the manager can.",
        "common_causes": [
          "a feature enabled by default in remote-work or endpoint software",
          "aggregate reporting bought, per-person reporting delivered in the same product",
          "an interval left at the product default instead of set to the coarsest that serves the purpose",
          "a pilot for one team that stayed on for everyone"
        ],
        "not_this": "A measurement series from a device in the home that reveals occupancy is Reporting interval that reveals occupancy, where the subject is a household and the party a supplier. Images of what is on the worker's screen are Screen capture of a worker's device: this entry counts activity, that one records content. A figure about a team that cannot be resolved to a person is not this entry."
      },
      "detection": {
        "indicator": "The product's own output contains rows attributable to one named worker at an interval shorter than a working day: a timestamp, an identifier of the person, an activity value. Establish it from the administrator's view or from the worker's own access request, not from the product description or the dashboard.",
        "method": "document-comparison",
        "qod": 85,
        "capture_requirements": [
          "ask for the records of one person over one day, in the form the product exports them",
          "record the interval, and whether the worker can see the same rows",
          "record whether the figure is used in any assessment, and where that use is written down",
          "note the difference between what the dashboard shows as an aggregate and what is stored per person; the storage is the finding"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "The stored records cannot be resolved to a person, and the export shows totals per team only.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The activity value is produced by the worker's own action, such as time they book themselves.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The worker sees the same rows at the same interval and can correct them.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The measurement runs for a bounded investigation with a stated ground and an end date.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "A targeted investigation is a different processing from permanent measurement of everyone, and it is written down somewhere."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-88",
          "nl-wor-27",
          "eu-gdpr-22"
        ],
        "rebuttals": [
          {
            "objection": "The employees agreed to it.",
            "answer": "In a relationship of authority consent is rarely free, because refusing costs something. That is why the discussion runs over necessity and over the works council rather than over a signature."
          },
          {
            "objection": "We only look at team totals.",
            "answer": "Then the storage should be team totals. A per-person row that exists can be looked at, and will be as soon as there is a reason to look."
          },
          {
            "objection": "It is our equipment.",
            "answer": "Owning the device settles who may install software on it, not what may be recorded about the person using it."
          },
          {
            "objection": "The system does not decide anything, a manager does.",
            "answer": "Where the manager sees the score and not the work, the system did the selecting. What has to be shown is what the manager had in front of them."
          }
        ]
      },
      "related": [
        "DPE-2026-0022",
        "DPE-2026-0037",
        "DPE-2026-0038"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify what the product stores per person per interval, rather than what the dashboard shows the manager.",
        "procurement": "The product stores no per-person activity row at an interval shorter than the reporting the purpose requires, and the worker can see their own rows.",
        "complaint": "The export of one worker's rows for one day, the interval, and the works council decision if there is one.",
        "audit_question": "Show me one day of one employee, in the form the system stores it.",
        "audit_question_nl": "Laat een dag van een medewerker zien, zoals het systeem het opslaat.",
        "complaint_nl": "De uitdraai van een dag van een medewerker met het tijdvak per regel, en het instemmingsbesluit van de ondernemingsraad als dat er is.",
        "objection_nl": "De medewerkers hebben ermee ingestemd.",
        "answer_nl": "In een gezagsverhouding is toestemming zelden vrij. Het gesprek gaat over noodzaak en over de ondernemingsraad, niet over een handtekening."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0037",
      "name": "Screen capture of a worker's device",
      "slug": "screen-capture-of-a-worker",
      "name_nl": "Schermopname op het werkapparaat",
      "family": "data",
      "applies_to": [
        "desktop",
        "web",
        "mobile-app"
      ],
      "summary": "Work software records the screen itself, on a timer or a trigger, without the worker starting it.",
      "summary_nl": "Werksoftware neemt het scherm zelf op, met vaste tussenpozen of op een signaal, zonder dat de medewerker dat start.",
      "not_a_vulnerability": "Nothing is exploited. The agent takes the images because it was configured to, and the objection is to the configuration rather than to a defect.",
      "mechanism": {
        "what": "The device produces images of the screen, or a stream of it, on a timer or on a trigger such as a keyword, an application coming to the foreground, or a score crossing a threshold. The image holds everything that was visible: the work, but also a private message in another window, a colleague's data, a document belonging to a client, a password manager at the moment it was open. The images are stored centrally and can be opened by someone other than the person captured.",
        "why_it_matters": "A screenshot is not a measurement about the worker alone. It captures whatever was on the screen, including data about clients, patients and colleagues who have no relationship with the monitoring at all, and it captures the private moments that occur on any device used all day. The worker cannot see when a capture is taken, and cannot know afterwards which ones exist.",
        "common_causes": [
          "a screenshot feature bundled with time tracking and enabled as delivered",
          "a trigger list that fires far more often than the incident it was bought for",
          "recordings kept for months although the review they serve happens the same week",
          "an agent rolled out for one team and left running on the standard image"
        ],
        "not_this": "Counting activity per person is Per-person productivity scoring at work: that records how much, this records what. Recording a visitor's session on a website is Session recording, which is bounded by the page; a screen capture is bounded by nothing that was open."
      },
      "detection": {
        "indicator": "Image or video records of the worker's screen exist in the product's store, produced at a moment when the worker performed no action to produce them. Establish it from the administrator's view, from the worker's own access request, or from the files the agent writes locally, and count them per hour.",
        "method": "document-comparison",
        "qod": 85,
        "capture_requirements": [
          "ask for the images of one hour of one person and record how many there are",
          "record what triggers a capture, and whether the worker is told at the moment it happens",
          "record what is visible in the images besides the work: other applications, other people's data",
          "record the retention of the image store separately from the retention of the activity records"
        ],
        "attribution": [
          "document-diff",
          "process-trace"
        ]
      },
      "falsifiers": [
        {
          "condition": "Every capture is started by the worker, for instance to attach evidence to a ticket.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The stored image is reduced before storage to a form in which no content is readable.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "Check a stored image rather than the setting that claims to do it."
        },
        {
          "condition": "Capture runs only during a bounded investigation with a stated ground, and the worker was told.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The device serves one task and nothing else can appear on the screen.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-5-1-e",
          "eu-gdpr-88",
          "nl-wor-27"
        ],
        "rebuttals": [
          {
            "objection": "It is only for security incidents.",
            "answer": "Then it runs during an incident. A capture that runs continuously is not an investigation but a standing recording, and the difference is visible in the number of images per hour."
          },
          {
            "objection": "Nobody looks at the images.",
            "answer": "They exist, they are readable, and the retention says how long that stays true. What is looked at is not the measure."
          },
          {
            "objection": "Employees know it happens.",
            "answer": "Knowing is not the same as necessary, and it does nothing for the clients and colleagues whose data is in the frame and who were told nothing."
          },
          {
            "objection": "The worker can pause it during breaks.",
            "answer": "Test that, and check the store for the period it was paused. A pause that stops the display and not the capture is the finding rather than the answer to it."
          }
        ]
      },
      "related": [
        "DPE-2026-0005",
        "DPE-2026-0036"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify how many images of one person exist for one hour and what else is visible in them, rather than the sentence that screenshots are possible.",
        "procurement": "The product produces no screen image unless the worker starts it, or capture is bounded to a stated investigation with an end date.",
        "complaint": "The number of images per hour for one worker, a sample in which third-party data is visible, and the retention of the image store.",
        "audit_question": "How many pictures of my screen were taken this hour, and who can open them?",
        "audit_question_nl": "Hoeveel opnamen van mijn scherm zijn er dit uur gemaakt, en wie kan die openen?",
        "complaint_nl": "Het aantal opnamen per uur van een medewerker, een voorbeeld waarop gegevens van derden zichtbaar zijn, en de bewaartermijn van die opslag.",
        "objection_nl": "Het is alleen voor beveiligingsincidenten.",
        "answer_nl": "Dan draait het tijdens een incident. Een opname die permanent doorloopt is geen onderzoek maar een doorlopende registratie."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0038",
      "name": "Vehicle tracked outside working hours",
      "slug": "vehicle-tracked-outside-hours",
      "name_nl": "Dienstvoertuig gevolgd buiten werktijd",
      "family": "data",
      "applies_to": [
        "vehicle",
        "iot",
        "mobile-app"
      ],
      "summary": "A tracking unit keeps recording position when the vehicle is out of service, with no working way to mark private use.",
      "summary_nl": "Een volgsysteem blijft posities vastleggen als het voertuig buiten dienst is, zonder werkende manier om privegebruik aan te geven.",
      "not_a_vulnerability": "Nothing is exploited. The unit reports because that is what it was fitted to do, and the objection is to the period it covers rather than to a defect in it.",
      "mechanism": {
        "what": "A tracking unit reports position, speed and ignition state at a fixed interval for as long as it has power. The purpose given for it, planning, theft recovery, mileage administration, concerns the vehicle in service. The unit knows nothing about shifts, so it records the drive home, the weekend, the pharmacy and the address where the driver sleeps. Where a private-use control exists it is often not fitted on the installed model, switched off in the fleet configuration, or it hides the track in the interface while the records keep arriving.",
        "why_it_matters": "A position series over weeks is among the most revealing records there is. It shows where someone lives, who they visit and when they are away from home, and it does so for everyone else in the vehicle as well. The driver cannot see the record, cannot switch off the unit, and often has no other car.",
        "common_causes": [
          "a unit with a fixed reporting interval and no awareness of shifts",
          "the private-use control not fitted, or fitted and disabled in the fleet configuration",
          "a private-use mode that hides the track for the manager while the records are stored",
          "an interval chosen for theft recovery applied to normal operation"
        ],
        "not_this": "A device reporting at an interval that reveals when a house is empty is Reporting interval that reveals occupancy, where the subject is a household. A vehicle sending data to its manufacturer with no function behind it is Device telemetry without function. This entry is about the employment relationship and the boundary of the shift: records exist about time that is not the employer's."
      },
      "detection": {
        "indicator": "Position records exist with timestamps outside the driver's recorded working hours, in the fleet system's own export or in the driver's access request. Where a private-use mode exists, records for the same period exist after it was switched on. The roster and the export are compared row by row.",
        "method": "document-comparison",
        "qod": 85,
        "capture_requirements": [
          "ask for the records of one vehicle over one week, with timestamps, and the roster for the same week",
          "test the private-use control if there is one, and ask for the records of the period during which it was on",
          "record the interval and whether periods with the ignition off are reported as well",
          "record who in the organisation can see the track and how long it is kept"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "A private-use mode exists and no records for that period appear in the export.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "Only ignition events are recorded outside the shift, without position.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The vehicle may not be used privately and does not leave the site outside working hours, which the records themselves show.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The record outside working hours is limited to what a theft alert needs and is destroyed when no alert follows.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-5-1-b",
          "eu-gdpr-88",
          "nl-wor-27"
        ],
        "rebuttals": [
          {
            "objection": "It is our vehicle.",
            "answer": "Owning the vehicle settles what may be driven in it, not what may be recorded about the person driving. Outside the shift, the time is not the employer's."
          },
          {
            "objection": "It is for theft recovery.",
            "answer": "Theft recovery needs a position when a vehicle is reported stolen. A permanent series in a database is a different processing with a different retention, and the two can be told apart in the export."
          },
          {
            "objection": "The driver can switch it off.",
            "answer": "Test it, and ask for the records of the period it was off. A mode that hides the track in the interface while the records keep arriving is the finding, not the refutation."
          },
          {
            "objection": "We need it for the mileage administration.",
            "answer": "That needs distances per trip, which is a coarser record than a position every minute, and it needs nothing at all on days the vehicle was not in service."
          }
        ]
      },
      "related": [
        "DPE-2026-0012",
        "DPE-2026-0022",
        "DPE-2026-0036"
      ],
      "in_practice": {
        "dpia": "Verify the export of one vehicle for one week against the roster, instead of the statement that tracking is for business use.",
        "procurement": "The unit records no position outside service, or a private-use mode is fitted, works, and suppresses the record rather than the display.",
        "complaint": "The position export for one week, the roster for the same week, and the written answer about the private-use mode.",
        "audit_question": "Show me the track of one vehicle for a Sunday.",
        "audit_question_nl": "Laat de registratie van een voertuig zien voor een zondag.",
        "complaint_nl": "De uitdraai met posities over een week, het rooster van dezelfde week, en het antwoord over de privestand.",
        "objection_nl": "Het is onze auto.",
        "answer_nl": "Eigendom van de auto zegt wat ermee gereden mag worden, niet wat er over de bestuurder mag worden vastgelegd buiten diensttijd."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0039",
      "name": "Exam supervision by behavioural scoring",
      "slug": "exam-supervision-scoring",
      "name_nl": "Examentoezicht met gedragsscores",
      "family": "data",
      "applies_to": [
        "web",
        "desktop",
        "mobile-app"
      ],
      "summary": "Exam software watches body, sound and screen, and a per-student suspicion record outlives the result.",
      "summary_nl": "Examensoftware kijkt naar lichaam, geluid en scherm, en houdt per student een verdenkingsregistratie over na de uitslag.",
      "not_a_vulnerability": "Nothing is exploited and the software works as sold. The objection is to what it observes and to what remains of it, not to a defect.",
      "mechanism": {
        "what": "During an examination the software watches through the camera and the microphone and over the screen: face position, gaze direction, a second face in the frame, sound in the room, windows opened, typing rhythm. From that it derives flags or a score for each student. The recording and the derived judgement are stored, reviewed by staff or by the supplier, and kept after the examination has been graded. An identity step by face comparison often precedes it.",
        "why_it_matters": "The student sits at home and cannot decline without failing the course. What is recorded includes the room, the people in it and the sounds of a household. A score derived from body movement is a judgement about a person that the person has to argue against, produced by a system that does not explain itself, and where a face is compared the processing is biometric identification.",
        "common_causes": [
          "a supplier product with flagging enabled as delivered",
          "recordings kept for the appeal period for every student rather than for the flagged ones",
          "the identity step performed by face comparison because the alternative requires staff",
          "flags treated as evidence rather than as a prompt for a human to look"
        ],
        "not_this": "Recording a website session is Session recording. Recognising everyone who passes a camera is Recognition of every passer-by, where the setting is a public space. This entry is about a compulsory examination: the observation concerns one identified student, it produces a judgement about that student, and it outlives the result."
      },
      "detection": {
        "indicator": "After the mark is final, records about individual students still exist: the recording, the derived flags, or a score. Establish it from the institution's retention schedule for this system, from the supplier's export, or from a student's access request that returns their own flags, and distinguish the three.",
        "method": "document-comparison",
        "qod": 85,
        "capture_requirements": [
          "ask what remains per student after grading, distinguishing recording, flags and score",
          "ask which of the three the student can see, and whether they were told about the score at the time",
          "record whether the identity step compares a face, and against which source",
          "record whether an alternative to the software was offered, in the same period, and what it cost the student"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "Nothing per student survives grading except the mark itself.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "A human invigilator watched live and nothing was recorded or scored.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "Only sessions a human flagged are kept, with a stated ground and an end date.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "A genuine alternative was available in the same period, without a penalty and without a separate fee.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "The compulsion argument then falls. The observation itself still has to be necessary for the purpose."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-5-1-e",
          "eu-gdpr-22",
          "eu-gdpr-9-1"
        ],
        "rebuttals": [
          {
            "objection": "The student agreed to the examination conditions.",
            "answer": "Agreeing under threat of not graduating is not free consent, which is why examinations run on a public task or a contract and have to satisfy necessity instead."
          },
          {
            "objection": "The system does not decide, a person does.",
            "answer": "Where that person sees only the flags the system produced, the system did the selecting. What has to be shown is what the reviewer had in front of them besides the score."
          },
          {
            "objection": "The camera image is deleted immediately.",
            "answer": "Then the flags derived from it are the record, and the question moves to them. Ask what remains, not what is deleted."
          },
          {
            "objection": "Fraud has to be prevented.",
            "answer": "It does, and that is a purpose. It does not settle the interval, the room, the retention or the score, each of which is a separate choice that can be made differently."
          }
        ]
      },
      "related": [
        "DPE-2026-0005",
        "DPE-2026-0024"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify what remains per student after grading, recording, flags and score separately, instead of the supplier's statement that data is deleted after the exam.",
        "procurement": "After grading, nothing per student remains beyond the mark, except sessions flagged by a human with a stated ground and an end date.",
        "complaint": "The retention schedule for this system, the student's own flags from an access request, and the answer about whether an alternative was offered.",
        "audit_question": "The exam is graded. What still exists about a student nobody flagged?",
        "audit_question_nl": "Het examen is nagekeken. Wat bestaat er dan nog over een student bij wie niets is opgemerkt?",
        "complaint_nl": "De bewaartermijn van dit systeem, de eigen scores uit een inzageverzoek, en het antwoord of er een alternatief was.",
        "objection_nl": "De student ging akkoord met de examenvoorwaarden.",
        "answer_nl": "Akkoord gaan onder dreiging van niet afstuderen is geen vrije toestemming. Daarom loopt dit over noodzaak, niet over toestemming."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0040",
      "name": "Pay or accept as the only choice",
      "slug": "pay-or-accept-only-choice",
      "name_nl": "Betalen of accepteren als enige keuze",
      "family": "consent",
      "applies_to": [
        "web",
        "mobile-app"
      ],
      "summary": "The first screen offers payment or consent to third-party purposes, and no path that refuses and still reaches the content.",
      "summary_nl": "Het eerste scherm biedt betalen of instemmen met doelen van derden, en geen pad dat weigert en toch bij de inhoud komt.",
      "not_a_vulnerability": "Nothing is broken. The wall is the product decision, stated openly, and the objection is to the choice it leaves.",
      "mechanism": {
        "what": "Before any content is shown, the visitor is offered two ways forward: pay for a subscription, or accept processing for advertising and measurement by third parties. There is no third path. A refusal exists on paper, and that is what the payment is for, but exercising it costs money and the price is set by the party asking for the consent.",
        "why_it_matters": "Consent has to be free, and here it is weighed against access to information. The people for whom the price is real are the ones with the least room to refuse, so the arrangement buys consent from those who can least afford to withhold it. And the choice returns on every site, which no household budget survives.",
        "common_causes": [
          "a subscription introduced as the alternative that is supposed to make the consent free",
          "an advertising operation that cannot run without the third-party purposes, so no third path is designed",
          "a price set at the level of a full subscription rather than at the value of the advertising it replaces",
          "the paid tier keeping some of the same purposes, which is only visible in a capture"
        ],
        "not_this": "A banner with no refusal control at all is No refusal option: here a refusal exists and it has a price. A refusal that changes nothing in the traffic is Refusal without effect: here the refusal works, and the question is whether it was free."
      },
      "detection": {
        "indicator": "On the first screen the paths that reach the content are exactly two: one that registers a positive consent state for third-party purposes, and one that requires payment. No control reaches the content with a negative consent state registered. Establish it by taking every path from a clean profile and recording the resulting state.",
        "method": "differential",
        "qod": 90,
        "capture_requirements": [
          "clean profile, no interaction before the wall appears",
          "walk every layer reachable from the first screen, including screens behind a link or a small control",
          "record the price, and which purposes the paid path still permits; a paid tier that keeps third-party purposes is part of the finding",
          "record the country the capture egressed from, because the wall is often shown to some regions only"
        ],
        "attribution": [
          "har-pageref"
        ]
      },
      "falsifiers": [
        {
          "condition": "A third path exists that reaches the content with a refusal registered, however unattractive it is made.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The wall covers part of the offering while the rest is reachable without either choice.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The accepting path registers a refusal for third-party purposes and permits only the operator's own.",
          "checkable": "automated",
          "if_true": "reclassify",
          "note": "The choice is then between paying and being measured by the operator itself, which is a narrower question than this entry."
        },
        {
          "condition": "The paid path is free of the third-party purposes and the price is stated before the choice is made.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "This does not dispose of the freedom question, but it removes the compounding one, where paying buys nothing."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-7-4",
          "eu-gdpr-6-1-a",
          "nl-tw-11-7a"
        ],
        "rebuttals": [
          {
            "objection": "Nobody is forced; there is a paid alternative.",
            "answer": "That is the point at issue. Refusing then costs money, and consent has to be free of exactly that weighing."
          },
          {
            "objection": "Journalism has to be paid for.",
            "answer": "It does, and a subscription is a lawful way to do it. What is at issue is the pairing: the price is set against the consent rather than against the advertising revenue the consent produces."
          },
          {
            "objection": "Supervisory authorities have accepted this model.",
            "answer": "Positions differ per authority and are moving. Cite the position of the authority competent for the party, with its date. The measurement is the same whatever that position becomes."
          },
          {
            "objection": "The paid tier has no advertising.",
            "answer": "Testable in a capture of the paid path. Where third-party purposes persist behind the payment, the two options collapse into one."
          }
        ]
      },
      "related": [
        "DPE-2026-0002",
        "DPE-2026-0003"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify how many paths reach the content and which consent state each one registers, rather than the statement that visitors have a choice.",
        "procurement": "A path exists to the content with third-party purposes refused, without payment, and it is reachable from the first screen.",
        "complaint": "A capture of the first screen, every path taken separately with the consent state that followed, and the price of the paid path.",
        "audit_question": "Show me the way to your article for someone who refuses and does not pay.",
        "audit_question_nl": "Laat me zien hoe iemand bij uw artikel komt die weigert en niet betaalt.",
        "complaint_nl": "Een opname van het eerste scherm, elk pad afzonderlijk gelopen met de toestemmingsstand die eruit volgt, en de prijs van het betaalde pad.",
        "objection_nl": "Niemand wordt gedwongen, er is een betaald alternatief.",
        "answer_nl": "Dat is juist het punt. Weigeren kost dan geld, en toestemming moet vrij zijn van die afweging."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0041",
      "name": "Input kept as training data by default",
      "slug": "input-kept-as-training-data",
      "name_nl": "Invoer wordt standaard trainingsmateriaal",
      "family": "data",
      "applies_to": [
        "web",
        "mobile-app",
        "api",
        "desktop"
      ],
      "summary": "What a person types into a service is retained to improve a model unless they find a setting and switch it off.",
      "summary_nl": "Wat iemand in een dienst typt, wordt bewaard om een model te verbeteren, tenzij hij een instelling vindt en uitzet.",
      "not_a_vulnerability": "Nothing is taken by force. The second use is written down somewhere and the control exists, and the objection is that the default answers for the person.",
      "mechanism": {
        "what": "A service accepts text, images or files in order to answer, and keeps them afterwards for a second purpose: improving a model, evaluating quality, or review by people. A control that prevents it exists, but it stands at on when the account is created, sits several steps from the input screen, applies only to what is submitted after it is changed, or is offered on a paid tier only. At the moment of typing the person is told nothing about the second purpose.",
        "why_it_matters": "People put things into these services that they put nowhere else: a draft resignation, a medical letter, a client file, a message about a family member. Kept as training material, that content leaves the person's reach altogether. It cannot be found back, cannot be corrected, and cannot be removed from what has been built on it.",
        "common_causes": [
          "retention for improvement on by default, with an opt-out per account",
          "a business tier excluded from training while the free tier is not, without that being visible at the moment of typing",
          "review by people described as a security measure rather than as a second purpose",
          "an application built on another party's model, passing content on under that party's default terms"
        ],
        "not_this": "Content reaching an advertising or measurement party is User input to third parties, where the content is a by-product. Here it is the payload, and the fault is the second use of it. A store that writes the payload into a log is Logs recording content, not events, which is about the operator's own housekeeping rather than a second purpose."
      },
      "detection": {
        "indicator": "In an account created for the test and left untouched, the control governing use of input for model improvement or review by people stands at on, and the terms of the same date state that submitted content is used for that purpose. Both are read as delivered, before anything is changed.",
        "method": "document-comparison",
        "qod": 90,
        "capture_requirements": [
          "a fresh account, nothing changed, and a record of the default state with the date and the version",
          "record where the control sits and how many steps it is from the input screen",
          "record whether switching it off also covers what was already submitted",
          "record whether a paid tier differs, and whether that difference is visible at the moment of typing"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "The default stands at off and the person has to switch it on.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "Submitted content is used to produce the answer and is destroyed within a stated short period.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "Switching the control off also removes what was submitted before.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The operator does not retain it; the content is passed to another party under that party's terms.",
          "checkable": "manual",
          "if_true": "reclassify",
          "note": "The recipient is then the party to address, and the operator's silence about it is a transparency finding."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-b",
          "eu-gdpr-25",
          "eu-gdpr-6-1-a"
        ],
        "rebuttals": [
          {
            "objection": "It is in the terms.",
            "answer": "A second purpose has to be clear at the moment of typing, and the default has to be the protective one. A term accepted once at sign-up is not a choice per submission."
          },
          {
            "objection": "The data is anonymised before training.",
            "answer": "Free text is not anonymised by removing a name; it identifies through its content. And what is being examined is what is retained, not what may be filtered later."
          },
          {
            "objection": "You can switch it off.",
            "answer": "The finding is the default, not the possibility. A control that has to be found is a control most people never reach."
          },
          {
            "objection": "Reviewers only see fragments.",
            "answer": "A fragment of a medical letter is a medical letter. The unit of review does not change the category of the content."
          }
        ]
      },
      "related": [
        "DPE-2026-0006",
        "DPE-2026-0034"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify the default state of the control in a fresh account, and whether switching it off works backwards, instead of the supplier's statement that customer data is not used for training.",
        "procurement": "Content submitted by users is used to produce the answer and for nothing else, demonstrated by the default state of a fresh account and the terms of the same date.",
        "complaint": "A screenshot of the default state in a fresh account with its date, and the passage in the terms describing the second purpose.",
        "audit_question": "In a new account, is the training setting on or off, and what happens to what I already typed if I switch it off?",
        "audit_question_nl": "Staat de instelling voor trainen in een nieuw account aan of uit, en wat gebeurt er met wat ik al typte als ik hem uitzet?",
        "complaint_nl": "Een schermafdruk van de standaardinstelling in een vers account met datum, en de passage in de voorwaarden over het tweede doel.",
        "objection_nl": "Het staat in de voorwaarden.",
        "answer_nl": "Het tweede doel moet duidelijk zijn op het moment van typen, en de standaard hoort de beschermende te zijn."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0042",
      "name": "Extension permissions beyond its function",
      "slug": "extension-permissions-beyond-function",
      "name_nl": "Uitbreiding vraagt meer rechten dan haar functie",
      "family": "data",
      "applies_to": [
        "web",
        "desktop"
      ],
      "summary": "An add-on declares access to every page while the function it describes concerns a handful of them.",
      "summary_nl": "Een uitbreiding claimt toegang tot alle paginas terwijl de functie die zij beschrijft over een handvol sites gaat.",
      "not_a_vulnerability": "Nothing is bypassed: the browser grants exactly what the package declares. The objection is to the distance between that declaration and the function it was installed for.",
      "mechanism": {
        "what": "An extension declares in its package which hosts it may read and change and which interfaces it may use. That declaration is what the browser enforces; the description in the listing is what the person reads. Where the declaration covers every host, or browsing history, or the contents of all pages, while the described function operates on a named handful of sites, the extension can read everything the person does in the browser, including what sits behind a login, because it runs inside the session.",
        "why_it_matters": "An extension sits where no website reaches: after decryption, inside the account, on every tab. Access granted once persists silently across updates, and an extension can change owner without asking again. The person granted it for a function and cannot see what is read, because reading leaves no trace.",
        "common_causes": [
          "a broad host pattern declared during development and never narrowed",
          "one permission set covering several features, including ones this person never uses",
          "a bundled library requiring a permission the extension itself does not need",
          "an extension sold or transferred, keeping the permissions it already had"
        ],
        "not_this": "A page reading device characteristics is Device fingerprinting. A component inside an application that collects on its own account is Bundled component collection, which is established from observed traffic. This entry is about declared access, which exists whether or not anything has been sent yet."
      },
      "detection": {
        "indicator": "The permission declaration in the published package covers hosts beyond those the listing describes the function as operating on: a pattern matching every host, or access to browsing history or to the contents of all pages, set against a description naming a bounded set. Both documents belong to the publisher; the researcher only does the set comparison.",
        "method": "static-source",
        "qod": 90,
        "capture_requirements": [
          "read the declaration from the published package, not from a repository that may differ from what is shipped",
          "record the version, the date, and the listing text of the same date",
          "record permissions requested at runtime separately from those declared at install",
          "check whether the publisher offers a narrower variant that the person could have installed instead"
        ],
        "attribution": [
          "document-diff"
        ]
      },
      "falsifiers": [
        {
          "condition": "The described function does operate on every site.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The broad access is requested at runtime, when the person uses the extension on a site, and can be refused per site.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The listing describes the broader function plainly, on the screen where the person installs it.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "The declaration is broad and the shipped code demonstrably operates on the named hosts only.",
          "checkable": "manual",
          "if_true": "weaken",
          "note": "The access still exists and survives every update. The finding is about what is granted, and it is worth saying that the current release does not use it."
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-c",
          "eu-gdpr-25",
          "nl-tw-11-7a"
        ],
        "rebuttals": [
          {
            "objection": "The browser shows the permissions at install.",
            "answer": "Once, in a sentence, next to a description that says something else. The comparison between those two is exactly the finding."
          },
          {
            "objection": "We do not use the access we have.",
            "answer": "Access is what can be checked; use is not, and it changes with every release without anyone being asked again."
          },
          {
            "objection": "Every extension asks for this.",
            "answer": "That is a statement about the ecosystem, not about necessity. A narrower pattern is available in the same interface and costs one line."
          },
          {
            "objection": "The store reviewed and approved it.",
            "answer": "A review checks the package against the store's rules. It does not establish that the access is necessary for the function the person installed it for."
          }
        ]
      },
      "related": [
        "DPE-2026-0007",
        "DPE-2026-0013"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify the permission declaration of the shipped package against the described function before approving an extension for managed devices.",
        "procurement": "Extensions on managed devices declare host access limited to the sites the function operates on, checked again per version.",
        "complaint": "The declaration from the published package, the listing text of the same date, and the version number of both.",
        "audit_question": "Which sites can this extension read, and which sites does it say it works on?",
        "audit_question_nl": "Welke sites mag deze uitbreiding lezen, en op welke sites zegt zij te werken?",
        "complaint_nl": "De rechtenverklaring uit het gepubliceerde pakket, de omschrijving in de winkel van dezelfde datum, en het versienummer van allebei.",
        "objection_nl": "De browser laat bij het installeren zien welke rechten er zijn.",
        "answer_nl": "Een zin, een keer, naast een omschrijving die iets anders zegt. Het verschil tussen die twee is de bevinding."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    },
    {
      "id": "DPE-2026-0043",
      "name": "Registers joined on a person number",
      "slug": "registers-joined-on-person-number",
      "name_nl": "Registraties gekoppeld op persoonsnummer",
      "family": "chain",
      "applies_to": [
        "api",
        "web",
        "desktop"
      ],
      "summary": "Records collected under one statutory task are joined to another body's records on the statutory number.",
      "summary_nl": "Gegevens die voor de ene wettelijke taak zijn verzameld, worden op het persoonsnummer gekoppeld aan die van een andere instantie.",
      "not_a_vulnerability": "Nothing is broken into. The bodies exchange deliberately, usually under an arrangement they wrote themselves, and the objection is to the combination rather than to a defect.",
      "mechanism": {
        "what": "Two public bodies each hold records for their own statutory purpose. The statutory personal number makes joining them trivial, so a file, a query facility or a shared environment comes into being in which records from both sit next to each other about the same person. The combination answers questions neither register was created for. The person sees only the outcome: a check, a selection, a decision that draws on information they gave somewhere else.",
        "why_it_matters": "Each register was justified separately and the combination was justified nowhere. A person cannot see which body drew on which source, cannot correct a record at the body that used it, and cannot avoid the number, because it is assigned to them. The combined set then becomes the reason to keep data longer, share it further and select on it.",
        "common_causes": [
          "a sharing arrangement made between bodies without a provision naming the combination",
          "a joint environment for detection or enforcement, fed from several registers",
          "one supplier delivering the same platform to both bodies, with the join as a feature",
          "a provision that permits the delivery of one register, read as covering the combination"
        ],
        "not_this": "A statutory number reaching a party with no statutory task is Statutory identification number to a third party, where the recipient should not hold it at all. Here both bodies may hold the number, and the fault is the joining of records collected for different purposes. Two commercial parties matching identifiers is Identifier synchronisation between parties."
      },
      "detection": {
        "indicator": "An access request to one body returns fields that only the other body collects, or the body's own processing register names a source it does not collect itself. Both are documents the body publishes or must supply, and the comparison is a set difference on the fields.",
        "method": "document-comparison",
        "qod": 80,
        "capture_requirements": [
          "make the access request at both bodies and compare the answers field by field",
          "read the processing register entry of the same date, including the sources named in it",
          "ask which provision names the combination, not the provision that names the register",
          "record whether the combination is held in a separate environment, and who administers that environment"
        ],
        "attribution": [
          "document-diff",
          "vendor-statement"
        ]
      },
      "falsifiers": [
        {
          "condition": "A provision names the combination itself, with its purpose and its retention.",
          "checkable": "manual",
          "if_true": "drop",
          "note": "The discussion then moves to whether the practice stays inside that provision, which is a different and more tractable question."
        },
        {
          "condition": "The receiving body collected the field itself, from the person.",
          "checkable": "manual",
          "if_true": "drop"
        },
        {
          "condition": "The exchange is a single answer to a single question, with nothing retained afterwards.",
          "checkable": "manual",
          "if_true": "weaken"
        },
        {
          "condition": "What was returned is a derived value, and the underlying record stayed with the body that holds it.",
          "checkable": "manual",
          "if_true": "weaken"
        }
      ],
      "legal": {
        "provisions": [
          "eu-gdpr-5-1-b",
          "nl-uavg-46",
          "eu-gdpr-5-1-a"
        ],
        "rebuttals": [
          {
            "objection": "Both bodies are allowed to use the number.",
            "answer": "For their own task, yes. The number is what makes the join cheap; it is not what makes it permitted. The provision has to name the combination."
          },
          {
            "objection": "It is all one government.",
            "answer": "Not in law. Each body has its own task and its own basis, and that separation is the reason a person can give information to one without giving it to all."
          },
          {
            "objection": "We only exchange what is necessary.",
            "answer": "Then the exchange answers a question and retains nothing. A stored combination is a different thing, and the two can be told apart by asking what is kept."
          },
          {
            "objection": "The person can request access, so it is transparent.",
            "answer": "Access is a right, not a justification. That the combination becomes visible when someone asks does not establish that it was permitted."
          }
        ]
      },
      "related": [
        "DPE-2026-0016",
        "DPE-2026-0017"
      ],
      "seen_in_the_wild": {
        "confirmed": false,
        "note": "Observed in practice by the authors but not yet backed by a published reference. Set to false until a citation exists: a claim without a source is exactly what this catalogue holds others to."
      },
      "in_practice": {
        "dpia": "Verify which provision names the combination, rather than the provisions that name each of the two registers.",
        "procurement": "A platform serving several bodies keeps their records separated, and a join requires a provision named per query and logged with it.",
        "complaint": "The access request answers from both bodies, the field that can only have come from the other, and the processing register entry of the same date.",
        "audit_question": "Which provision permits combining these two registers, as opposed to holding each of them?",
        "audit_question_nl": "Welke bepaling staat het koppelen van deze twee registraties toe, los van de bepalingen die elk register afzonderlijk toestaan?",
        "complaint_nl": "De antwoorden op inzageverzoeken bij beide instanties, het veld dat alleen van de ander kan komen, en het verwerkingsregister van dezelfde datum.",
        "objection_nl": "Beide instanties mogen het persoonsnummer gebruiken.",
        "answer_nl": "Voor hun eigen taak, ja. Het nummer maakt koppelen makkelijk, niet toegestaan. Er moet een bepaling zijn die de koppeling zelf noemt."
      },
      "schema_version": "2.0",
      "status": "active",
      "credit": [
        {
          "name": "Mick Beer",
          "role": "proposed",
          "date": "2026-07-26"
        }
      ],
      "does_not_establish": [
        "harm; the catalogue standardises a finding so it can be referred to, it does not weigh it",
        "severity; there is no score here, by design. Weighing belongs to whoever applies the entry to a concrete case",
        "unlawfulness; that is for a supervisory authority or a court",
        "intent; a fault is usually a build decision, not a plan",
        "absence: not finding it in one capture is not evidence that it is not there"
      ],
      "reproduction": {
        "methods": [
          {
            "tier": "manual",
            "path": "METHOD.md",
            "expect": "no dedicated reproduction exists yet; follow the general method and the indicator above"
          }
        ]
      },
      "changes": [
        {
          "at": "2026-07-26T00:00:00Z",
          "actor": "registry",
          "entries": [
            "Entry created.",
            "Name assigned.",
            "Detection method and falsifiers defined.",
            "Legal provisions linked."
          ]
        }
      ]
    }
  ]
}
