Is Corgi AI - Your language teacher safe?

Medium risk

Corgi AI ships hardcoded Voicemaker and Google Analytics credentials in its extension bundle.

The extension includes a Voicemaker bearer API key and Google Analytics Measurement Protocol secret in its installed JavaScript. Its text-to-speech requests send the Voicemaker key to developer.voicemaker.in, and analytics requests send the Google Analytics secret to www.google-analytics.com.

Corgiv1.7.3Chrome Web Store
48Risk

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

Publishers can request a review.

Findings

Corgi AI ships live Voicemaker and Google Analytics keys in its code

Corgi AI's background script contains a hardcoded Voicemaker API key and a Google Analytics API secret, identical in every install.

The Voicemaker key still worked when replayed outside the extension, confirming it is live.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-522
Source
Dynamic sandbox
What actually happens
You did this

You select a word or phrase and click the pronunciation button to hear it read aloud.

The extension did this

The extension authenticates to a third-party text-to-speech vendor using an API key that is hardcoded into every copy of the extension.

The key is not generated per user or per session; it is the same value in every install.

Captured request
POSThttps://developer.voicemaker.in/voice/api

HTTP 200 with success:true and a remaining-quota counter, confirming the key extracted from the shipped bundle is a live, currently valid, metered vendor credential that works with no login and no extension context.

Headers
Content-Type
application/json
Authorization
Bearer <redacted>
Body
{  "VoiceId": "ai3-Jony",  "LanguageCode": "en-US",  "Text": "hello",  "OutputFormat": "mp3",  "SampleRate": "48000",  "Effect": "default",  "MasterSpeed": "0",  "MasterVolume": "0",  "MasterPitch": "0"}
The code that does this

The vendor secrets object, inlined three separate times in the shipped bundle

Readable version
// The bundler inlines this same object literal three separate times.// Written out once here for clarity; the shipped code repeats it verbatim.const VENDOR_SECRETS = {  VOICEMAKER_API_KEY: "<redacted>",  GA_MEASUREMENT_ID: "G-3RDMY7F6D8",  GA_API_SECRET: "<redacted>",};headers['Authorization'] = `Bearer ${VENDOR_SECRETS.VOICEMAKER_API_KEY}`;fetch(`${GA_ENDPOINT}?measurement_id=${VENDOR_SECRETS.GA_MEASUREMENT_ID}&api_secret=${VENDOR_SECRETS.GA_API_SECRET}`, {  method: 'POST',  body: JSON.stringify({ client_id, events: [{ name: eventName, params: eventData }] }),});
What actually happens
You did this

You use any normal feature of the extension, such as completing a translation or opening the popup.

The extension did this

The extension logs the usage event to Google Analytics using a measurement ID and API secret that are identical in every install.

The API secret is sent in plain text in the request URL to Google's Measurement Protocol endpoint.

Where the hardcoded credentials are sent
    • developer.voicemaker.in

    Third-party text-to-speech vendor. Receives the hardcoded bearer key on every audio request, billed against Voicemaker's own metered usage plan.

    • www.google-analytics.com

    Google Analytics Measurement Protocol collector. Receives the hardcoded measurement ID and API secret with every usage event.

Check if you're affected

Scans a directory of extracted extension JavaScript for literal strings assigned to API-key- or credential-shaped variable names, the same pattern that exposed this extension's Voicemaker key.

Requires
  • Node.js 18+
find-hardcoded-secrets.js · js
#!/usr/bin/env node// find-hardcoded-secrets.js// Usage: node find-hardcoded-secrets.js <path-to-extracted-extension-dir>const fs = require('fs');const path = require('path');const SECRET_NAME = /(API[_-]?KEY|SECRET|TOKEN|BEARER)/i;const ASSIGNMENT = /["']?([A-Za-z0-9_]{3,40})["']?\s*:\s*["']([A-Za-z0-9\-_.]{12,80})["']/g;function scanFile(filePath) {  const text = fs.readFileSync(filePath, 'utf8');  const hits = [];  let match;  while ((match = ASSIGNMENT.exec(text)) !== null) {    const [, name, value] = match;    if (SECRET_NAME.test(name)) {      hits.push({ name, value, index: match.index });    }  }  return hits;}function walk(dir, cb) {  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {    const full = path.join(dir, entry.name);    if (entry.isDirectory()) walk(full, cb);    else if (/\.(js|mjs)$/.test(entry.name)) cb(full);  }}const target = process.argv[2];if (!target) {  console.error('Usage: node find-hardcoded-secrets.js <path-to-extracted-extension-dir>');  process.exit(1);}let total = 0;walk(target, (file) => {  const hits = scanFile(file);  for (const hit of hits) {    total += 1;    console.log(`${file}: ${hit.name} = "${hit.value.slice(0, 6)}..." (offset ${hit.index})`);  }});console.log(`\n${total} candidate hardcoded secret(s) found.`);
How to run it
  1. 1node find-hardcoded-secrets.js <extension-dir>.
  2. 2Review each printed KEY/TOKEN hit.
  3. 3Revoke and reissue it server-side instead of embedding it client-side.

What it can do

Permissions this extension asks for, as declared in version 1.7.3. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    http://*/*

  • Read and change your data on every secure site you visit

    https://*/*

  • See the address and title of every tab you have open

    tabs

  • Store data in your browser

    storage

  • Store an unlimited amount of data in your browser

    unlimitedStorage

  • Sign you in with your Google account

    identity

  • See the email address of your Google account

    identity.email

Where it sends data

Destinations our analysis observed Corgi AI - Your language teacher 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.

  • www.google-analytics.comwidely used

    Corgi AI - Your language teacher sends data to www.google-analytics.com. A widely used service: 346 other extensions we have analysed send data here.

  • developer.voicemaker.in

    Corgi AI - Your language teacher sends data to developer.voicemaker.in. No other extension we have analysed sends data here.

Updated 30 September 2026jgabolakboecklnmocdljjcdkkhjigck