Is Content Ninja Suggest safe?

Medium risk

Generates AI comment suggestions for LinkedIn posts based on the user’s profile, tone, and settings.

This extension provides one-click comment suggestions for LinkedIn posts in styles such as professional, supportive, curious, and insightful. It can learn from the user’s profile, writing patterns, and comment history, and includes engagement lists, guided engagement sessions, and settings for tone, emoji frequency, dialect, and custom instructions.

content-ninja-dev-teamv5.0.4Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

LinkedIn Session Token Read from Page Cookies for Voyager API Access

On LinkedIn, Content Ninja Suggest reads the JSESSIONID cookie via document.cookie.

LinkedIn uses it as a CSRF token for Voyager; the extension sends it as a csrf-token header for profile, feed, and search requests, scoped to linkedin.com.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You visit any page on linkedin.com while the extension is installed.

The extension did this

The extension reads your LinkedIn JSESSIONID cookie from the page and uses it as an authentication header to call LinkedIn's internal Voyager API on your behalf.

The JSESSIONID value is never sent outside linkedin.com; it authenticates requests the extension makes directly to LinkedIn's own endpoints.

The code that does this

Cookie-reading and API-calling code: shipped source vs. deobfuscated readable form.

Readable version

Deobfuscated: getCSRFToken() — reads JSESSIONID cookie

VoyagerClient.prototype.getCSRFToken = function() {  try {    var cookies = document.cookie.split(';');    for (var i = 0; i < cookies.length; i++) {      var parts = cookies[i].trim().split('=');      var name  = parts[0];      var value = parts.slice(1).join('=');      if (name === 'JSESSIONID') {        // LinkedIn wraps the value in quotes; strip them        return value.replace(/^"(.+)"$/, '$1');      }    }    return null;  } catch (e) {    return null;  }};

Deobfuscated: request() — attaches token as csrf-token header

VoyagerClient.prototype.request = function(path, options) {  var csrfToken = this.getCSRFToken();  if (!csrfToken) {    throw new VoyagerError('Not logged into LinkedIn - CSRF token not available', 'NOT_LOGGED_IN');  }  var url     = 'https://www.linkedin.com' + path;  var headers = Object.assign({    accept:                       'application/vnd.linkedin.normalized+json+2.1',    'csrf-token':                 csrfToken,    'x-li-lang':                  'en_US',    'x-li-page-instance':        'urn:li:page:feed_index;' + this.generatePageInstance(),    'x-restli-protocol-version': '2.0.0'  }, (options && options.headers) || {});  return fetch(url, Object.assign({ method: 'GET' }, options, {    headers:     headers,    credentials: 'include',    cache:       'no-store'  }));};
Voyager API endpoints the extension calls using the extracted session token
  • Your LinkedIn profile
    /voyager/api/me

    The extension retrieves your own profile data when you first use it.

  • Any LinkedIn member's full profile
    /voyager/api/identity/dash/profiles/ACoAABcABcABcABcABcA?decorationId=com.linkedin.voyager.dash.deco.identity.profile.FullProfile-76

    The extension fetches the full profile of members it processes, including work history, education, and contact data.

  • LinkedIn feed content
    /voyager/api/feed/updates/urn%3Ali%3Aactivity%3A7123456789012345678

    Post and activity data from your feed or a member's activity feed.

  • LinkedIn search results
    /voyager/api/graphql?includeWebMetadata=true&variables=(start:0,origin:SWITCH_SEARCH_VERTICAL,query:(keywords:AI+tools,...))&queryId=voyagerSearchDashClusters.ef3d0937fb65bd7812e32e5a85028e79

    Content search via the Voyager GraphQL endpoint, using your session to query LinkedIn's internal index.

Hosts that receive authenticated Voyager API requests
    • www.linkedin.com

    LinkedIn's own Voyager API. All requests stay on linkedin.com; the JSESSIONID token is not forwarded to any third-party server.

Reproduce it yourself

Run this in DevTools on any LinkedIn page to confirm whether the JSESSIONID cookie is accessible to page-level JavaScript and whether the extension would be able to read it.

Requires
  • Chrome with an active LinkedIn session
  • DevTools Console access
content-ninja-csrf-check.js · js
// content-ninja-csrf-check.js// Reproduces the logic of Content Ninja Suggest's getCSRFToken().// Run in Chrome DevTools Console while on any linkedin.com page.(function checkCSRFToken() {  var cookies = document.cookie.split(';');  for (var i = 0; i < cookies.length; i++) {    var parts = cookies[i].trim().split('=');    var name  = parts[0];    var value = parts.slice(1).join('=');    if (name === 'JSESSIONID') {      var token = value.replace(/^"(.+)"$/, '$1');      console.log('[CNS-CSRF] JSESSIONID accessible to page JS:', token);      console.log('[CNS-CSRF] Would be sent as csrf-token header to /voyager/api/*');      return token;    }  }  console.log('[CNS-CSRF] JSESSIONID not found in document.cookie (not logged in, or HttpOnly)');  return null;})();
How to run it
  1. 1Open linkedin.com/feed, logged in.
  2. 2Console: paste, run.
  3. 3JSESSIONID prints.
  4. 4fetch('/voyager/api/me',{headers:{'csrf-token':<t>,'x-restli-protocol-version':'2.0.0'},credentials:'include'}).then(r=>r.text()).then(console.log)

Where it sends data

Destinations our analysis observed Content Ninja Suggest 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.

  • LinkedIn

    Content Ninja Suggest sends data to LinkedIn. Named as a recipient by 4 other extensions we have analysed.

Updated 30 September 2026fleloaemgeopkjancpbiiflagoiihaak