Git Product home page Git Product logo

fledge-shim's Introduction

FLEDGE Shim

Note: this project is on hold. Chrome's prototype FLEDGE implementation is accessible locally with feature flags, and per the Privacy Sandbox Timeline broader testing should be possible soon.

This is the beginning of a pure-JavaScript implementation of the FLEDGE proposal, on top of existing browser APIs. The goal is to allow testing as much of FLEDGE as possible, in as realistic a manner as possible, given the constraint of not being able to add new features to the browser itself.

Status

This project has not yet been tested in production; use at your own risk. Furthermore, most of the API is not yet implemented.

Building

As with most JavaScript projects, you'll need Node.js and npm. Install dependencies with npm install as per usual.

In order to build the frame, you have to set a list of allowed URL prefixes for the worklets. The frame will only allow biddingLogicUrl and decisionLogicUrl values that start with those prefixes. Each such prefix must consist of an HTTPS origin optionally followed by a path, and must end with a slash. So, for instance, you could allow worklet scripts under https://dsp.example, or https://ssp.example/js/.

The reason for this is because worklet scripts have access to cross-site interest group and related data, and nothing prevents them from exfiltrating that data. So, if you're going to host the frame and have such cross-site data stored in its origin in users' browsers, you should make sure to only allow worklet scripts from sources that you trust not to do that.

Once you have an allowlist, set the ALLOWED_LOGIC_URL_PREFIXES environment variable to the allowlist with the entries separated by commas, then run npm run build. For example, on Mac or Linux, you might run ALLOWED_LOGIC_URL_PREFIXES=https://dsp.example/,https://ssp.example/js/ npm run build; on Windows PowerShell, the equivalent would be $Env:ALLOWED_LOGIC_URL_PREFIXES = "https://dsp.example/,https://ssp.example/js/"; npm run build.

Design

FLEDGE requires a way to store information in the browser that is (a) accessible across all websites but (b) only through JavaScript access control. localStorage in a cross-origin iframe fits this well. In Chrome this is not partitioned and only JavaScript running within the iframe can read or modify the data.

The shim is divided into two pieces:

  • A frame that's embedded onto the page cross-origin in an <iframe> tag, e.g., <iframe src="https://fledge-shim.example/0.1.html">.

  • A library that consumers use to communicate with the frame over postMessage.

Almost all of the work happens in the frame; the library is a small adapter that translates the API from functions to messages.

API

We're planning to implement the API as closely as possible to what is presented in the explainer, but some aspects necessarily differ due to the constraints of running on publisher and advertiser pages, and implementing without browser changes.

On-Page API

To make the API available on a page consumers will compile the library into their code. We're thinking of making it available as an NPM package, or people can pull from github manually.

Initialization

The library needs to know how to load the frame on the page.

const fledgeShim = new FledgeShim("https://fledge-polyfill.example/0.1.html");

The version number of the frame must match that of the library; this is checked at runtime.

Joining Interest Groups

fledgeShim.joinAdInterestGroup(myGroup, 30 * kSecsPerDay);

Initially, only owner, name, user_bidding_signals, and ads will be supported. We also plan to support for daily_update_url and trusted_bidding_signals_*, and at least the report_win portion of bidding_logic_url. See the worklet discussion below for more on bidding_logic_url.

The daily_update_url is supported, but because we cannot actually run updates in the background as the browser would, we will only be able to fetch updates on days when the polyfill loads on some page.

For trusted bidding signals, we'll need to implement our own caching of responses, since we read FLEDGE as caching at the per-key level. We'll need to parse caching response headers, but we might limit the range of formats we accept.

Initiating an On-Device Auction

// auctionWinnerUrl is an opaque token, and not the real rendering url
const auctionWinnerUrl = await fledgeShim.runAdAuction(myAuctionConfig);

All auction configuration options will be supported, but decision_logic_url (see worklet discussion below) will initially only handle report_result.

Rendering a winning ad

const adFrame = document.createElement("iframe");
adFrame.src = auctionWinnerUrl;
// set whatever further attributes you like on adFrame
document.getElementById("ad-slot-div").appendChild(adFrame);

Because fencedframes don't exist yet, this will render the ad in an ordinary iframe. The shim will not be realistic in testing the security, privacy, performance, or other attributes of fencedframes, since it won't use them at all.

The auctionWinnerUrl will be the same URL as the FLEDGE Shim frame, with a randomly generated token appended in the fragment. When rendered with such a token in its URL fragment, the FLEDGE Shim frame will create a nested iframe inside itself pointing at the original renderUrl. This only works from the same page that called runAdAuction.

