Skip to content

Use configured publisher domain for navigation-path auction requests#937

Open
aram356 wants to merge 2 commits into
mainfrom
fix/auction-request-publisher-host
Open

Use configured publisher domain for navigation-path auction requests#937
aram356 wants to merge 2 commits into
mainfrom
fix/auction-request-publisher-host

Conversation

@aram356

@aram356 aram356 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

On the navigation / SSAT proxy path, the server-side auction advertised the incoming request Host header — which on that path is the trusted-server edge host (e.g. the staging domain) — as the publisher domain. That value flowed into the outbound OpenRTB bid request and, through it, into injected creatives and the IAS brand-safety pixel, so both carried the edge/staging host instead of the real publisher domain.

build_auction_request set publisher.domain, site.domain, and the page_url host from request_info.host. This change sources those fields from settings.publisher.domain instead — matching what convert_tsjs_to_auction_request already does on the /auction endpoint path.

Closes #936.

Root cause

Two AuctionRequest builders derived the publisher host from opposite sources:

  • convert_tsjs_to_auction_request (auction/formats.rs) — used config (settings.publisher.domain). ✅
  • build_auction_request (publisher.rs) — used the raw incoming Host header. ❌ (navigation path: AuctionSource::InitialNavigation and SpaNavigation)

PR #934 only corrected ext.trusted_server.request_host inside the Prebid provider; it did not touch site.domain / site.publisher.domain / site.page, and on the navigation path request.publisher.domain was itself the poisoned edge host. This fixes the builder at the source.

Changes

  • Add a publisher_domain: &str parameter to build_auction_request and use it for publisher.domain, site.domain, and the page_url host (scheme and path are unchanged).
  • Both call sites pass &settings.publisher.domain.
  • New regression test auction_request_uses_configured_publisher_domain_not_edge_host: with a divergent edge host (ts.example.com) and configured domain (www.example.com), the bid request advertises the configured domain for publisher.domain, site.domain, page_url, and site.page. Written test-first (verified it fails on the old behavior before the fix).

Test plan

  • cargo fmt --all -- --check
  • cargo test-fastly (wasm — core + fastly, incl. new regression test)
  • cargo test-axum (native — shared core)
  • cargo clippy-* — could not run locally: clippy-fastly fails in the trusted-server-js build script (Unrecognized option: 'p'), which reproduces on unmodified main, so it is a pre-existing local-environment issue unrelated to this change. Deferred to CI.

Notes

Targets main (the buggy code exists on main, not just the release branch). Can be cherry-picked / merged into rc/july as needed.

build_auction_request derived publisher.domain, site.domain, and the page
URL host from the incoming request Host header. On the SSAT proxy path that
header is the trusted-server edge host (e.g. the staging domain), which then
leaked into the outbound OpenRTB bid request and, through it, into injected
creatives and the IAS brand-safety pixel.

Source these fields from settings.publisher.domain instead, matching what
convert_tsjs_to_auction_request already does on the /auction endpoint path.

Closes #936
@aram356 aram356 self-assigned this Jul 20, 2026
@aram356
aram356 requested review from ChristianPavilonis and prk-Jr and removed request for ChristianPavilonis July 20, 2026 23:10
aram356 added a commit that referenced this pull request Jul 20, 2026
…n requests) into rc/july

# Conflicts:
#	crates/trusted-server-core/src/publisher.rs

@prk-Jr prk-Jr 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

Fixes the navigation-path (SSAT/SPA) AuctionRequest builder so publisher.domain, site.domain, and the page URL host come from the configured settings.publisher.domain instead of the incoming edge Host header, matching the pattern already used by convert_tsjs_to_auction_request on the /auction path. Minimal, well-targeted diff (publisher.rs only) with a solid test-first regression test.

Non-blocking

🌱 seedling

  • Scheme source differs between the two AuctionRequest builders: build_auction_request (publisher.rs:2021) still derives page_url's scheme from request_info.scheme (edge-detected), while convert_tsjs_to_auction_request (auction/formats.rs:202) hardcodes "https" for the same field. Not a bug today (the edge always terminates TLS as https in production), but worth aligning in a follow-up so both builders source scheme the same way.

👍 praise

  • Test-first regression coverage: auction_request_uses_configured_publisher_domain_not_edge_host uses a deliberately divergent edge host (ts.example.com) vs. configured domain (www.example.com) and asserts all four leak points (publisher.domain, site.domain, page_url, site.page). Confirmed to fail on the pre-fix code per the PR description.

CI Status

  • fmt: PASS
  • clippy: not reported as a distinct check (cargo check jobs pass)
  • rust tests: PASS (fastly/axum/cloudflare/spin, cross-adapter parity)
  • js tests (vitest): PASS
  • integration tests: PASS

@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.

Summary

The core OpenRTB/APS domain correction is narrow and correct. Approving with two follow-up findings noted inline: navigation telemetry still uses the edge host as publisher_domain, and the new regression test covers the helper rather than the production handlers.

ec_id,
&consent_context,
&request_info,
&settings.publisher.domain,

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.

🔧 P1 / High — Navigation telemetry still records the edge host as the publisher domain

The auction request now correctly receives settings.publisher.domain here, but the AuctionObservationContext::from_parts call immediately above still receives request_host. The SPA path has the same mismatch at lines 2438–2440, where it passes request_info.host. On the affected routing model those values are the edge/staging host this PR is removing from the auction request.

AuctionObservationContext copies the value into publisher_domain, which Tinybird uses for sorting, rollups, dashboard filters, and ingestion-freshness reporting. Navigation metrics will therefore remain attributed to the edge host while /auction metrics and outbound bids use the configured publisher domain.

Suggested fix: Pass &settings.publisher.domain to both observation constructors and add coverage with divergent request/configured hosts that asserts the emitted event rows use the configured publisher domain.

}

#[test]
fn auction_request_uses_configured_publisher_domain_not_edge_host() {

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.

🌱 P2 / Medium — The regression test does not exercise either production call path

This test invokes build_auction_request directly and supplies "www.example.com" itself. It would continue passing if either newly changed handler reverted to passing request_info.host, because both sources have the same &str type.

The original defect was a source-selection error between builders and request paths, so helper-only coverage proves field assignment but not that initial and SPA navigation choose the correct source.

Suggested fix: Add handler-level tests for initial navigation and /__ts/page-bids with divergent edge/configured hosts, capturing the dispatched auction or OpenRTB request. Those tests can also cover the telemetry inconsistency noted above.

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.

Injected creatives + IAS brand-safety pixel carry the TS edge host instead of the publisher domain

3 participants