From 2043f5c1efb1597119f47ca39e7b5976f74250f2 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Fri, 17 Sep 2021 15:35:33 -0700 Subject: [PATCH] PublinkId - validate hash and fix decode --- modules/conversantBidAdapter.js | 1 + modules/publinkIdSystem.js | 17 +++++++++++--- test/spec/modules/publinkIdSystem_spec.js | 27 ++++++++++++++++------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index a1ca094273b7..5e05499a18e4 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -373,6 +373,7 @@ function collectEids(bidRequests) { if (utils.isArray(request.userIdAsEids) && request.userIdAsEids.length > 0) { // later following white-list can be converted to block-list if needed const requiredSourceValues = { + 'epsilon.com': 1, 'adserver.org': 1, 'liveramp.com': 1, 'criteo.com': 1, diff --git a/modules/publinkIdSystem.js b/modules/publinkIdSystem.js index 5e5497320971..ca6ca9cf8d83 100644 --- a/modules/publinkIdSystem.js +++ b/modules/publinkIdSystem.js @@ -18,6 +18,10 @@ const PUBLINK_S2S_COOKIE = '_publink_srv'; export const storage = getStorageManager(GVLID); +function isHex(s) { + return (typeof s === 'string' && /^[A-F0-9]+$/i.test(s)); +} + function publinkIdUrl(params, consentData) { let url = utils.parseUrl('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink'); url.search = { @@ -49,8 +53,13 @@ function makeCallback(config = {}, consentData) { } } }; + if (config.params && config.params.e) { - ajax(publinkIdUrl(config.params, consentData), handleResponse, undefined, options); + if (isHex(config.params.e)) { + ajax(publinkIdUrl(config.params, consentData), handleResponse, undefined, options); + } else { + utils.logError('params.e must be a hex string'); + } } }; } @@ -96,11 +105,11 @@ export const publinkIdSubmodule = { /** * decode the stored id value for passing to bid requests * @function - * @param {string} id encrypted userid + * @param {string} publinkId encrypted userid * @returns {{publinkId: string} | undefined} */ decode(publinkId) { - return {publink: publinkId}; + return {publinkId: publinkId}; }, /** @@ -108,6 +117,8 @@ export const publinkIdSubmodule = { * Use a publink cookie first if it is present, otherwise use prebids copy, if neither are available callout to get a new id * @function * @param {SubmoduleConfig} [config] Config object with params and storage properties + * @param {ConsentData|undefined} consentData GDPR consent + * @param {(Object|undefined)} storedId Previously cached id * @returns {IdResponse} */ getId: function(config, consentData, storedId) { diff --git a/test/spec/modules/publinkIdSystem_spec.js b/test/spec/modules/publinkIdSystem_spec.js index 2999fda5aa0e..0680e02e3fa7 100644 --- a/test/spec/modules/publinkIdSystem_spec.js +++ b/test/spec/modules/publinkIdSystem_spec.js @@ -10,7 +10,7 @@ describe('PublinkIdSystem', () => { describe('decode', () => { it('decode', () => { const result = publinkIdSubmodule.decode(TEST_COOKIE_VALUE); - expect(result).deep.equals({publink: TEST_COOKIE_VALUE}); + expect(result).deep.equals({publinkId: TEST_COOKIE_VALUE}); }); }); @@ -69,6 +69,7 @@ describe('PublinkIdSystem', () => { expect(result).to.exist; expect(result.callback).to.be.a('function'); }); + it('Use local copy', () => { const result = publinkIdSubmodule.getId({}, undefined, TEST_COOKIE_VALUE); expect(result).to.be.undefined; @@ -82,14 +83,14 @@ describe('PublinkIdSystem', () => { }); it('Fetch with consent data', () => { - const config = {storage: {type: 'cookie'}, params: {e: 'hashedemailvalue'}}; + const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7'}}; const consentData = {gdprApplies: 1, consentString: 'myconsentstring'}; let submoduleCallback = publinkIdSubmodule.getId(config, consentData).callback; submoduleCallback(callbackSpy); let request = server.requests[0]; request.url = request.url.replace(':443', ''); - expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=hashedemailvalue&mpn=Prebid.js&mpv=$prebid.version$&gdpr=1&gdpr_consent=myconsentstring'); + expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=ca11c0ca7&mpn=Prebid.js&mpv=$prebid.version$&gdpr=1&gdpr_consent=myconsentstring'); request.respond(200, {}, JSON.stringify(serverResponse)); expect(callbackSpy.calledOnce).to.be.true; @@ -97,16 +98,26 @@ describe('PublinkIdSystem', () => { }); it('server doesnt respond', () => { - const config = {storage: {type: 'cookie'}, params: {e: 'hashedemailvalue'}}; + const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7'}}; let submoduleCallback = publinkIdSubmodule.getId(config).callback; submoduleCallback(callbackSpy); let request = server.requests[0]; request.url = request.url.replace(':443', ''); - expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=hashedemailvalue&mpn=Prebid.js&mpv=$prebid.version$'); + expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=ca11c0ca7&mpn=Prebid.js&mpv=$prebid.version$'); request.respond(204, {}, JSON.stringify(serverResponse)); - expect(callbackSpy.calledOnce).to.be.false; + expect(callbackSpy.called).to.be.false; + }); + + it('reject plain email address', () => { + const config = {storage: {type: 'cookie'}, params: {e: 'tester@test.com'}}; + const consentData = {gdprApplies: 1, consentString: 'myconsentstring'}; + let submoduleCallback = publinkIdSubmodule.getId(config, consentData).callback; + submoduleCallback(callbackSpy); + + expect(server.requests).to.have.lengthOf(0); + expect(callbackSpy.called).to.be.false; }); }); @@ -122,13 +133,13 @@ describe('PublinkIdSystem', () => { }); it('Fetch with usprivacy data', () => { - const config = {storage: {type: 'cookie'}, params: {e: 'hashedemailvalue'}}; + const config = {storage: {type: 'cookie'}, params: {e: 'ca11c0ca7'}}; let submoduleCallback = publinkIdSubmodule.getId(config).callback; submoduleCallback(callbackSpy); let request = server.requests[0]; request.url = request.url.replace(':443', ''); - expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=hashedemailvalue&mpn=Prebid.js&mpv=$prebid.version$&us_privacy=1YNN'); + expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=ca11c0ca7&mpn=Prebid.js&mpv=$prebid.version$&us_privacy=1YNN'); request.respond(200, {}, JSON.stringify(serverResponse)); expect(callbackSpy.calledOnce).to.be.true;