Skip to content

Restrict Prebid Server forwarding to consent cookies - #1429

Open
prk-Jr wants to merge 9 commits into
mainfrom
fix/763-prebid-cookie-allowlist
Open

prk-Jr wants to merge 9 commits into
mainfrom
fix/763-prebid-cookie-allowlist

Conversation

@prk-Jr

@prk-Jr prk-Jr commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Restrict Prebid Server Cookie headers to euconsent-v2, __gpp, __gpp_sid, and us_privacy; omit the header in openrtb_only.
  • Match consent extraction's parsing and last-duplicate behavior. Normalize safe decimal GPP section whitespace and preserve unsafe-to-forward consent through JSON without forwarding unsafe cookie bytes.
  • In cookies_only, body fallback includes only the affected signal; GPP and section IDs travel together. Original consent gating and identity decisions use the unchanged complete context.

Changes

Files Change
crates/trusted-server-core/src/integrations/prebid.rs Shared consent-cookie selection and selective serialization fallback for both request builders.
crates/trusted-server-core/src/auction/{openrtb,orchestrator}.rs Apply fallback in production request construction and test every forwarding mode, unsafe TC/GPP/US values, duplicates, header framing, and body placement.
crates/trusted-server-core/src/cookies.rs Remove unused unrestricted forwarding and stripping helpers.
Cookie-forwarding/Prebid guides, architecture spec, technical plan, CHANGELOG Document actual forwarding surfaces, identity exceptions, and signal-specific fallback.

Closes

Closes #763

Spec

Not a feature. The issue specifies the policy. Technical plan: docs/superpowers/plans/2026-10-22-prebid-consent-cookie-allowlist.md.

Behavior decisions and review

A consent signal that cannot be safely framed as a cookie falls back to its JSON representation in cookies_only; unrelated safe signals stay cookie-only. GPP string and section IDs are one coupled signal, with required GDPR applicability metadata. Policy-sourced consent retains its existing body behavior. Unsafe raw bytes never bypass the header filter.

Production-path regressions cover unsafe euconsent-v2, GPP section IDs, and US Privacy values alongside safe unrelated signals. The regression first failed with the broad fallback, then passed with selective fallback. Fresh independent cookie and cross-PR reviews found no remaining actionable correctness issues.

Compatibility limitation: a receiving service must consume consent cookies for safe cookies_only signals. The standard PBS auction documentation specifies OpenRTB consent fields; it does not establish support for these four incoming consent cookies. This existing mode's compatibility with particular PBS deployments was not validated here. This PR preserves the mode rather than silently changing all safe consent to body forwarding.

Test plan

  • Full native core tests, integration tests, and doctests; 229 focused Prebid tests.
  • All five adapter test aliases, including reusable Fastly sandboxes.
  • Cross-adapter parity and native build-digest tests.
  • All eight clippy aliases, build-digest lint, Rust format, and diff checks.
  • 1,211 JS tests, JS format, and 13-module build.
  • Docs/outside-doc Markdown format, WASM clock lint, and documentation-proposal checks.
  • Optimized Fastly WASM build.
  • Independent cookie and cross-PR review.
  • Actual combined tree: 2,982 native core tests and 2,976 Viceroy core tests passed, plus integration suites and doctests.

Exploratory tsc --noEmit and whole-repository actionlint report pre-existing errors in unchanged files; they are not counted as passing checks. The changed workflows in #1433 pass scoped lint. Local verification uses Rust 1.98.1, Viceroy 0.21.0, and Node 24.12.0; the repository pins Node 24.20.0. No live PBS/browser validation was performed.

Checklist

  • Changes follow AGENTS.md conventions.
  • No Python code, secrets, customer data, new dependencies, or unsafe raw-cookie fallback.
  • Original consent context remains intact for enforcement.
  • Production serialization and malformed-input cases have regression coverage.

@prk-Jr prk-Jr self-assigned this Oct 22, 2026
@prk-Jr
prk-Jr marked this pull request as ready for review October 26, 2026 09:19

@ChristianPavilonis ChristianPavilonis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Restricts Prebid Server cookie forwarding to consent signals, with signal-specific JSON fallback while preserving the full consent context for enforcement.

@dhruv8sh dhruv8sh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This PR stops sending the browser's whole Cookie header to Prebid Server (PBS). In both and cookies_only mode, PBS gets only the four consent cookies; in openrtb_only, it gets no Cookie header at all. When a consent cookie can't be forwarded safely in cookies_only mode, just that one signal is sent in the OpenRTB body instead. The cookie parsing is the same as consent extraction's, so the two always pick the same values. This meets every acceptance criterion in #763. Tests run through the real request path and cover every mode, both consent sources, and the malformed-input cases. The outbound-cookie audit in the docs is a useful addition.

None of the inline comments below carries a one-click suggestion. Each fix is described in prose because it changes more than a single contiguous line range.

Non-blocking

