Is CAI Tools safe?

Medium risk

CAI Tools is medium risk. CAI Tools' ChatGPT-backed greeting generator fetches your ChatGPT session endpoint, extracts the access token, and uses it to send ChatGPT a conversation request with your prompt, a generated device ID, and sentinel proof tokens.

muhammedirsat000v3.8.3Chrome Web Store
45Risk
Who publishes it

İrşat - 1 other listing 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
muhammedirsat000
Declared legal entity
İrşat
Registered address
İsmetpaşa, Çanakkale Devlet Hst., Çanakkale Merkez, Çanakkale 17000, TR
Registered contact
İrşat

Same store account

1 other listing published from this account, 5k+ users between them, none of them carrying a finding.

Shared hosts - 12 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.chatbotmanager.net
Also called by 2 other listings
api.chub.ai
Also called by 2 other listings
auth.janitorai.com
Also called by 2 other listings
characterhub.org
Also called by 2 other listings
chatbotmanager.net
Also called by 2 other listings
image.jannyai.com
Also called by 2 other listings: Chatbot Manager, CAI Tools
irsat.gitbook.io
Also called by 2 other listings: Chatbot Manager, CAI Tools
jannyai.com
Also called by 2 other listings: Chatbot Manager, CAI Tools
search.jannyai.com
Also called by 2 other listings: Chatbot Manager, CAI Tools
plus.character.ai
Also called by 3 other listings
ella.janitorai.com
Also called by 5 other listings
neo.character.ai
Also called by 5 other listings

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

Publishers can request a review.

Findings

ChatGPT token used for extension prompts

MediumunwantedCWE-359Dynamic sandbox

CAI Tools' ChatGPT-backed greeting generator fetches your ChatGPT session endpoint, extracts the access token, and uses it to send ChatGPT a conversation request with your prompt, a generated device ID, and sentinel proof tokens.

What actually happens

You did this

You click the extension feature that asks ChatGPT to generate a greeting.

The popup builds the prompt from character settings, persona text, and special instructions.

The extension did this

The extension reads your ChatGPT access token and uses it to send the prompt to ChatGPT's backend API.

The code also adds sentinel proof tokens and a generated device ID to match the ChatGPT web request shape.

Captured request

GEThttps://chatgpt.com/api/auth/session

The code reads accessToken from this session response; no dynamic response body was recorded for the confirmed proof.

Captured request

POSThttps://chatgpt.com/backend-api/sentinel/chat-requirements

The code sends a locally generated chat-requirements token before building the final conversation request; no dynamic request body was recorded.

Captured request

POSThttps://chatgpt.com/backend-api/conversation

The code submits the generated prompt to ChatGPT's conversation API with bearer authorization and sentinel headers; no dynamic request body was recorded.

Values the extension reads or sends in the ChatGPT path

  • ChatGPT access token
    Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImNoYXRncHQtd2ViIn0.eyJzdWIiOiJ1c2VyXzEyMzQ1IiwiYXVkIjoid2ViIn0.RXhhbXBsZVNpZ25hdHVyZUZvckJhY2tmaWxs

    This token authenticates the request as your logged-in ChatGPT web session.

  • Greeting prompt text
    Write an opening greeting using the character settings and persona notes provided in the extension.

    This is the content the extension asks ChatGPT to answer for you.

  • Generated device ID
    77d7e6f4-6f7c-4b33-9c22-7342de9eec40

    This value makes the request look like it came from a particular ChatGPT web device session.

  • Sentinel proof tokens
    openai-sentinel-proof-token: gAAAAABWyIxMMiwiVHVlIEp1bCAxNCAyMDI2IiwwLDQyLCJNb3ppbGxhLzUuMCJd

    These values satisfy ChatGPT's request checks before the conversation is submitted.

  • Visibility flag
    is_visible: false

    This marks the generated turn as not visible in the ChatGPT conversation UI.

The code that does this

ChatGPT token read and conversation request construction

Readable version

Popup trigger for the ChatGPT greeting feature

deobfuscated/src/popup/popup.js
// Get prompt, import char settings, import persona, import special instructionslet prompt = defaultGreetingGenPrompt_GPT;let rawPersonaText = persona ? '\n\n' + Object.keys(persona)    .filter((key) => persona[key]) // Leave out the empty and undefined    .map((key) => `${key}: ${persona[key]}`).join('\n') : '';prompt = prompt.replace(/{{dynamic-char-settings/g, rawCharPersonalityText)    .replace(/{{user-persona}}/g, rawPersonaText)    .replace(/{{special-instructions}}/g, special ? `\n\n${special}` : '');this.ReportProgress("Loading... (Asking ChatGPT)");generateGreetingWithChatGPT({ prompt, model: this.model_select.value })

Read the ChatGPT web access token

deobfuscated/src/utils/helper.js
export async function generateGreetingWithChatGPT(args) {    try {        const gptLoginData = await getChatGPTAccessToken();        if (!gptLoginData.token)            return { error: "not_logged_in", message: `You need to login to your ChatGPT account to be able to use this feature.<br/><a href='https://chatgpt.com/' target='_blank'>https://chatgpt.com/</a><br/>If you are already logged in, try logging out & in on ChatGPT.${gptLoginData.error ? `<br/>${gptLoginData.error}` : ''}` };        // Ask gpt        const res = await askChatGPT(args.prompt, gptLoginData.token, args.model);        return res;    } catch (error) {        return { error: "unexpected_error", message: error.message || error };    }}// Get session for access tokenasync function getChatGPTAccessToken() {    try {        const res_session = await fetch("https://chatgpt.com/api/auth/session");        if (!res_session.ok)            throw new Error("ChatGPT login error.", res_session.status, res_session.statusText)        const data_session = await res_session.json();        return { token: data_session.accessToken };    } catch (error) {        return { error };    }}

Build sentinel proof values and send the conversation request

deobfuscated/src/utils/helper.js
async function askChatGPT(prompt, chatgptAccessToken, model, maxTries = 3, modelSelection = 1) {    const randomDeviceId = crypto.randomUUID();    try {        // For chat requirements        const chatReqToken = await solveChallenge("chat_req_token", { chatReqSeed: "" + Math.random(), chatReqDifficulty: "0" });        if (!chatReqToken) {            return { error: "requirements_failed", message: "Couldn't generate the first gpt chat requirement token." };        }        const res_req = await fetch("https://chatgpt.com/backend-api/sentinel/chat-requirements", {            "headers": {                "accept": "*/*",                "authorization": `Bearer ${chatgptAccessToken}`,                "content-type": "application/json"            },            "body": JSON.stringify({ p: chatReqToken }),            "method": "POST"        });        if (!res_req.ok) {            try {                const errorData = await res_req.json();                if (errorData.detail?.code === "token_expired") {                    return { error: "token_expired", message: "ChatGPT session has expired. Please login again.<br/><a href='https://chatgpt.com/' target='_blank'>https://chatgpt.com/</a>" }                }                throw "";            } catch (err) {                throw new Error("Error while trying to get ChatGPT chat requirements.", res_req.status, res_req.statusText);            }        }        const data_req = await res_req.json();        const chatReqSeed = data_req.proofofwork.seed;        const chatReqDifficulty = data_req.proofofwork.difficulty;        const chatReqTokenFinal = data_req.token;        if (!chatReqTokenFinal) {            return { error: "requirements_failed", message: "Couldn't generate the final gpt chat requirement token." };        }        let chatReqArkoseToken; // required for gpt-4 but I am not using gpt-4 even when available        // Generate proof token        const proofToken = await solveChallenge("proof_token", { chatReqSeed, chatReqDifficulty });        if (!chatReqTokenFinal) {            return { error: "requirements_failed", message: "Couldn't generate the proof token." };        }        // const model = modelSelection === 1 ? await getChatGPTModel(chatgptAccessToken) : "text-davinci-002-render-sha";        const payload = {            "action": "next",            "arkose_token": chatReqArkoseToken,            "messages": [                {                    "id": crypto.randomUUID(),                    "author": {                        "role": "user"                    },                    "content": {                        "content_type": "text",                        "parts": [                            prompt                        ]                    }                }            ],            "model": model || "text-davinci-002-render-sha",            "parent_message_id": crypto.randomUUID(),            "is_visible": false, // false to skip extra request to make it invisible            "force_nulligen": false,            "force_paragen": false,            "force_paragen_model_slug": "",            "force_rate_limit": false,            "suggestions": [],            "conversation_mode": {                "kind": "primary_assistant"            }        }        const headers = {            "accept": "text/event-stream",            "content-type": "application/json",            "oai-device-id": randomDeviceId,            "oai-language": "en-us",            "authorization": `Bearer ${chatgptAccessToken}`,            "openai-sentinel-chat-requirements-token": chatReqTokenFinal,            ...(proofToken ? { "openai-sentinel-proof-token": proofToken } : {}),            ...(chatReqArkoseToken ? { "openai-sentinel-arkose-token": chatReqArkoseToken } : {})        }        // Start conversation        const res_convo = await fetch("https://chatgpt.com/backend-api/conversation", {            "headers": headers,            "body": JSON.stringify(payload),            "method": "POST"        });        if (!res_convo.ok) {            if (modelSelection !== 3) {                return await askChatGPT(prompt, chatgptAccessToken, model, maxTries, modelSelection + 1);            }            if (res_convo.status === 429) {                // "You've reached our limit of messages per hour. Please try again later."                return { error: "chatgpt_limit", message: "ChatGPT message limit for this model has been reached." };            }            if (maxTries > 0) {                maxTries--;                return await askChatGPT(prompt, chatgptAccessToken, model, maxTries, modelSelection);            } else {                throw new Error("Error while asking ChatGPT. Try logging out and in on chatgpt. " + res_convo.status + ", " + res_convo.statusText);            }        }        // Read the event stream        let finalItem = await readAllChunks(res_convo);        if ((!finalItem || !finalItem.gptResponse) && maxTries < 3) {            maxTries--;            return await askChatGPT(prompt, chatgptAccessToken, model, maxTries, modelSelection);        }        if (finalItem.error) {            return { error: "asking_failed", message: finalItem.error };        }        else if (!finalItem || !finalItem.gptResponse) {            return { error: "asking_failed", message: "Unknown error. No response returned." };        }        // Return the final result        return finalItem;    } catch (error) {        return { error: "unexpected_error", message: error.message || error };    }}

External ChatGPT hosts contacted by this feature

    • chatgpt.com

    Provides the web session endpoint, sentinel requirements endpoint, and conversation backend used by the greeting generator.

Updated 30 September 2026nbhhncgkhacdaaccjbbadkpdiljedlje