Skip to content

Remove dead ad-proxy URL rewriting from Prebid parse_response#531

Open
ChristianPavilonis wants to merge 3 commits intomainfrom
fix/prebid-host-scheme-trust
Open

Remove dead ad-proxy URL rewriting from Prebid parse_response#531
ChristianPavilonis wants to merge 3 commits intomainfrom
fix/prebid-host-scheme-trust

Conversation

@ChristianPavilonis
Copy link
Collaborator

@ChristianPavilonis ChristianPavilonis commented Mar 19, 2026

Summary

Fixes a security issue (#417) where request_host and request_scheme for URL rewriting were read from the upstream Prebid Server response JSON, allowing a compromised or misconfigured bidder to inject arbitrary values into ad markup URL rewrites.

What we discovered

During review we found that the entire transform_prebid_response code path is dead code:

  1. Route handler removedtransform_prebid_response generates /ad-proxy/ URLs (e.g. https://host/ad-proxy/adsrvr/...), but the /ad-proxy/ route handler was removed in 25084ba ("NextJS with Prebid Integration"). These URLs fall through to the publisher origin fallback, which can't handle them.

  2. Downstream rewriter already handles thiscreative::rewrite_creative_html (called from formats.rs during convert_to_openrtb_response) rewrites all third-party URLs in creative HTML to signed /first-party/proxy?tsurl=...&tstoken=... paths using Settings. This is the active, working rewriter.

  3. Double rewriting — When both rewriters were active, transform_prebid_response first rewrote https://cdn.adsrvr.org/pixel.pnghttps://host/ad-proxy/adsrvr/pixel.png, then creative::rewrite_creative_html saw that as an absolute URL and rewrote it again to /first-party/proxy?tsurl=https://host/ad-proxy/adsrvr/pixel.png&tstoken=... — a proxy URL pointing to a non-existent route.

  4. nurl/burl rewriting was dead work — those fields are parsed into the Bid struct but never used in the final convert_to_openrtb_response output.

How it was fixed

Instead of patching the untrusted-data path (the original approach used OnceLock<RequestInfo> to cache local request info), we removed the dead code entirely:

  • Deleted transform_prebid_response, rewrite_ad_markup, and make_first_party_proxy_url (~80 lines)
  • Removed OnceLock<RequestInfo> field from PrebidAuctionProvider — it was only needed to feed the deleted rewriter
  • Removed the RequestInfo capture in request_bids and the transform_prebid_response call in parse_response
  • Cleaned up unused imports (OnceLock, base64::BASE64, serde_json::json)
  • Deleted the two tests that exercised the removed functions

PrebidAuctionProvider returns to being a stateless config-only struct. The request_host/request_scheme fields are still sent to Prebid Server in TrustedServerExt for the signing protocol — that outbound path is unchanged.

Verification

  • cargo test --workspace — all 667 tests pass
  • cargo clippy --all-targets --all-features -- -D warnings — clean
  • cargo fmt --all -- --check — clean
  • Manual: confirm creatives render correctly and /first-party/proxy URLs appear in auction responses (not /ad-proxy/)

Closes #417

@ChristianPavilonis ChristianPavilonis changed the title Use local request info for Prebid response URL rewriting Remove dead ad-proxy URL rewriting from Prebid parse_response Mar 19, 2026
@ChristianPavilonis ChristianPavilonis marked this pull request as ready for review March 19, 2026 21:11
Copy link
Collaborator

@prk-Jr prk-Jr left a comment

Choose a reason for hiding this comment

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

👍 Looks good

Copy link
Collaborator

@aram356 aram356 left a comment

Choose a reason for hiding this comment

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

@ChristianPavilonis Please resolve conflict

Store RequestInfo from the original client request on the provider
during request_bids and use it in parse_response for URL rewriting.
Previously, host and scheme were read back from the upstream Prebid
Server response body, allowing a compromised or misconfigured bidder
to inject arbitrary values into ad markup URL rewrites.

The request_host and request_scheme fields are still sent to Prebid
Server in the TrustedServerExt for the signing protocol, but the
response-side values are no longer trusted for rewriting.

Closes #417
The transform_prebid_response, rewrite_ad_markup, and
make_first_party_proxy_url functions generated /ad-proxy/ URLs whose
route handler was removed in 25084ba (NextJS with Prebid Integration).
The downstream creative::rewrite_creative_html already rewrites all
creative URLs to /first-party/proxy, making the Prebid-level rewriting
both dead and harmful (it produced double-rewritten URLs pointing to a
non-existent endpoint).

Removing this dead code also eliminates the security issue where
request_host and request_scheme were read from the upstream Prebid
Server response body (#417) — there is simply no response-side URL
rewriting left to trust or distrust.

Closes #417
@ChristianPavilonis ChristianPavilonis force-pushed the fix/prebid-host-scheme-trust branch from 18041e7 to 9bce2ea Compare March 20, 2026 19:17
Copy link
Collaborator

@aram356 aram356 left a comment

Choose a reason for hiding this comment

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

👍 Looks good

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.

Prebid response rewriting trusts host/scheme from upstream response body

3 participants