Is LinkMatch for Copper safe?

Medium risk

LinkMatch for Copper copies LinkedIn profile, messaging and search API responses and uploads them to linkmatch.com.

On LinkedIn pages the extension wraps the page's fetch and XHR calls and copies the JSON responses for profiles, contact info, messages, Sales Navigator and Recruiter searches. The content script then sends each copied response, together with the user's LinkMatch email, to app2.linkmatch.com. The upload happens on every intercepted response, not only when the user saves a contact.

Yuriy Yazlovytskyyv2.84Chrome Web Store
49Risk
Who publishes it

Logical Pure Minds SRL - 9 other listings from the same operator, 6 of them carrying a finding

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

Publisher
Yuriy Yazlovytskyy
Declared legal entity
Logical Pure Minds SRL

Shared hosts - 2 hostnames

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

api.copper.com
Also called by 3 other listings, including Copper CRM, PandaDoc Proposals and eSignatures for Copper
app.copper.com
Also called by 6 other listings, including Copper CRM, PandaDoc Proposals and eSignatures for Copper

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

Publishers can request a review.

Findings

LinkedIn API responses are copied and uploaded to app2.linkmatch.com

Code analysis shows page scripts copy LinkedIn profile, messaging and recruiter API responses and the extension posts them to app2.linkmatch.com/api/s_data when a LinkMatch user is signed in.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Static analysis
What actually happens
You did this

You open a LinkedIn profile, inbox, Sales Navigator or Recruiter page while signed in to LinkMatch.

The extension did this

The extension copies the data LinkedIn returns to the page and sends it to app2.linkmatch.com.

No save or export click is needed for the upload to fire.

The code that does this

Page-world hook and URL table

Readable version

Content script: relay listener

content-script-bundle.js
                  const e = r => {                    var o;                    if (((o = r.data) === null || o === void 0 ? void 0 : o.type) === "REQ_RESPONSE") {                      const i = r.data;                      D7e(i.url, i.response, i.request)                    }                  };                  window.addEventListener("message", e, !1), window.addEventListener("beforeunload", () => {                    d7e(), pS = !1

Content script: upload to /api/s_data

content-script-bundle.js
                cX = (e, t) => {                  let r = `${_a.linkmatch_host2}/api/s_data`;                  return Yd().then(o => o.caseOf({                    just: i => Ka(r, {                      data: Ci({                        user_id: i.email,                        data: e,                        type: t,                        s: i.s,                        app: _a.ats                      })                    }, "application/json").then(_ => _.caseOf({                      left: E => (gi({                        type: "interception_error",                        params: {                          message: "Error caching data",                          error: E,                          reqType: e.reqType                        }                      }), {                        success: !1                      }),                      right: E => E                    })),                    nothing: () => Promise.resolve({                      success: !1
The code that does this

Handler that routes each intercepted response to the upload

Readable version

Every parsed response is passed to cX(...) without a user save action

content-script-bundle.js
D7e(url, response, request):  reqType = classify(url)  parsed = parser[reqType](response)  cX({pageUrl, reqType, response: parsed}, 'page' | 'global')  // POST to /api/s_data
Upload body to /api/s_data
  • Account email
    jane.doe@example.com (illustrative)

    Your LinkMatch login email is sent as the user id.

  • Parsed API data
    {"reqType":"profile","data":{...}}

    Profile, contact, message or lead fields from LinkedIn's response.

  • Page URL
    https://www.linkedin.com/in/example-profile/

    The LinkedIn page you were viewing.

  • Request type
    profile, contactInfo, sLeadSearch

    Which LinkedIn endpoint class the data came from.

  • App tag
    copper

    Names the product variant that sent the data.

Where the copied data is sent
    • app2.linkmatch.com

    Receives /api/s_data uploads and serves them back via /api/g_data; LinkMatch vendor host.

Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

Where it sends data

Destinations our analysis observed LinkMatch for Copper 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.

  • app2.linkmatch.com

    LinkMatch for Copper sends data to app2.linkmatch.com. 6 other extensions we have analysed send data here.

Updated 15 October 2026mincolbnjlhfnkegjmjkonffgieoddog