Skip to content

APS creatives requiring nested same-origin semantics render blank #999

Description

@ChristianPavilonis

Description

Some APS creatives do not render even though the APS renderer and Amazon runner initialize. The failure occurs when a creative library expects a nested HTTPS iframe to retain its real origin.

A confirmed example is a Flashtalking Richload creative: its nested Richload iframe remains visibility: hidden with an empty document, so the placement appears blank.

This is separate from the PUC transport, GAM 1x1 shell resizing, and clipping fixes in #998.

Root cause

The APS renderer is served from the publisher origin at:

/integrations/aps/renderer

To keep third-party code isolated from the publisher, the outer renderer iframe and its response CSP deliberately omit allow-same-origin from their sandboxes.

That gives the renderer an opaque origin, but it also activates the sandboxed-origin restriction for the renderer's entire descendant browsing-context tree. A nested iframe cannot loosen an ancestor's sandbox restrictions. Consequently, adding allow-same-origin to the creative iframe created by Amazon's runner is ineffective: the inherited outer restriction still forces it to origin null.

The affected Flashtalking creative then reports errors such as:

SecurityError: Blocked a frame with origin "null" from accessing a cross-origin frame.
Both frames are sandboxed and lack the "allow-same-origin" flag.

TypeError: Cannot read properties of null (reading 'open') at #setupRichload

When the effective sandbox permits same-origin semantics, the Richload iframe receives its expected HTTPS origin, populates its document, and becomes visible.

Security constraint

We should not simply add allow-same-origin to the current publisher-origin renderer.

Combining allow-scripts and allow-same-origin on a publisher-origin document would allow code in that document to access publisher DOM and origin state and potentially remove its iframe sandbox. Any solution must preserve the boundary between APS/creative code and the publisher.

Existing protections should also remain intact:

  • Bounded and canonical descriptor validation
  • Nonce-bound, one-shot message transport
  • Exact source-frame and MessagePort ownership
  • Publisher-origin creative URL rejection
  • Direct-parent compatibility
  • GAM/PUC slot ownership and guarded shell resizing

Potential solutions and trade-offs

1. Naturally opaque data: renderer

Instead of navigating the renderer iframe to a publisher-origin endpoint, embed the static renderer document in a data: URL and apply a sandbox containing allow-scripts allow-same-origin.

A data: document has a naturally unique opaque origin. allow-same-origin therefore does not make it publisher-origin, but it avoids imposing the sandboxed-origin restriction on its HTTPS descendants.

A controlled Chromium proof with the affected Flashtalking creative produced:

  • Renderer origin: null
  • Publisher DOM readable from renderer: no
  • Renderer frameElement readable/removable: no
  • Flashtalking frame origin: https://cdn.flashtalking.com
  • Richload used/loaded: yes
  • Richload visibility: visible
  • Richload document populated: yes

Advantages:

  • No new renderer hostname or service
  • Preserves browser-enforced separation from the publisher
  • Allows nested creative frames to keep their real origins
  • Does not require rewriting vendor creative markup into the publisher document
  • Existing nonce and MessageChannel protocols can remain

Trade-offs and open questions:

  • A data: document cannot receive HTTP response headers. Resource restrictions can use a meta CSP, but CSP directives such as sandbox cannot be equivalently delivered through a meta policy. The iframe sandbox attribute becomes the primary boundary.
  • Publisher and GAM/PUC frame policies must permit data: in frame-src/child-src.
  • location.origin is null, so defense-in-depth validation that currently rejects creative URLs matching the publisher must receive or embed the trusted publisher origin explicitly.
  • The static renderer source moves into the client/PUC program and makes the iframe URL larger and less convenient to inspect.
  • Self-navigation, popup, top-navigation, and sandbox-removal attempts need explicit adversarial tests.
  • Chromium, Firefox, WebKit, direct rendering, and real PUC topology all need validation.

2. Dedicated cross-origin renderer endpoint

Serve the renderer from a distinct browser origin and permit allow-same-origin there.

Advantages:

  • Conventional HTTP response headers and CSP
  • Straightforward origin-targeted messaging
  • Clear isolation boundary when the origin has no other authority

Trade-offs:

  • Requires DNS, TLS, routing, deployment, and publisher CSP changes
  • The origin must be exclusively renderer-only; exposing normal Trusted Server routes under it would weaken the boundary
  • Additional operational ownership for a single integration surface

This may not be operationally acceptable for deployments that do not want a dedicated renderer domain.

3. Render remote iframe creatives directly as siblings

Keep the opaque APS controller but ask trusted publisher-side code to create a direct cross-origin creative iframe outside the opaque controller's descendant tree.

Advantages:

  • Retains a normal HTTPS origin for iframe-tag creatives
  • No additional renderer hostname

Trade-offs:

  • Does not generically support script-tag creatives, where Amazon's runner fetches creative HTML and renders it through srcdoc
  • Requires reimplementing part of Amazon's rendering behavior
  • Risks fragile format- or vendor-specific handling
  • Increases the amount of creative orchestration performed by first-party code

4. Vendor-specific fallback

Detect affected creative formats/vendors and render them through a special path.

Advantages:

  • Potentially narrow implementation

Trade-offs:

  • Brittle and difficult to generalize
  • Requires reliable vendor/format identification before execution
  • Likely to regress as vendor markup changes
  • Creates inconsistent security and rendering behavior

5. Preserve the current opaque renderer

Continue rejecting incompatible same-origin-dependent creatives.

Advantages:

  • No change to the existing security model

Trade-offs:

  • Affected paid placements remain blank
  • Renderer success signals may not reflect whether deeply nested creative content actually painted

Suggested investigation

The naturally opaque data: renderer appears to be the most promising no-domain direction, but it should not be selected without completing the security and compatibility work.

  1. Build a test-only data-URL renderer using the existing static renderer program.
  2. Keep descriptors out of the URL and transfer them only after nonce/source authentication.
  3. Reproduce the current resource CSP with a meta policy and document the directives that cannot be preserved.
  4. Add explicit publisher-origin validation rather than relying on the data document's location.origin.
  5. Run adversarial navigation, popup, storage, DOM-access, sandbox-removal, replay, and wrong-source tests.
  6. Exercise direct APS and real Prebid Universal Creative topologies in Chromium, Firefox, and WebKit.
  7. Add the confirmed Flashtalking Richload creative as a controlled browser regression.
  8. Preserve the current HTTPS renderer as a compatibility fallback until mixed deployments and rollback behavior are defined.

Acceptance criteria

  • Affected nested creatives render and paint at their expected size.
  • Renderer and creative code cannot read or mutate publisher DOM, cookies, storage, or globals.
  • Descendant creative frames retain their intended remote origins.
  • Descriptor, nonce, source, port, timeout, and ownership checks remain enforced.
  • Wrong-origin and publisher-origin creative URLs fail closed.
  • Direct and real PUC paths behave consistently.
  • The solution has cross-browser regression coverage and a documented rollback path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingjavascriptPull requests that update javascript code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions