upstream-sync: sync Prebid.js 11.26.0 → 11.27.0 - #111
Conversation
* Mantis RTD: New RTD Module Added * Mantis RTD: Removed the use of window.location.href for page url * Mantis RTD: Documentation improvements and segtax fix * Mantis RTD: Documentation improvements * Mantis RTD: Documentation improvements * Mantis RTD: Updated Taxonomies for All Segment Groups --------- Co-authored-by: Pramod Kumar <pramod.kumar@reachplc.com> Co-authored-by: Patrick McCann <patmmccann@gmail.com>
* Refactor PPID validation logic with regex Updated PPID validation to use regex for length and character checks. * Remove trailing space * Updated expected message in test
…avigation (#15383) * Tercept Analytics Adapter: fix page view tracking for in-page (SPA) navigation The adapter marked a page view (is_pl) only on the first auction after a hard page load, using a firstSent flag that never reset. Sites that navigate between articles or slides via history.pushState (SPA routing, slideshow-style pagination) never trigger a new page load, so every auction after the first was miscounted as a repeat view of the same page. Replace firstSent with a lastPageUrl comparison in flush(): a page view is now counted whenever the current URL differs from the URL of the last counted auction, which correctly detects in-page navigations without requiring a reload. Also guard against an auction flushing with zero bids consuming the page-load flag — an auction with no bids should not block the next real auction on the same page from being counted as the page view. * Tercept Analytics Adapter: bump version to v2.3.1 * Tercept Analytics Adapter: capture page URL at auction start, not at flush time flush() read the current page URL when it ran, not when the auction was created. With a delayed flush (analyticsBatchTimeout, or simply the natural gap between AUCTION_INIT and AUCTION_END) an in-page navigation could happen before an auction's beacon goes out, so the URL comparison used to detect a new page view was reading the wrong page. Depending on flush order across concurrent auctions this could drop a real page view outright. Capture the URL on the auction object when it is initialized instead, and compare/store that value in flush(), so each auction is always attributed to the page it actually ran on regardless of when — or in what order — it flushes. * Tercept Analytics Adapter: guard page-view tracking against out-of-order auction flushes Auctions can flush in a different order than they started in (independent batch timers), so a slow auction from a page the visitor has since navigated away from could flush after a newer page's auction and rewind lastPageUrl, causing the current page to be double-counted or the stale page to be wrongly credited with a page view. Each auction now records a monotonic sequence number at AUCTION_INIT, and only an auction at least as new as the most recently applied page state can update the tracked URL or be marked as a page view. Also stopped deriving auctionInit.host/path/search from the live window location at send time — an in-page navigation between an auction starting and its (possibly delayed) flush could attribute the auction to the wrong page. These fields are now derived from the same URL captured at auction start that drives the is_pl decision.
* Core: escape values interpolated into generated VAST XML Prebid builds VAST XML by string concatenation in two places, and both placed untrusted values into the document without escaping them. `wrapURI` in src/videoCache.ts and `getUrlNode` in vastXmlBuilder.js wrapped tracker and ad tag URLs in `<![CDATA[...]]>`. A CDATA section ends at the first `]]>`, so a URL containing that sequence closed the section early and the rest of it was parsed as markup - enough to add a sibling element, for instance a second `<Impression>` pointing somewhere else. `getOpeningLabel` in vastXmlBuilder.js interpolated attribute values with no escaping at all, so a value containing a double quote closed the attribute and could add another. `wrapURI` had the same problem for the `event` attribute of `<Tracking>`. Add `cdata` and `attributeValue` to a new src/utils/xml.ts and use them at both sites. `cdata` splits `]]>` across two adjacent sections, which a parser reads back as the original text, so no tracker is dropped or altered. Values that contain none of these characters are emitted exactly as before, which keeps the generated documents byte for byte identical for ordinary input; building the documents with DOM APIs instead would have been safe by construction but changes the serialised form, since empty elements collapse to `<Creatives/>`. Attribute names are not escaped. Every name in these builders is a literal, and a name taken from input would need validating against the XML Name grammar, which escaping cannot do; the constraint is noted where the names are assembled. Also drop the comment in wrapURI that discounted this, which reasoned that the VAST URL is bidder controlled in any case. That covers the URL it was written for, but not the tracker values, which can come from analytics modules through `registerVastTrackers`. npx eslint src/utils/xml.ts src/videoCache.ts libraries/video/shared/vastXmlBuilder.js and both changed specs - clean. npx tsc --noEmit --strict src/utils/xml.ts - clean. npx gulp test --nolint --file, all passing: videoCache_spec 33, vastXmlBuilder 19, vastXmlEditor 11, videoImpressionVerifier 3, vastTrackers 22, gamAdServerVideo 94. Each set of added tests was confirmed to fail with its source change reverted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Tests: cover structural injection in DOM-built VAST XML The VAST builders that use DOM APIs rather than string concatenation cannot have their document structure altered by the values they place in it, but nothing asserted that, so rewriting one of them with string templates would have passed every existing test. `insertVastTrackers` gets six tests. Four place a value containing `]]>` or a double quote in an impression url, an error url, a tracking event url and a tracking event name, and check that no element or attribute appears beyond the one the tracker describes. Two cover the fallback: vastXml with no Wrapper or InLine element, and vastXml that cannot be parsed, are both returned unchanged. The assertions read the parsed document rather than matching strings, so they hold for any implementation that keeps the property. A value that cannot be represented may be left out - which is what happens today, since createCDATASection rejects `]]>` and the whole insertion is abandoned - so the element count is asserted as at most one rather than exactly one. They were checked by replacing insertVastTrackers with a string template implementation, which failed all four of the injection tests. gamAdServerVideo gets one test for the locally cached branch, where a bid's own vastXml arrives through vastLocalCache as a blob and is placed in a CDATA section. Note it does not fail if only the base64 encoding is dropped from getBase64BlobContent, because createCDATASection then rejects the sequence on its own; it covers the two steps together rather than either one. The mock server responds to one request per call, and the second of the two requests getVastXml makes is only issued once the first resolves, so responding to both needs a wait. That was repeated inline in two tests and is now respondToAdServerThenBlob. npx eslint on both changed specs - clean. npx gulp test --nolint --file: vastTrackers_spec 28, gamAdServerVideo_spec 95. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Core: note bot authorship of the VAST XML escaping helpers Required by the repo guidelines in CLAUDE.md for changes proposed to prebid/Prebid.js. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dmytro-po <dmytro.po@intentiq.com>
…5406)
* Core: escape HTML-unsafe characters in encodeMacroURI macro names
encodeMacroURI located each already-encoded `${...}` span by building a search
needle with encodeURIComponent, then replaced it with the raw macro text. That
restored every character in the macro name, so a name containing `"`, `<`, `>`
or whitespace was emitted unescaped into the `src="..."` attribute built by
createTrackPixelHtml, which is enough to terminate the attribute and inject
another attribute or tag.
Emit the braces literally, as before, but percent-encode only the characters
that can break out of a double-quoted attribute value, leaving the rest of the
name byte-identical. Because the needle matching is gone, the encodeURI vs
encodeURIComponent divergence that decided which spans were restored no longer
applies; the macro pattern now excludes the characters those two encode
differently, so brace expressions that are not macros keep their current
encoded form.
Tests cover each unsafe character both inside and outside a macro, and assert
at the DOM level that the markup createTrackPixelHtml produces with this
encoder yields no extra element or attribute.
npx eslint src/utils.js test/spec/utils_spec.js - clean.
npx gulp test --nolint --file, all passing: utils_spec 207, ortbConverter
banner_spec 14, kimberlite 12, trustx 38/43, adkernel 45, deltaprojects 31,
taboola 95/101.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Core: encode macro names as UTF-8 in encodeMacroURI
HTML_UNSAFE_CHARS used `\s`, which matches 20 non-ASCII whitespace code
points in addition to ASCII whitespace, and percentEncode escaped them
with charCodeAt, i.e. per UTF-16 code unit rather than per UTF-8 byte.
The resulting escapes are well-formed but decode to something else: a
macro name containing U+2000 came out as `%2000`, which decodes to a
space followed by a literal `00`, while U+00A0 and U+FEFF produced `%A0`
and `%FEFF`, which throw URIError on decode.
Spell the ASCII whitespace out instead. None of the non-ASCII whitespace
can terminate a double-quoted attribute value, so leaving it alone keeps
a macro name byte-for-byte wherever escaping is not required. Replace
percentEncode with encodeURIComponent so that the escape is correct for
any character, and the character class stays a policy knob.
Also correct the comment above the class: encodeURI does not leave these
characters alone, it encodes all of them. They need explicit handling
because a macro name bypasses encodeURI, its braces being emitted
literally so that downstream substitution can find them.
Tests cover six representative non-ASCII whitespace code points, each
asserting passthrough inside a macro and that the output survives
decodeURIComponent unchanged, and add vertical tab to the HTML_UNSAFE
table, which listed nine of the ten characters the class covers.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Core: match encodeMacroURI macros without shared regex state
The macro pattern is a module-level /g regex, and exec advances lastIndex
on the object it is called on. The loop was self-cleaning on the happy
path, since the final exec returns null and resets lastIndex to 0, but a
call that could not finish left the offset behind: encodeURI throws
URIError on a lone surrogate, and when one sits before a macro the throw
happens after exec has already advanced. The next call then began its
scan mid-URL, missed its macro, and percent-encoded the braces, so
${AUCTION_PRICE} came out as $%7BAUCTION_PRICE%7D and price substitution
silently stopped working.
buildBidResponse catches and logs per bid, so the throwing bid was
skipped loudly while every later banner bid carrying an nurl was
corrupted with no further error logged.
Iterate with matchAll, which matches against a copy, so the shared
pattern is never mutated and there is no offset to carry over. This also
leaves no defensive line whose removal would quietly reintroduce the
problem.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Core: assert encodeMacroURI escapes exactly, and cover the macro pattern
The escaping tests asserted only that the unsafe character was absent
from the output, which any transform that removes it satisfies. Escaping
a tab as '%9' instead of '%09' passed, even though the following
character is then read as part of the escape and `${A<tab>B}` collapses
to the single byte 0x9B; so did deleting the character outright. Assert
the escape exactly instead.
The set of characters excluded from a macro name had no coverage at all,
though it is what keeps a brace expression that is not a macro encoded
the way it was before macro names were escaped. Widening it to `[^}]+`
passed the whole suite. Add a case per excluded character.
Drop the six round-trip cases over non-ASCII whitespace: the URLs they
build contain no percent sign, so decodeURIComponent is the identity over
them and the assertion held whenever the exact-output assertion above it
did.
Correct two comments. Of the characters escaped inside a macro name only
the double quote can close the attribute value createTrackPixelHtml
writes; the others are escaped because the URL is not guaranteed to land
in a double-quoted attribute, and because they do not belong in a URI.
The macro name is passed through except for HTML_UNSAFE_CHARS, which is
narrower than "characters that are unsafe in HTML markup" - the single
quote and ampersand are not escaped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Patrick McCann <patmmccann@gmail.com>
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4 to 4.37.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@v4...v4.37.3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.37.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
|
This PR includes an adapter whose code does not match its file name. Bid adapter modules should be named |
|
This PR introduces changes that may not work on all browsers. According to Babel, the following polyfills may be needed, and they are not automatically included:
The best way to address this is to provide good test coverage, as normal PR checks run unit tests on older browsers. |
…age rule violations (#15249)
|
Moved `b3ce02a9f` (upstream `5738ac743`, `#15249`) from Skipped to Applied — it was auto-classified as adapter-only (bundled with a `sonobiBidAdapter.js` change, which isn't shipped here), but it also fixes a real storage-compliance gap in our shipped `dgkeywordRtdProvider.js`: replaces a raw `window.localStorage.getItem(...)` call (flagged with its own `TODO: use storageManager` / `eslint-disable-next-line no-restricted-properties`) with the proper `storageManager.getDataFromLocalStorage(...)` API. Cherry-picked just the `dgkeywordRtdProvider.js` hunk; the `sonobiBidAdapter.js` modify/delete conflict resolved by keeping our side's deletion (adapter not shipped). |
* Support GAM view tracking URL (viewUrl) end-to-end and add API to fire it - Add support for a GAM-provided view tracking URL (`viewUrl`) so creatives can pass a view impression endpoint to Prebid for later firing. - Provide a public API to trigger firing of the stored `viewUrl` by ad unit code or ad ID. - Cross-domain renderer: added `parseRenderArgs` and updated `renderer` to accept `viewUrl` (supports both object-style and positional GAM args) and send `viewUrl` in the `Prebid Request` options. - Examples/build: updated `integrationExamples/gpt/x-domain/creative.html` to include `viewUrl` in the generated creative payload and support the new positional argument parsing. - Data model/types: added `viewUrl?: string` to bid response interface in `bidfactory.ts` so the URL can be stored on bids. - Rendering pipeline: propagate `viewUrl` from `render` options into the `bidResponse` in `adRendering.ts` so it is available post-render, and include it when calling `handleRender`. - Public API: added `pbjs.fireViewUrlForAdUnitCode` which locates the matching winning bid by ad unit code or ad ID and fires `viewUrl` using the internal pixel trigger helper (`utils.internal.triggerPixel`). - Tests and examples: updated and added unit tests and cross-domain creative tests to verify `viewUrl` is included in outgoing messages, stored on the bid, and fired via the new API. - Updated unit and integration tests (`test/spec/creative/crossDomainCreative_spec.js`, `test/spec/unit/adRendering_spec.js`, `test/spec/unit/pbjs_api_spec.js`) were run and pass in the test suite. - Existing rendering and message handling tests were exercised to ensure no regressions in creative rendering and messaging; all automated tests succeeded. * Add support for GAM viewUrl: propagate from creatives and allow firing via API - Allow GAM creatives to supply a view tracking URL (`viewUrl`) that needs to be passed from cross-domain creatives into the renderer and stored on the winning bid for later firing. - Support both object and legacy positional argument forms of `pbRender` so `viewUrl` can be supplied by existing publishers. - Provide a small API to let publishers fire the stored GAM view URL on demand (by ad unit code or ad id). - Cross-domain renderer: added `parseRenderArgs` to accept either an object or positional args, and include `viewUrl` in the message `options` sent to the parent (`creative/crossDomain.js` and minified integration example). - Rendering pipeline: added optional `viewUrl` to render option types and propagate `viewUrl` into the `bidResponse` before render hooks run in `handleRender`, and pass `viewUrl` through calls that originate rendering (`adRendering.ts`). - Types and models: added `viewUrl?: string` to the base bid response interface (`bidfactory.ts`). - Public API: added `pbjs.fireViewUrlForAdUnitCode` which locates the current winning bid by ad unit code or ad id and fires the stored `viewUrl` using the internal `triggerPixel` helper (`prebid.ts`). - Tests and examples: updated integration example and unit tests to cover `viewUrl` propagation, positional argument support, and firing behavior. - Unit tests updated and run: `cross-domain creative` spec (`test/spec/creative/crossDomainCreative_spec.js`), `adRendering` spec (`test/spec/unit/adRendering_spec.js`), and `pbjs_api` spec (`test/spec/unit/pbjs_api_spec.js`) which include new cases for `viewUrl` handling and `pbjs.fireViewUrlForAdUnitCode` behavior, and all passed. - Existing test suite was executed and the modified test cases succeeded. * Add support for GAM viewUrl on bids * pass every extra argument (not positionally) * Update generated x-domain example --------- Co-authored-by: Demetrio Girardi <dgirardi@prebid.org>
* Build system: do not publish compiled tests * Build system: move unnecessary runtime dependencies to devDependencies * Build system: lint for undeclared runtime dependencies * Build system: make eslint aware of typescripts resolution logic
* CI: use bundled Safari for browser tests * CI: align native Safari configuration
* Update package-lock.json * Update package-lock.json
Conflicting commits resolved
Source ( The only conflict was in the checked-in, autogenerated
Note: upstream's own PR description says "Do not merge" even though it was in fact merged upstream — flagging that here in case it affects how this is reviewed. Also worth noting this is directly related to the Safari E2E timing bug fixed in PR #110 (
|
Prebid.js Sync:
11.26.0→11.27.0📊 Run summary
This PR was auto-generated by the Sync with Upstream Prebid.js workflow.
Prebid 11.27.0 Release Page
✅ Applied Commits
⏭️ Skipped Commits
These commits were intentionally skipped because they made changes to files matching
BidAdapter:❌ Conflicting Commits (require manual resolution)