demo · v130

debug key leakage matrix

The chromestatus motivation: "if either a source or trigger debug key is specified then it will be included in the attribution report. This may lead to a privacy leak if third-party cookies are only allowed on either the publisher or the advertiser site but not both." The 2x2 matrix below lays out all four combinations and walks you through the cross-site identifier that pre-Chrome 130 leaked.

spec-rule walkthrough, no live API The fix is a behavior change inside Chrome — there is no JavaScript surface to call. This page is an interactive walkthrough of the pre/post rule for each combination of publisher and advertiser cookie state.
era:
debug key leaked (privacy gap) debug key included (intended) stripped (safe)
advertiser 3PC: ALLOWED
advertiser 3PC: BLOCKED
publisher 3PC:
ALLOWED
publisher 3PC:
BLOCKED

click a cell to walk through what would happen

why one-sided cookies leak

The Attribution Reporting API sends reports to the ad-tech's reporting origin from both the publisher site (during source registration) and the advertiser site (during trigger registration). Debug keys are 64-bit values the ad-tech chooses and registers in those requests. If the ad-tech can set its third-party cookies on only one of the two sites, it can read its real first-party identifier on that side, register a debug key derived from that identifier, then look for the debug key in the attribution report. That joins the identifier from one side to the activity on the other — exactly what the API was designed to prevent.

The Chrome 130 fix: debug keys are stripped from reports unless the reporting origin can prove it has third-party cookie access on both sides. If either side is cookie-blocked, the report still emits, but without the debug keys.

the rule

// Chrome 130+ inclusion rule:
const includeDebugKeys =
  hasArDebugCookie(sourceSite) &&
  hasArDebugCookie(triggerSite) &&
  !isCrossAppWebReport(report);

if (includeDebugKeys) {
  report.source_debug_key  = src.debug_key;
  report.trigger_debug_key = trg.debug_key;
}
// Otherwise, both fields are omitted — no partial leaks.

see also