crypto.subtle Is Undefined — Secure Context Required
Fix crypto.subtle being undefined by serving over HTTPS or localhost, since the Web Crypto API is restricted to secure contexts.
Symptoms
- TypeError: Cannot read properties of undefined (reading 'digest')
- Web Crypto works locally but not on the staging server
- An app served over plain http:// cannot hash or encrypt
Possible causes
- The page is not a secure context (HTTP origin other than localhost)
- The code accesses window.crypto.subtle without a feature check
- An old or embedded browser lacks Web Crypto support
Diagnosis steps
Check the secure-context flag
console.log(window.isSecureContext, window.crypto?.subtle)Interpretation
isSecureContext false or subtle undefined confirms the environment, not your code.
Serve over HTTPS or localhost
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 1Interpretation
A quick self-signed cert makes the origin secure so subtle becomes available.
Root cause
The Web Crypto API exposes crypto.subtle only in secure contexts (HTTPS, localhost, or file). On an insecure origin, window.crypto exists for getRandomValues but subtle is undefined, so calls throw.
Fix
Serve the app over HTTPS in all non-local environments, feature-detect crypto.subtle before use, and provide a server-side fallback when the API is unavailable.
Risk note
Falling back to a non-cryptographic hash for security purposes is dangerous; only fall back for non-security uses.
Verify the fix
Load the page over HTTPS and confirm isSecureContext is true and crypto.subtle.digest resolves; test that HTTP origins still show a clear fallback message.
Symptoms
This guide profiles the failure behind “crypto.subtle Is Undefined — Secure Context Required”. It walks through the observable symptoms, a reproducible diagnosis path, the underlying root cause, the concrete fix, and how to verify the change and prevent a regression.
Observed symptoms include:
- TypeError: Cannot read properties of undefined (reading ‘digest’)
- Web Crypto works locally but not on the staging server
- An app served over plain http:// cannot hash or encrypt
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Check the secure-context flag
console.log(window.isSecureContext, window.crypto?.subtle)
isSecureContext false or subtle undefined confirms the environment, not your code.
Step 2: Serve over HTTPS or localhost
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 1
A quick self-signed cert makes the origin secure so subtle becomes available.
Likely contributors, in order of frequency:
- The page is not a secure context (HTTP origin other than localhost)
- The code accesses window.crypto.subtle without a feature check
- An old or embedded browser lacks Web Crypto support
Root Cause
The Web Crypto API exposes crypto.subtle only in secure contexts (HTTPS, localhost, or file). On an insecure origin, window.crypto exists for getRandomValues but subtle is undefined, so calls throw.
The Fix
Serve the app over HTTPS in all non-local environments, feature-detect crypto.subtle before use, and provide a server-side fallback when the API is unavailable.
Watch out: Falling back to a non-cryptographic hash for security purposes is dangerous; only fall back for non-security uses.
if (window.isSecureContext && window.crypto?.subtle) {
const enc = new TextEncoder();
const hash = await crypto.subtle.digest('SHA-256', enc.encode('data'));
console.log([...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, '0')).join(''));
} else {
// secure context required; fall back or ask the user to use HTTPS
console.warn('crypto.subtle unavailable: secure context required');
}
Verify and Prevent
Load the page over HTTPS and confirm isSecureContext is true and crypto.subtle.digest resolves; test that HTTP origins still show a clear fallback message.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.