Is Publisher Discovery Extension safe?

High risk

Publisher Discovery Extension sends visited page URLs, account email, clicks, and non-password form values to its servers.

When a logged-in user changes tabs, navigates, or focuses a browser window, the extension records the active page URL and domain with the user's account email. Its content script also runs on every site, captures click labels and non-password input or select values, and forwards those analytics events to Publisher Discovery.

Publisher Discoveryv100.0.10Chrome Web Store
72Risk
Who publishes it

Publisher Discovery - no other listings under this identity

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Publisher Discovery
Declared legal entity
Publisher Discovery
Registered address
Cambridge House, 1 Henry Street, Bath BA1 1JS, GB
Registered contact
Tom Bourne

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Form values and click labels sent to Publisher Discovery

We observed the all-sites content script collect click text, element identifiers, field names, and non-password form values, forwarding events to app.publisherdiscovery.com/api/tracking/events once logged in, batched every two seconds.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You click page content or change a non-password form field.

The content script runs on every website matched by the extension manifest.

The extension did this

The extension records click labels, element identifiers, field names, and non-password values, then queues them for transmission.

Dynamic analysis confirmed `input_change` events with a planted non-password input marker and `click` events with clicked page text.

Fields captured from page interactions
  • Your non-password form value
    pd_form_canary_7f3c21

    A value you type or select can reveal searches, account details, preferences, or other page-specific entries even when it is not a password.

  • The field name or ID
    account_email

    The field label can explain what the value represents, such as an email field, search box, coupon field, or account setting.

  • The page context
    https://example-shop.test/account/preferences

    The page URL and domain connect the event to the site where you interacted.

  • The clicked text
    pd_click_canary_7f3c21

    Text from the element you clicked can show what option, link, or button you selected on the page.

  • The element selector and ID
    #newsletter-signup

    Selectors and IDs add page structure around the click or form event, making the interaction easier to interpret later.

When this fires

Every 2 seconds

The content script flushes queued interaction events every two seconds while the page is active and sends any pending session event when the page loses focus.

Captured request
POSThttps://app.publisherdiscovery.com/api/tracking/events

Dynamic analysis confirmed a POST to this endpoint containing `input_change` with a planted non-password input marker and `click` with clicked page text.

Headers
Accept
application/json
Content-Type
application/json
Authorization
Bearer <redacted>
The code that does this

Shipped code that captures page interactions and forwards the batch

Readable version

Readable interpretation of the content-script collection path

analytics.js
function initializeInteractionTracking() {    captureCurrentPageContext();    document.addEventListener('click', event => {        queueAnalyticsEvent('click', {            element: selectorFor(event.target),            text: event.target.innerText?.substring(0, 30) || 'no-text',            id: event.target.id        });    });    document.addEventListener('change', event => {        const target = event.target;        if (target.tagName !== 'INPUT' && target.tagName !== 'SELECT') return;        if (target.type === 'password') return;        queueAnalyticsEvent('input_change', {            field: target.id || target.name,            value: target.value        });    });    const startTime = Date.now();    window.addEventListener('blur', () => {        queueAnalyticsEvent('session_end', { duration: Date.now() - startTime });        flushQueuedEvents();    });}

Readable interpretation of the two-second batch handoff

analytics.js
async function flushQueuedEvents() {    if (eventQueue.length === 0) return;    if (isSaving) return;    isSaving = true;    const batch = [...eventQueue];    eventQueue = [];    try {        chrome.runtime.sendMessage({            type: 'SYNC_ANALYTICS',            payload: batch        });    } catch (error) {        eventQueue = [...batch, ...eventQueue];    } finally {        isSaving = false;    }}

Readable interpretation of the background forwarding path

background.js
function handleAnalyticsMessage(request, sendResponse) {    if (request.type !== 'SYNC_ANALYTICS') return false;    if (USER_TOKEN && request.payload && request.payload.length > 0) {        pdApiCall('/api/tracking/events', 'POST', request.payload);    }    sendResponse({ success: true });    return true;}

Readable interpretation of the JSON POST helper

background.js
async function postToPublisherDiscovery(endpoint, body) {    if (!USER_TOKEN) {        const stored = await chrome.storage.local.get(['pd_token']);        USER_TOKEN = stored.pd_token;        if (!USER_TOKEN) return null;    }    const response = await fetch(`https://app.publisherdiscovery.com${endpoint}`, {        method: 'POST',        headers: {            Authorization: `Bearer ${USER_TOKEN}`,            'Content-Type': 'application/json',            Accept: 'application/json'        },        body: JSON.stringify(body)    });    if (!response.ok) return null;    const text = await response.text();    return text ? JSON.parse(text) : {};}
Destination receiving the interaction batch
    • app.publisherdiscovery.com

    Publisher Discovery tracking API endpoint that receives the content-script event batch when the background worker has a user token.

Where it sends data

Destinations our analysis observed Publisher Discovery Extension contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • app.publisherdiscovery.com

    Publisher Discovery Extension sends data to app.publisherdiscovery.com. No other extension we have analysed sends data here.

Updated 30 September 2026cgikbmpnchlhjohhbglcpcahabbjboan