Skip to content

The creative click guard ignores <base target> when opening wrapped links #1392

Open

Description

@dhruv8sh

Description

The creative runtime's click guard ignores <base target> when it decides where a wrapped creative link opens.

Since #1252, a bidder <base> keeps its target and only loses its href. On POST /auction, the injected click guard calls preventDefault() on any link with data-tsclick and then navigates using only the anchor's own target (crates/trusted-server-js/lib/src/integrations/creative/click.ts:351):

const target = a.getAttribute('target') || (isMiddle ? '_blank' : '_self');

The form-rebuild path does the same (click.ts:313, form.target = anchor.getAttribute('target') || '_self').

So a creative that relies on <base target="_blank"> behaves inconsistently:

  • POST /auction: wrapped landing links open inside the frame, while unwrapped links (relative, excluded, non-http) open in a new tab, as the browser resolves <base target> for them.
  • Inline SSAT/page-bids (no click guard): wrapped links open in a new tab.

docs/guide/creative-processing.md documents this limitation and the workaround: give links an explicit target.

Reproduction steps

  1. Run an auction on POST /auction with default rewriting, where the winning creative contains <base target="_blank"> and <a href="https://landing.example.com/"> with no target.
  2. Click the link in the rendered creative iframe.
  3. The landing page opens inside the creative frame.

Expected behavior

The click guard resolves the effective target the way the browser does: the anchor's own target, then <base target>, then the default. For example:

const baseTarget = document.querySelector('base[target]')?.getAttribute('target');
const target = a.getAttribute('target') || baseTarget || (isMiddle ? '_blank' : '_self');

Done when

  • click.ts resolves the effective target from <base target> for both direct navigation and the form-rebuild path.
  • Vitest tests cover a link with no target under <base target="_blank">, and a link whose own target overrides the base.
  • The workaround note in creative-processing.md is removed or updated.

Affected area

HTML processing / JS injection

Context

From aram356's review on #1252 (crates/trusted-server-core/src/creative.rs, around line 1288).

Activity

  1. added theissue type on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions