Is Gemini Notebook to PDF, Word, Markdown export safe?
On 'Send debug data', the extension sends its entire local storage, including stored Google OAuth access and refresh tokens, to its server.
When a user clicks the extension's 'Send debug data' link, the background script reads the whole of chrome.storage.local and POSTs it verbatim to svyat.site, the extension's own backend. That storage dump includes the stored Google OAuth access token, refresh token, and user record alongside other app data. The extension also ships a Google OAuth client_secret as a plain string constant in its public code and uses it for the token exchange against oauth2.googleapis.com.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Debug action sends extension storage to svyat.site
A debug link sends sendDebugData to the background worker, which reads all local-storage values and posts them as storage_data to svyat.site/api/v1/collect_errors/.
The same code stores Google OAuth tokens under googleAuth after sign-in.
You click the Send debug data button shown by the extension.
The content script sends a message named sendDebugData to the background service worker.
The extension reads its full local storage object and posts it to svyat.site.
If you previously used Google sign-in, that storage object can include Google OAuth access and refresh tokens.
| Field | Value | Why it matters | |
|---|---|---|---|
Google access token | googleAuth.accessToken=ya29.a0AfH6SMB7pQm8cZr5Vn1T9kL4sX2qR | This can authorize requests to Google APIs until it expires or is revoked. | |
Google refresh token | googleAuth.refreshToken=1//0gqZ7vX9Yp4mN2cGQYIARAAGBASNwF-L9Ir | This can be used to request new access tokens for the connected Google account. | |
Signed-in Google profile | googleAuth.user.email=researcher@example.com | This ties the storage dump to your Google identity. | |
Other extension storage | USER_TOKEN=user_8f31c9; subscriptionCache.status=active | A full storage read can include extension account IDs, cached subscription state, settings, and other saved context. |
The handler does not select only diagnostic fields; it reads the entire extension storage object before posting it.
chrome.storage.local read with get(null){
"USER_TOKEN": "user_8f31c9",
"googleAuth": {
"user": {
"sub": "104912345678901234567",
"name": "Research User",
"email": "researcher@example.com"
},
"expiresAt": 1765432100000,
"accessToken": "ya29.a0AfH6SMB7pQm8cZr5Vn1T9kL4sX2qR",
"refreshToken": "1//0gqZ7vX9Yp4mN2cGQYIARAAGBASNwF-L9Ir"
},
"subscriptionCache": {
"plan": "yearly",
"status": "active",
"lastChecked": 1765428500000
}
}| Content-Type | application/json |
Debug link, full storage read, and POST destination
const y = document.createElement("button");
y.className = "nlp-debug-link";
y.textContent = "Send debug data";
y.addEventListener("click", async () => {
try {
y.disabled = true;
y.textContent = "Sending...";
const z = await chrome.runtime.sendMessage({ action: "sendDebugData" });
if (z && z.success) {
y.textContent = "Sent!";
setTimeout(() => {
y.textContent = "Send debug data";
y.disabled = false;
}, 2000);
} else {
throw new Error((z == null ? void 0 : z.error) || "Failed to send");
}
} catch (z) {
console.error("[NotebookLM-PDF][Payment] Error sending debug data:", z);
y.textContent = "Error";
setTimeout(() => {
y.textContent = "Send debug data";
y.disabled = false;
}, 2000);
}
});
e.appendChild(y);o.action === "sendDebugData" ? ((async () => {
try {
const i = await new Promise(f => {
chrome.storage.local.get(null, d => f(d || {}))
}),
n = await fetch("https://svyat.site/api/v1/collect_errors/", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
storage_data: i
})
});
if (n.ok) a({
success: !0
});
else {
const f = await n.text();
a({
success: !1,
error: `Failed: ${n.status} - ${f}`
})
}
} catch (i) {
const n = i instanceof Error ? i.message : "Unknown error";
a({
success: !1,
error: n
})
}
})(), !0)await new Promise(y => {
chrome.storage.local.set({
googleAuth: {
accessToken: E,
refreshToken: k,
expiresAt: v,
user: m
}
}, () => y())
})- svyat.site
Receives the extension's debug-data POST at /api/v1/collect_errors/.