Worklets

Buyer and Seller Logic

The proposal allows buyers and sellers to provide custom JavaScript (generate_bid, score_ad) which will have access to interest group information. That access is compatible with the privacy model, because these worklets are heavily locked down, have no network access, and operate as pure functions. We are not aware of any secure way to execute arbitrary JavaScript while protecting information from exfiltration. Initially, we are planning to require buyers and sellers to check their logic into this repo. Later, we may be able to use Web Assembly or something custom to avoid that requirement.

Users may wish to test FLEDGE in circumstances where the privacy guarantees are not necessary, such as internal end-to-end testing. We will probably build support for running custom JavaScript in WebWorkers, behind a compile-time "testing only" flag.

Reporting

Because the MVP allows event level reporting, we do not need the same level of protection for reporting worklets. The report_result and report_win functions will be invoked as described in the spec.

Stages

We are planning to implement this in stages, trying to have a version that is minimally useful as early as possible. Our current planned stages are:

V1

Implement core functionality:

  • joinAdInterestGroup
  • leaveAdInterestGroup
  • runAdAuction

Bidding and auction logic will be hardcoded; currently, each ad simply has a static price, and the ad with the highest price wins.

V2

Implement network functionality: respecting daily_update_url and trusted_bidding_signals_url.

V3

Implement bidding and auction logic: respecting bidding_logic_url and decision_logic_url.

V4

Reporting. Respect report_result and report_win.

Fidelity

  • Performance: While we will build the shim in a manner as performant as possible, you should not generally expect the performance characteristics of the shim to be realistic.

  • K-Anonymity: We don't intend to implement any of the k-anonymity restrictions. Implementing these restrictions requires either peer-to-peer browser interactions or a trusted server. We may revisit this once Chrome announces how they intend to implement it.

fledge-shim's People

Contributors

dependabot[bot] avatar jeffkaufman avatar taymonbeal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fledge-shim's Issues

trusted_scoring_signals_url

Initially we'll just fetch this and then throw away the results. Later, when more sophisticated scoring algorithms are supported (see #21), they may use the results.

trusted_bidding_signals_url

Initially we'll just fetch this and then throw away the results. Later, when more sophisticated bidding algorithms are supported (see #20), they may use the results.

Test positioning of creative

In particular we want to make sure that there aren't any undesirable borders or margins or anything and that the inner iframe's width and height are the same as the outer one's.

I tried Intersection Observer but that doesn't seem to be able to look through the iframe viewport to see the position relative to the actual browser window. I looked at the WebDriver documentation but didn't see any way to do this. I suppose I could try just measuring each iframe relative to its parent but that seems like a place where mistakes could get in. Still trying to think of other options.

Using a same-origin ad creative might be necessary or at least convenient. The API doesn't currently allow srcdoc and data: URIs are cross-origin, so this might require a change on the build-tooling side.

Public TypeScript typings for worklet script authors

If you're writing a worklet script in TypeScript, TypeScript should know what type generateBid is supposed to be and should yell at you if you get it wrong. There's an open question as to how exactly to distribute these typings, e.g., whether they should be a separate package, or what. Follow-up to #20.

Compile-time allowlisting of bidding and scoring logic URLs

Not totally clear on whether this is needed, since if you're vendoring this code and you've got logic that you don't want to open source, you can just put it in your local copy. But if you're using npm then that might be trickier. There are various implications to the different possible API shapes here, so will wait to investigate further until we know what users need.

seller property of runAdAuction argument

For the moment I'm not planning to implement this because it seems to be redundant, but filing an issue so this is on our radar in case the spec changes later.

Behavioral differences with Chrome's implementation of trusted signals fetching

Looking through https://source.chromium.org/chromium/chromium/src/+/main:content/services/auction_worklet/trusted_bidding_signals.cc, there are two apparent differences with how we fetch trusted signals:

  1. FLEDGE Shim appends the hostname and keys parameters after any existing query parameters in the provided URL. Chrome appears to require that the provided URL have no query parameters.
  2. FLEDGE Shim escapes each key, joins them with ,, then escapes them again. Chrome appears to do only one layer of escaping, which means that keys may be ambiguous if there's a , in one of them.

We should find out whether these are bugs in Chrome's implementation or whether the intent is for the feature to be specified this way.

Event-level reporting for sellers

