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.
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.
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.
ID: extension-data-privacy.storage-security.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 in chrome.storage.sync without encryption.
Pass criteria: Count all chrome.storage.sync.set calls and list the keys stored. chrome.storage.sync is only used for non-sensitive data (preferences, settings, UI state) with 0% sensitive values. Any sensitive data (passwords, tokens) uses chrome.storage.local with encryption or is not synced at all.
Fail criteria: Bearer tokens, API keys, or passwords found in chrome.storage.sync without 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.local for 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.local with encryption.