From 838e30cd96dccfb3b89c612952552de4e2fca982 Mon Sep 17 00:00:00 2001 From: pankivanastasiya Date: Thu, 12 Feb 2026 11:00:44 +0200 Subject: [PATCH] Core: validate bid response mediaType against ad unit mediaTypes Reject bid responses whose mediaType does not match any of the ad unit's declared mediaTypes. This prevents mismatched bids (e.g. a video bid for a banner-only ad unit) from entering the auction. Co-Authored-By: Claude Opus 4.6 --- src/adapters/bidderFactory.ts | 10 ++++ test/spec/unit/core/bidderFactory_spec.js | 66 +++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/src/adapters/bidderFactory.ts b/src/adapters/bidderFactory.ts index bbd42934057..aec185dc2af 100644 --- a/src/adapters/bidderFactory.ts +++ b/src/adapters/bidderFactory.ts @@ -685,6 +685,16 @@ export function isValid(adUnitCode: string, bid: Bid, {index = auctionManager.in return false; } + if (bid.mediaType) { + const mediaTypes = index.getMediaTypes(bid); + if (mediaTypes && Object.keys(mediaTypes).length > 0) { + if (!mediaTypes.hasOwnProperty(bid.mediaType)) { + logError(errorMessage(`Bid mediaType '${bid.mediaType}' is not supported by the ad unit. Allowed: ${Object.keys(mediaTypes).join(', ')}`)); + return false; + } + } + } + if (FEATURES.NATIVE && bid.mediaType === 'native' && !nativeBidIsValid(bid, {index})) { logError(errorMessage('Native bid missing some required properties.')); return false; diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 79b09cfbe11..ea73fc30188 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1744,6 +1744,72 @@ describe('bidderFactory', () => { }); }); }) + + describe('media type validation', () => { + let req; + + function mkResponse(props) { + return Object.assign({ + requestId: req.bidId, + cpm: 1, + ttl: 60, + creativeId: '123', + netRevenue: true, + currency: 'USD', + width: 1, + height: 2, + }, props); + } + + function checkValid(bid) { + return isValid('au', bid, {index: stubAuctionIndex({bidRequests: [req]})}); + } + + beforeEach(() => { + req = { + ...MOCK_BIDS_REQUEST.bids[0], + mediaTypes: { + banner: { + sizes: [[1, 2]] + } + } + }; + }); + + it('should reject video bid when ad unit only has banner', () => { + expect(checkValid(mkResponse({mediaType: 'video'}))).to.be.false; + }); + + it('should reject banner bid when ad unit only has video', () => { + req.mediaTypes = {video: {context: 'instream'}}; + expect(checkValid(mkResponse({mediaType: 'banner'}))).to.be.false; + }); + + it('should accept banner bid when ad unit has banner', () => { + expect(checkValid(mkResponse({mediaType: 'banner'}))).to.be.true; + }); + + it('should accept video bid when ad unit has both banner and video', () => { + req.mediaTypes = { + banner: {sizes: [[1, 2]]}, + video: {context: 'instream'} + }; + expect(checkValid(mkResponse({mediaType: 'video', vastUrl: 'http://vast.xml'}))).to.be.true; + }); + + it('should skip check when bid.mediaType is not set', () => { + expect(checkValid(mkResponse({mediaType: undefined}))).to.be.true; + }); + + it('should skip check when mediaTypes is unavailable from index', () => { + delete req.mediaTypes; + expect(checkValid(mkResponse({mediaType: 'banner'}))).to.be.true; + }); + + it('should reject native bid when ad unit only has banner', () => { + expect(checkValid(mkResponse({mediaType: 'native'}))).to.be.false; + }); + }); }); describe('gzip compression', () => {