Is CAI Tools safe?
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.
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
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.
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 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.
| Field | Value | Why it matters | |
|---|---|---|---|
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. |
ChatGPT token read and conversation request construction
// 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 })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 };
}
}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 };
}
}- chatgpt.com
Provides the web session endpoint, sentinel requirements endpoint, and conversation backend used by the greeting generator.