-
Notifications
You must be signed in to change notification settings - Fork 236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Securely Propagating Auction Signals #119
Comments
Just to be sure I understand: your goal is for the seller to receive some opaque blob with the contextual response, which the seller's domain (e.g. its worklet) can open up and then pass along to the buyers in its auction? So you are trying to protect the contents of this blob from use outside the auction you're running, but are willing to allow free use within that auction? This seems entirely reasonable as a goal. I'll need to work with some other Chrome engineers to figure out the technical details of how to support it, though. |
Yes, that's right! |
@michaelkleber This is still something we're interested in -- is this something you've been able to give more thought to? I think this is probably something that could be built on top of Subresource Bundles. |
Hi @jeffkaufman : We have not been pursuing this approach. I presume, from your bumping this issue, that the use cases you're considering cannot be addressed instead by use of the seller's Key-Value server? @JensenPaul if you have thoughts on how to consider this for future planning. |
Yes, we have signals that we don't want to expose to other scripts running in the publisher JS context, and these signals depend on the contextual ad request and so can't come from the K-V server. |
Being able to privately propagate auction signals to the FLEDGE auction also seems relevant in the context of discussions in #59 and #202 on how multiple sellers might be supported: different sellers who work with a given publisher and may have code running on that publisher’s pages might wish to keep their own auction signals private and not readable by other sellers. While a seller could invoke |
When the contextual signals are returned (the ones that you’re asking to securely propagate), can they be exposed to JS momentarily, so they can be passed from, for example, the XHR result to a new API to convert them to an opaque blob? Is the goal that one blob of signals are passed to all of a seller’s bidders? |
@JensenPaul if the signals are exposed momentarily, then other JS running on the page can read them, so I don't think that works? Let me write something up describing a few ideas for how to implement this and get back to you?
Some signals are for a seller's bidders (ex: "how likely is this slot to meet the ActiveView criteria") and those could go to all. Other signals are for the seller themself in scoring bids (ex: "how valuable is this slot on this particular page right now"). |
@JensenPaul Ok, here are four potential approaches to protecting server-generated contextual signals from scripts running on the publisher page:
Since we want a solution that handles component auctions and performs well, I think the strongest options are (2) and (4). Of these, since (2) requires the browser to generate public keys and implement a new cryptographic protocol, that pushes strongly in favor of (4). Aside, on proxy-based attacks: every approach here is somewhat vulnerable to a hostile seller running JS on the page. If the attacker is willing to run a proxy and impersonate the browser they can override the API to create the iframe, the API used to call the ad server, or the |
If the fetch of the signals happened in an iframe, would that secure them from other scripts on the page? Perhaps the browser could offer something akin to postMessage() to securely feed the signals from the iframe into a FLEDGE auction bidder or seller? |
I think something like that could work, though it does add additional latency relative to (4). I think this would require adding something to the auction config saying that additional signals are expected, so the browser knows to delay starting the auction until the signals arrive? Spitballing an API, the publisher page could call:
Then whatever iframe the seller configures can run:
These can be called in either order: if One thing I like this API is that it supports a (4)-like flow where the signals are returned as an html resource within a webbundled contextual ad response, minimizing the latency impact. |
Can you describe where the additional latency concern comes from? is this due to the iframe requirement? Could we simplify your API by having the |
Yes: creating an iframe and waiting for it to run JS is going to add latency.
That would work, but it would add even more latency because of the
|
Subresource bundles are now in origin trial (M90-M101) in Chrome. Perhaps a hybrid
The bundle UUID would resolve to a JSON resource -- the worklet doesn't know or care if the signals came from a bundle or from a JS object. The same behavior of delaying the auction until all signals have been received would apply. If / when subresource bundles become standardized, I think we wouldn't need Of course, this approach has more complexity (needing to deal with both subresource bundles and delaying the auction), which would be good to avoid if the benefits aren't necessary. |
Alternatively, another hybrid approach would be to allow |
I'm going to try prototyping the subresource bundle portion of the hybrid approach above ( |
@jeffkaufman A minor semantic clarification: I think the ACAO response header from CORS doesn't have the ability to restrict access -- on the contrary, it allows access to a resource like application/json files / subresources that have already been restricted by the same origin policy (and also CORB; CORB will prevent the cross-site JSON from being sent to the renderer process, even if a request is made via fetch(), <script>, etc.). My understanding is that the origin of the subresources will be treated as the same as the origin of the wbn package containing them. The important thing then from the Chromium side is that the request for the subresources should be made as if they were from the seller's origin, and not the frame's origin (which doesn't have to match the seller's). (Mostly clarifying my understanding here -- you're likely already familiar with this situation). |
Another question concerns observation of signals by extensions -- I'm assuming this isn't in the threat model for this feature? |
@jeffkaufman Also, out of curiosity, is the use of the uuid-in-package scheme (vs. subresources with a https scheme) required to achieve the desired isolation of the signals? IIUC, I think both schemes could work -- is there something important about the use of the opaque origins of uuid-in-package resources? |
Yes, not trying to hide things from users |
I think you're right that UUID resources are not necessary for this. In WICG/webpackage#624 they are necessary to get the iframe onto a unique origin, but that isn't a consideration here. I think I probably included them in my comments above because I was thinking too much about bundled as loading when I wrote them. |
Do the requests for signals / bundles need cookies / credentials? |
@jeffkaufman FYI, for web bundle requests, I think the server will need to check that the request for the bundle file was made with For instance, a This will prevent the page from fetching and parsing the bundle contents itself (in JavaScript, or server-side). |
If secure signals fail to load, should the auction fail? Or is it acceptable to continue the auction without the secure signals? |
Sorry for missing your questions earlier!
Yes, while third party cookies are still a thing we'll need to be sending them for backwards compatibility.
That sounds good!
In our expected usage the auction would either need to be aborted by the browser or our seller JS would abort it, because some critical signals would be sent this way. But possibly other users of this API would be using it for non-critical signals only? |
Thanks for the responses!
Got it -- I think if there's a desire to have non-critical signals, we could always add a new AuctionConfig field for those, so that the critical and non-critical signals can be separated. |
I'm a bit confused here. The only critical signal seems to be the price of the GAM contextual winner, please correct me if that's not the critical signal you refer to. If Gam/AdX's signals fail, why wouldn't the auction proceed with other sellers? If Gam/Adx contextual doesn't fill, why would you have a critical signal at all? Your example of modeled viewability prediction doesn't seem to be critical. |
I'm no longer at Google, but what I was trying to say was that if the signals can't be transferred into the Turtledove auction we would not want to run an auction. The plan, as far as I understood before leaving, was that the critical signals would always be sent to the client, in the same web bundle as the contextual response. I think this is likely not a real issue, though: the only situation in which the signals wouldn't be available in the auction despite them being sent to the client would be a browser error, and it doesn't seem a very likely browser error? |
As requested in WICG#119, auctionConfig.extraSignals provides a mechanism that sellers can use to offer signals to auction participants, similar to the existing `auctionSignals` and `sellerSignals`, but accepting a subresource bundle URL instead of a JSON-serializable JavaScript object. By passing the auction signals this way (and by setting the X-FLEDGE-Auction-Only header on the response), scripts running on the publisher page won't be able to read the signals -- only the intended auction worklets will have access.
@zhengweiwithoutthei-zz (who I understand is taking this over from Jeff Kaufman). With the current (non-securely propagated) auction signals, the publisher page calls runAdAuction(), and therefore if the publisher is a different entity than the seller, it doesn't have to respect the seller's wishes with respect to which signals get passed to which buyers (publisher.com, or a script running on it's page, could make buyer1.com's signals get passed to buyer2.com, for instance). Am I correct in that we don't want this behavior for the securly-propagated auction signals? |
@zhengweiwithoutthei actually tag Zheng |
With respect to my prior comment, the current API (see #325) does ensure that the caller of runAdAuction() cannot make buyer1.com's signals get sent to buyer2.com, since the |
@caraitto when do you think #325 will be available for testing? I can see a change in progress https://chromium-review.googlesource.com/c/chromium/src/+/3615057 |
@caraitto Question: how does the current spec (#325) support multiple auctions in the document? The signals should be adslot/auction specific. It doesn't seems to be a way to register the the subresources for each auction. Can we pack each auction's extra signals as one object and key it with an uuid and pass that uuid as directFromSellerSignals? |
@zhengweiwithoutthei Sorry I missed your question earlier.
I have a working end-to-end test, and I'm in the process of breaking off reviewable pieces of that CL to land. I hope to be done in the next few weeks -- after that, the feature should be testable in Canary, and roll out to the other channels.
Each runAdAuction() call can be passed a different prefix. So, for example, if you have ad slots 1 and 2 on a page, you could use these prefixes (these are arbitrary -- they just need to be different from each other): https://seller.com/adSlot/1/signals This would get expanded using the pre-defined suffixes into the following subresource URLs, not all of which need be present in bundle file(s) (DirectFromSellerSignals doesn't care which subresource comes from which bundle -- they could all come from the same bundle file, as long as they come from the seller's origin): https://seller.com/adSlot/1/signals?sellerSignals https://seller.com/adSlot/2/signals?sellerSignals etc. Note that UUID URLs (with the uuid-in-package scheme) are not supported, as they don't support CORS, as mentioned in #325. (They also wouldn't work well with the prefix / suffix system). Instead, subresource use URLs that look like ordinary https URLs. |
@caraitto Thanks! This is useful. Should we clarify that the prefix can be slot specific in the explainer? |
@zhengweiwithoutthei Sure, I mailed #363 to do that. |
Question for @zhengweiwithoutthei, @patmmccann and anyone considering using this feature: With respect to failing the auction if the signals fail to load -- would this just happen for In other words, if the I'm considering changing the explainer to just have the signals be passed to worklet functions as null if they fail to load -- the seller worklet can decide to fail if it doesn't receive DirectFromSellerSignals This simplifies the implementation somewhat, but it also allows sellers and buyers the ability to decide what to do. However, with the design as-is, the seller worklet has no insight into whether or not the bidders were able to load their I'm wondering it that's acceptable or not? (FWIW, I don't think these errors are very likely most of the time -- they probably indicate that required headers are missing, JSON is invalid, or perhaps that the download of the bundle file failed, for instance, due to the seller's server being down). |
I like the idea of passing |
(4) requires ad tech to adopt a new technology - WebBundle - which comes with a cost and could negatively impact the adoptability of the FLEDGE API. All we need here is a pathway for the seller to provide signals to the auction and make them only accessible by the worklet. Is it possible for FLEDGE to introduce a new header which can be appended on the contextual ad response to securely transfer data. The signal can be trusted from the seller because it is returned on a response from the seller's origin. The header can be something like:
Chrome can make it so that:
One possible way for (2) is for Chrome to register the content as a subresource bundle under the hood with required content type and response headers. The URLs will be registered as seller’s origin/adslot_id + pre-defined suffixes. In this case, there is no change to the current spec for directFromSellerSignals. Caller will still need to pass the prefix to runAdAuction() but no need to fetch or register the bundle. This should make multi-seller support easier too. |
I mailed #376 to pass null and not fail the auction -- anyone interested in this feature should feel free to leave feedback in that PR, or this thread. Zheng, I'll respond to your proposal in a follow-up comment. |
@zhengweiwithoutthei @patmmccann FYI, DirectFromSellerSignals is now ready for testing in the latest Canary (version 110.0.5451.0 or later). It will rollout to Chrome beta and stable in version 110. |
@michaelkleber as reference for our discussion on Thursday You said in #418
As @MattMenke2 aptly summarizes in the merge of #325 ; the purpose of this feature is the opposite, with the publisher the threat and @jeffkaufman dictating requirements to the Chrome team with the clear goal of preserving AdX's advantage over other sellers by not exposing price of the contextual winner to publishers at event time. This lack of exposure is the only reason publishers submit other ssp bids to GAM, and GAM now subjects those bids to a secret floor, suppressing them without sharing that floor, and ensuring adx never sees a higher floor than another seller or misses an impression opportunity. This lack of exposure also allows the GAM team to extend their market position into the fledge auction. By not exposing the price of the contextual auction to publishers, publishers will have to use GAM to call runadauction if they want to use GAM at all, a choice they don't have because AdWords won't transact elsewhere. The more natural workflow would simply be the contextual win price is exposed to the publisher who then calls runadauction if they so choose and conducts a top level auction themselves. This would allow publishers to gather demand from whichever sources they choose without passing it all to GAM. In a strange irony, in protecting adx from leaking its price to publishers, you may not realize how adx requires all ATP to leak their prices to it and only this feature preserves that into the sandbox. In building this particular feature, you appear to have cemented the position of GAM forever and violated the principles as you laid them out. I think you should revert it. I look forward to our discussion tomorrow. |
We're considering integrating FLEDGE with a flow that looks like:
The ad tag on the client sends a traditional contextual ad request.
It receives a contextual ad response, and also auction signals generated on the server, such as the estimated likelihood of the slot being viewable.
The tag invokes the FLEDGE APIs to run an interest group auction, providing those signals.
We are concerned that other scripts on the page could extract auction signals from the contextual ad responses. These signals are the outputs of complex proprietary models, and access to high-quality bidding signals is one reason buyers choose a particular sell-side platform.
Could FLEDGE provide a path for the server to provide auction signals to the browser auction, without making them accessible to other scripts on the publisher page? (We understand that this would not protect signals from headless browsers or manual inspection, and we think these vectors should be followed up separately.)
One way this could work would be if the worklet processing the decision logic began executing before the auction. The worklet could send a request to the ad server to fetch additional signals to append to
auction_signals
, which the server would restrict to the worklet's origin with an ACAO response header. If other scripts on the page attempted to read the response, they would be blocked by the same-origin policy.Unfortunately this requires an additional round trip to fetch the signals. We could avoid that by having the contextual ad response be a web bundle, where the signals are provided in an opaque-origin resource, with an ACAO header limiting response access to the seller's origin. The ad tag could pass the opaque resource's URL to the decision logic worklet through
auction_signals
, and the signals fetch could be fulfilled from the bundle.The text was updated successfully, but these errors were encountered: