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.5.7Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

ChatGPT token used for extension prompts

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.

01EvidenceCAUSE EFFECT
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.

02EvidenceNETWORK CAPTURE
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.
03EvidenceNETWORK CAPTURE
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.
04EvidenceNETWORK CAPTURE
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.
05EvidenceFIELD TABLE
Values the extension reads or sends in the ChatGPT path
FieldValueWhy it matters
ChatGPT access token
Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImNoYXRncHQtd2ViIn0.eyJzdWIiOiJ1c2VyXzEyMzQ1IiwiYXVkIjoid2ViIn0.RXhhbXBsZVNpZ25hdHVyZUZvckJhY2tmaWxsThis 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-7342de9eec40This value makes the request look like it came from a particular ChatGPT web device session.
Sentinel proof tokens
openai-sentinel-proof-token: gAAAAABWyIxMMiwiVHVlIEp1bCAxNCAyMDI2IiwwLDQyLCJNb3ppbGxhLzUuMCJdThese values satisfy ChatGPT's request checks before the conversation is submitted.
Visibility flag
is_visible: falseThis marks the generated turn as not visible in the ChatGPT conversation UI.
06EvidenceCODE COMPARE
The code that does this

ChatGPT token read and conversation request construction

What it actually does
Popup trigger for the ChatGPT greeting featuredeobfuscated/src/popup/popup.js
// Get prompt, import char settings, import persona, import special instructions
let 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 tokendeobfuscated/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 token
async 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 requestdeobfuscated/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 };
    }
}
07EvidenceTHIRD PARTY LIST
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 17 September 2026nbhhncgkhacdaaccjbbadkpdiljedlje