Is Claude Tuner - Claude·ChatGPT·Gemini Tracker safe?
Claude Tuner sends snapshot submissions to its backend using a shared fallback API key.
Claude Tuner prepares snapshot POST requests to its backend API and includes authentication headers with those submissions. When no per-user bearer token is stored, the extension falls back to a shipped shared API key for requests to the snapshots endpoint.
Who publishes itDataMax - no other listings under this identity
DataMax - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Claude Tuner ships a hardcoded shared API key as its default auth credential
Claude Tuner embeds one API key in every install.
Until an install gets its own personal token, it authenticates heartbeat, preference, and usage-snapshot requests to the vendor's backend with that same hardcoded key instead.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You install Claude Tuner before it has issued your copy a personal login token.
This is the extension's normal state on first run and any time the per-install token is absent.
The extension authenticates its own backend requests with a single API key hardcoded into every copy of the extension.
The same literal value is sent as the X-API-Key header for heartbeat and preference requests, and as the _auth field in the body of snapshot uploads.
- Fallback API keyclaude-manager-dev-key-2024
Every install without a personal token authenticates with this exact value, the same one every other affected install also uses.
- Header name (heartbeat, preferences)X-API-Key
The field the key travels in for two of the three affected backend routes.
- Body field (snapshot uploads)_auth
Where the same key travels for usage-snapshot submissions, inside the JSON body instead of a header.
Where the fallback key is defined and used
bg/constants.js: the hardcoded literal
bg/constants.jsexport const DEFAULT_SERVER_URL = 'https://api.claudetuner.com';export const DEFAULT_API_KEY = 'claude-manager-dev-key-2024';bg/storage.js: getAuthHeaders() falls back to the literal
bg/storage.jsexport async function getAuthHeaders(config) { const extToken = await getExtToken(); if (extToken) { return { 'Authorization': `Bearer ${extToken}` }; } return { 'X-API-Key': config.apiKey };}bg/storage.js: simplePost() falls back to the same literal in the body
bg/storage.jsexport async function simplePost(config, url, payload) { const extToken = await getExtToken(); const response = await fetch(url, { method: 'POST', body: JSON.stringify({ ...payload, _auth: extToken || config.apiKey }), }); return { response, sentToken: extToken || null };}bg/storage.js: getConfig() seeds apiKey from the same default
bg/storage.jsexport async function getConfig() { return new Promise((resolve) => { chrome.storage.sync.get( { serverUrl: DEFAULT_SERVER_URL, apiKey: DEFAULT_API_KEY, intervalMinutes: DEFAULT_INTERVAL_MINUTES, intervalExplicitlySet: false, optimizationMode: 'notify_only', selectedOrgId: null }, resolve ); });}- api.claudetuner.com
The vendor's own backend. Accepts the shared fallback key as valid authentication for heartbeat, preference-sync, and usage-snapshot requests when no personal token is present.
Reads an unpacked copy of the extension and reports whether it still ships the hardcoded fallback API key, without sending any network traffic itself.
- Node.js 18+
// check_shared_key.js// Confirms whether an unpacked copy of Claude Tuner still ships the hardcoded// fallback API key described in this report. Reads local files only; makes// no network requests.//// Usage: node check_shared_key.js /path/to/unpacked-extensionconst fs = require('fs');const path = require('path');const PREVIOUSLY_OBSERVED_KEY = 'claude-manager-dev-key-2024';function readFile(extDir, rel) { const p = path.join(extDir, rel); return fs.existsSync(p) ? fs.readFileSync(p, 'utf8') : null;}const extDir = process.argv[2];if (!extDir) { console.error('Usage: node check_shared_key.js <unpacked-extension-dir>'); process.exit(1);}const constants = readFile(extDir, 'bg/constants.js');if (!constants) { console.error('bg/constants.js not found under ' + extDir); process.exit(1);}const match = constants.match(/DEFAULT_API_KEY\s*=\s*'([^']+)'/);if (!match) { console.log('No DEFAULT_API_KEY literal found. This build may no longer ship a fallback key.'); process.exit(0);}const shippedKey = match[1];console.log('Shipped fallback key:', shippedKey);console.log('Matches the key in this report:', shippedKey === PREVIOUSLY_OBSERVED_KEY);console.log('Any install without a personal token sends this exact value as:');console.log(' - the X-API-Key header on /api/heartbeat and /api/users/preferences');console.log(' - the _auth body field on /api/snapshots');- 1Unpack the extension's .crx (chrome://extensions in Developer Mode, or unzip the .crx directly).
- 2Run: node check_shared_key.js <unpacked-extension-dir>.
- 3Compare the printed key against the one this report cites.
Where it sends data
Destinations our analysis observed Claude Tuner - Claude·ChatGPT·Gemini Tracker 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.
- api.claudetuner.com
Claude Tuner - Claude·ChatGPT·Gemini Tracker sends data to api.claudetuner.com. No other extension we have analysed sends data here.