There's a bit of an open question as to how this API will work, since decision_logic_url won't work exactly as described in the spec. Options include:

  • Add a separate field that callers have to pass
  • Have decision_logic_url just do reporting and use trusted signals to choose the scoring algorithm
  • Have decision_logic_url do reporting and also make the choice of scoring algorithm in the global scope

additional_bids

In the spec, this is currently characterized by lots of handwaving and uncertainty, so for the moment we won't implement until a more solid plan for it is in place.

Interest group expiration

We can't auto-expire the actual storage (whatwg/storage#11), so this'll have to work by simply storing the expiration date, and deleting interest groups after reading them if they're expired.

daily_update_url

This won't support any k-anonymity restrictions, and it will only trigger on frame load, not in the background.

Event-level reporting for buyers

There's a bit of an open question as to how this API will work, since bidding_logic_url won't work exactly as described in the spec. Options include:

  • Add a separate field that callers have to pass
  • Have bidding_logic_url just do reporting and use trusted signals to choose the bidding algorithm
  • Have bidding_logic_url do reporting and also make the choice of bidding algorithm in the global scope

Auction timeouts

This should apply both to fetching the worklet script and to running it. Follow-up to #20.

Join forces?

Hi @jeffkaufman @taymonbeal 👋🏼 ,

@iamnewton and I have been working on a similar project to provide a pure JS implementation of the fledge spec. I don't see any value in having two versions of what will eventually be a throwaway library. Do. you want to collaborate together on this effort?

Deduplicate script fetches

As of #20, if n interest groups in a single auction all use the same biddingLogicUrl, we fetch it n times. This is clearly undesirable.

Optimize worker support code

As of #20, the source code is just included verbatim as a string in the binary, with no minification or anything. This is clearly undesirable. To fix it we're going to have to figure out some Webpack stuff.

trustedBiddingSignalsKeys

After #20, we fetch trustedBiddingSignalsUrl and we run a worklet, but we don't plumb the two together. This needs to be added.

Support error telemetry in the frame

Would be good for parties hosting the frame to be able to know if something is going wrong with it. (E.g., if there's a bug that they might want to tell us about.)

k-anonymity

For the reasons described in README.md, this won't be implemented for now.

Figure out whether embedded credentials are supposed to be allowed in URLs

Currently, we allow embedded credentials in URLs, because I haven't put in a check to explicitly disallow them. There's a comment to the effect that they're not supposed to be allowed in the Chrome codebase, and I could swear at one point I saw the code that actually implemented this check, but I can't find it now.

I think this might be security-relevant but am not super clear on the details. I wish there was an actual spec...

Multiple bidding algorithms

Currently, the only supported bidding algorithm is "bid a static price associated with the creative". Once others are suggested, we will need a way to allow bidders to choose between them. This will be the FLEDGE bidding_logic_url parameter, except that it will be a URI of the form fledge-shim:algorithm-name.

Support future database version upgrades

IndexedDB requires users to be careful about database versioning, or else code can crash or deadlock. We should figure out some form of this before FLEDGE Shim is deployed into production, to avoid having a problem that can't be fixed later.

Interest group owners

Feature-Policy will not be supported; the top-level site's permission will not be needed to join an interest group (since we have no way to enforce this). Group owner permission will simply be a domain check for now, without support for delegation. The FLEDGE proposal is ambiguous as to whether we're supposed to support public suffixes; for now, we won't.

Multiple scoring algorithms

Currently, the only supported scoring algorithm is "pass through the bid verbatim". Once others are suggested, we will need a way to allow sellers to choose between them. This will be the FLEDGE decision_logic_url parameter, except that it will be a URI of the form fledge-shim:algorithm-name.

Fledge shim for trusted server worklets

In turledove:#154 we proposed a way to move some of the JavaScript out of the browser and into a trusted server instead, using this technology. Would it be possible to extend the Fledge Shim so that it supports running experiments around this idea?

We’re thinking of two related experiments, both of which look like relatively minor changes to the Shim and which build on top of each other:

  1. Have JavaScript be pre-registered in the trusted server via a separate channel and assigned an id. Rather than send the full JS code from the browser to the trusted server, send just the function id and the arguments to call it with. The server runs the registered function and returns the results.
  2. Move the execution of a group of JS bidding functions, a scoring function, and the final auction to the trusted server.
    • The network overhead and browser compute would be further reduced here. We don’t yet know whether that will be required compared to (1).
    • In this setup either the FLEDGE Shim requests trusted signals from the client, or the server performs those calls given the keys from the client.

Note that we’re not yet sure what the trust model will be for the trusted server. That’s being explored here and so out of scope for these experiments.

Thanks,
Phil

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.