chrome.storage.sync not used for unencrypted passwords or secrets
Why it matters
chrome.storage.sync transmits data to Google's servers and replicates it across every browser the user is signed into. Storing an unencrypted API key, OAuth token, or password in sync storage means that credential is now held by Google and replicated to potentially untrusted devices. CWE-312 (Cleartext Storage of Sensitive Information) and CWE-313 (Cleartext Storage in a File or on Disk) both apply — the data is transmitted and stored by a third party outside the developer's control. OWASP 2021 A02 and GDPR Art. 32 require appropriate encryption for data at rest; syncing credentials in plaintext fails both standards.
Severity rationale
Medium because unencrypted secrets in `chrome.storage.sync` are transmitted to Google's infrastructure and replicated to all the user's signed-in browsers — a single compromised device in the sync chain exposes the credential everywhere.
Remediation
Never store passwords, tokens, or API keys in chrome.storage.sync. Use chrome.storage.local with encryption for any sensitive value:
// BAD — syncs plaintext secret to Google's servers
chrome.storage.sync.set({ apiKey: 'sk-abc123' });
// GOOD — stays local, encrypted at rest
import { encrypt } from './crypto-utils.js';
const encrypted = await encrypt('sk-abc123', derivedKey);
chrome.storage.local.set({ encryptedApiKey: encrypted });
For non-sensitive preferences (theme, language, UI state), chrome.storage.sync is appropriate. Draw the line at any value that grants access to an external service or identifies the user.
Detection
-
ID:
no-sync-secrets -
Severity:
medium -
What to look for: Examine uses of
chrome.storage.sync(which syncs data across user devices via Google account). Check whether any password, API key, auth token, or other sensitive secret is stored inchrome.storage.syncwithout encryption. -
Pass criteria: Count all
chrome.storage.sync.setcalls and list the keys stored.chrome.storage.syncis only used for non-sensitive data (preferences, settings, UI state) with 0% sensitive values. Any sensitive data (passwords, tokens) useschrome.storage.localwith encryption or is not synced at all. -
Fail criteria: Bearer tokens, API keys, or passwords found in
chrome.storage.syncwithout encryption. Sensitive data is transmitted to Google's servers for sync. -
Skip (N/A) when: The extension does not use
chrome.storage.sync, or it only stores non-sensitive preferences. -
Detail on fail: Name the sensitive data. Example:
"API key stored in chrome.storage.sync without encryption — will sync across user devices via Google account"or"OAuth token saved to chrome.storage.sync, exposing authentication across synced browsers." -
Remediation: Use
chrome.storage.localfor sensitive data:// BAD chrome.storage.sync.set({ apiKey: 'secret' }); // GOOD chrome.storage.local.set({ encryptedApiKey: encryptedValue });Or don't sync sensitive data at all; keep it in memory or only in
chrome.storage.localwith encryption.
External references
- cwe · CWE-312 — Cleartext Storage of Sensitive Information
- cwe · CWE-313 — Cleartext Storage in a File or on Disk
- owasp:2021 · A02 — Cryptographic Failures
- nist:rev5 · SC-28 — Protection of Information at Rest
- gdpr · Art. 32 — Security of processing
Taxons
History
- 2026-04-18·v1.0.0·Initial import from extension-data-privacy·automated