🤔 thinking / ♻️ refactor

  • An unreadable Cookie header turns off the body fallback in cookies_only: see inline at crates/trusted-server-core/src/integrations/prebid.rs:2118
  • A panic on the request path if CONSENT_COOKIE_NAMES grows: see inline at crates/trusted-server-core/src/integrations/prebid.rs:2134

👍 praise

  • Tests go through the real request path for each consent signal: see inline at crates/trusted-server-core/src/auction/orchestrator.rs:6460

CI Status

All checks pass.

@aram356 aram356 added this to the 202611 milestone Oct 29, 2026
Retain existing consent through the JSON fallback when the Cookie header cannot be read. Replace the future allowlist mismatch panic with a warning and conservative fallback.

@aram356 aram356 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This PR limits the PBS Cookie header to the four consent cookies (and sends none in openrtb_only), and adds a per-signal JSON fallback for unsafe values in cookies_only. The routed production path builds the body fallback and the header from the same transport snapshot, and the header-byte tests are thorough. Three things need changes before merge. The CHANGELOG should mark the PBS uids/host-cookie loss as breaking. The GDPR applicability carried by a partial fallback has no test (four mutations survive the full core suite). And the new audit page misstates where EC IDs travel.

6 of the inline comments below carry a one-click GitHub suggestion. Use Commit suggestion, or Add suggestion to batch for several at once, to apply them as commits on the PR branch. The remaining comments describe the fix in prose because it touches lines outside the diff or more than one file. Each suggestion was applied alone to c7b89e8 and verified: the Rust ones with rustfmt, all six clippy aliases, all four adapter test aliases, and parity; the Markdown ones with the pinned prettier. All six applied together also pass rustfmt, clippy-fastly, and the native core suite.

Blocking

🔧 wrench

  • Flag the PBS uids/host-cookie loss as Breaking: see inline at CHANGELOG.md:31
  • Pin the GDPR applicability of a partial fallback (4 surviving mutations): see inline at crates/trusted-server-core/src/integrations/prebid.rs:10094
  • Audit page misstates EC ID sources, forward_ec_id, and omits pull sync: see inline at docs/guide/integrations/cookie-forwarding.md:58
  • Delete the now-unused strips_consent_cookies(): see inline at crates/trusted-server-core/src/consent_config.rs:134
  • Filter the cookie in the transport snapshot instead of at each reader: see inline at crates/trusted-server-core/src/auction/routing.rs:208
  • Add the audit page to the docs sidebar: see inline at docs/guide/integrations/cookie-forwarding.md:1
  • Proxy row describes header sets imprecisely: see inline at docs/guide/integrations/cookie-forwarding.md:49
  • CookiesLen is the selected header's length, not a total: see inline at docs/guide/integrations/cookie-forwarding.md:84
  • Split the shadowed let … else in from_header: see inline at crates/trusted-server-core/src/integrations/prebid.rs:2118

Non-blocking

📌 out of scope

  • cookies_only gives a standard PBS no usable consent: see inline at crates/trusted-server-core/src/consent_config.rs:136

CI Status

  • .github/dependabot.yml: PASS
  • Analyze (actions): PASS
  • Analyze (javascript-typescript): PASS (2 runs)
  • Analyze (python): PASS
  • Analyze (rust): PASS
  • browser integration tests: PASS
  • cargo check (cloudflare native + wasm32-unknown-unknown): PASS
  • cargo check/build/test (spin native + wasm32-wasip1): PASS
  • cargo fmt: PASS (required)
  • cargo test: PASS (required)
  • cargo test (axum native): PASS
  • cargo test (cross-adapter parity): PASS
  • cargo test (ts CLI, native) (macos-latest): PASS
  • cargo test (ts CLI, native) (ubuntu-latest): PASS
  • CI Node pin guard: PASS
  • CLAUDE.md symlink guard: PASS
  • CodeQL: PASS
  • docs-proposal scripts: PASS
  • format-docs: PASS (required)
  • format-typescript: PASS (required)
  • HTML EOF runtime (Fastly): PASS
  • integration tests: PASS
  • integration tests (Fastly EC lifecycle): PASS
  • prepare integration artifacts: PASS
  • ts dev lint domains (changed lines): PASS
  • vitest: PASS

Comment thread CHANGELOG.md Resolved
prk-Jr and others added 2 commits October 30, 2026 16:29
Store the consent-cookie selection in PrebidTransportHeaders instead of the
raw browser Cookie header, so publisher session and identity cookies are
never retained for the auction and both readers share one parse. Pin the
GDPR applicability carried by a partial cookies_only fallback, remove the
unused strips_consent_cookies helper, and split the shadowed let-else in
PrebidConsentCookies::from_header.

Correct the cookie-forwarding audit (EC ID sources, forward_ec_id, pull
sync, proxy header sets, CookiesLen), add it to the docs sidebar, update
the architecture spec snapshot contract, and flag the PBS uids/host-cookie
loss as breaking in the CHANGELOG.
@prk-Jr
prk-Jr requested a review from aram356 October 30, 2026 11:48

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ensure what cookie data is being forwarded to Prebid Server / 3rd party backends

4 participants