Is Email Finder by Snov.io safe?

Medium risk

Snov.io is medium risk. When you use Snov.io's contact import on Twitter, the extension reads your ct0 CSRF cookie, combined with a hardcoded bearer token, to query api.twitter.com's GraphQL API, retrieving name, bio, location, links, skipping OAuth.

snov.iov2.3.24Chrome Web Store
45Risk
Who publishes it

Snovio inc - 2 other listings from the same operator, none carrying a finding

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

Publisher
snov.io
Declared legal entity
Snovio inc
Registered address
220 E 23rd St #401, New York, NY 10010, US
Registered contact
Snovio

Same store account

2 other listings published from this account, 120k+ users between them, none of them carrying a finding.

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Hardcoded bearer token and Twitter session cookie used to query profile data

When you use Snov.io's contact import on Twitter, the extension reads your ct0 CSRF cookie, combined with a hardcoded bearer token, to query api.twitter.com's GraphQL API, retrieving name, bio, location, links, skipping OAuth.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You select one or more Twitter profiles in the Email Finder popup to save as contacts.

The popup is open on a Twitter search-results page (URL contains /search?q=…&f=user).

The extension did this

The extension reads your ct0 CSRF cookie from twitter.com and sends a GraphQL GET request to api.twitter.com using that cookie and a bearer token hardcoded in its source code.

No OAuth authorization flow is triggered; the extension uses Twitter's own internal web-client bearer token rather than a developer API key registered to Snov.io.

02EvidenceFIELD TABLE
Values used to authenticate the Twitter API request
FieldValueWhy it matters
Hardcoded Twitter bearer token
Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnAA Twitter API authorization credential embedded in the source. It's Twitter's web-client token, not an OAuth token registered to Snov.io.
Your Twitter session CSRF token (ct0)
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6Twitter's CSRF token. The extension reads it from your browser and sends it as x-csrf-token, so the API treats it as your session.
Twitter screen name queried
janedoeThe @handle of the contact whose profile the extension is looking up, derived from the page content the popup is parsing.
03EvidenceCODE COMPARE
The code that does this

Hardcoded bearer and CSRF cookie use in twitterParserApi.js

What it actually does
// Bearer token hardcoded verbatim in extension source (line 1 of twitterParserApi.js)
const TWITTER_AUTH_HEADER =
  'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D' +
  '1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';

// screenName — the @handle to look up
// csrfToken  — the user's ct0 cookie value, passed in from twitterSearch.js
async function getTwitterData(screenName, csrfToken, retryCount = 0) {
  let result = {};
  await $.get({
    url:
      'https://api.twitter.com/graphql/P8ph10GzBbdMqWZxulqCfA/UserByScreenName' +
      '?variables=%7B%22screen_name%22%3A%22' + screenName +
      '%22%2C%22withHighlightedLabel%22%3Afalse%7D',
    beforeSend: xhr => {
      // Uses the hardcoded bearer, not an OAuth token registered to Snov.io
      xhr.setRequestHeader('authorization', TWITTER_AUTH_HEADER);
      // Uses the user's own active Twitter session CSRF token
      xhr.setRequestHeader('x-csrf-token', csrfToken);
    }
  })
  .done(data => {
    if (!Object.keys(data.data).length ||
        data.data.user === undefined ||
        data.data.user.legacy === undefined) {
      return {};
    }
    result = data.data.user;
  })
  .fail(() => {
    showNotLoginTwitter();
  });
  return result;
}
04EvidenceNETWORK CAPTURE
Captured request
GEThttps://api.twitter.com/graphql/P8ph10GzBbdMqWZxulqCfA/UserByScreenName?variables=%7B%22screen_name%22%3A%22twitter%22%2C%22withHighlightedLabel%22%3Afalse%7D
200 OK, JSON body containing user.legacy fields: name, description, location, profile_image_url_https, screen_name, entities.url.urls. Proof-of-concept testing confirmed the hardcoded bearer returns valid profile data for arbitrary screen names.
Headers
x-csrf-token<user ct0 value>
AuthorizationBearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA
05EvidenceTHIRD PARTY LIST
External host receiving requests driven by the user's Twitter session
  • api.twitter.com

    Twitter's GraphQL API. The extension sends UserByScreenName queries using the ct0 CSRF cookie plus a hardcoded bearer token, retrieving profile data without an OAuth grant.

What it can do

Permissions this extension asks for, as declared in version 2.3.24. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    http://*/ and 1 more

  • See the address and title of every tab you have open

    tabs

  • Read and change cookies, including the ones that keep you signed in

    cookies

  • Show you desktop notifications

    notifications

  • Store data in your browser

    storage

Updated 30 September 2026einnffiilpmgldkapbikhkeicohlaapj