← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Web Crypto API

JavaScript ES2015 Advanced
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list eslint and semgrep as the tools. Misuse of Math.random() for crypto or use of third-party JS crypto libraries instead of Web Crypto can be caught by semgrep rules or ESLint security plugins, but these are not default linter rules — they require specialist configuration. Not d3 because the pattern isn't caught by a default linter setup, and not d7 because automated tooling (semgrep) can reliably surface the common patterns.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix indicates replacing Math.random() with crypto.getRandomValues() or swapping a third-party library for crypto.subtle calls. This is typically a targeted replacement within one component or module — not a one-liner (requires understanding the API and adapting call sites), but not a cross-cutting refactor either. Hardcoded IV or AES-CBC without MAC mistakes may require a few co-located changes, keeping this at e3.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to context is web only, and the choice of how to implement client-side crypto is generally localised to a crypto utility module or specific feature (e.g. e2e encryption). It doesn't impose a codebase-wide tax — most application code is unaffected. However, if non-extractable keys and IndexedDB are used, it does impose some ongoing complexity in that component, so b3 is appropriate rather than b1.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception is explicit: developers believe Math.random() and crypto.getRandomValues() are equivalent for security purposes. This directly contradicts how randomness is conceptually understood — 'random is random' — when in fact Math.random() is deterministic and predictable. Additional traps include assuming AES-CBC is safe without a MAC, and reusing IVs. These are well-documented gotchas that contradict intuition from general programming contexts, placing this at t7.

About DEBT scoring →

Also Known As

crypto.subtle SubtleCrypto Web Crypto browser crypto CSPRNG browser

TL;DR

Browser-native cryptographic operations — crypto.subtle provides AES-GCM encryption, ECDSA signing, PBKDF2 key derivation, and SHA digests without external libraries.

Explanation

Web Crypto API (crypto.subtle): digests (SHA-256/384/512), key generation (AES-GCM, RSA-OAEP, ECDSA), encryption/decryption (AES-GCM), signing/verification (RSA-PSS, ECDSA), key derivation (PBKDF2, HKDF), key import/export. All operations are async (Promise-based) and work with ArrayBuffer. crypto.getRandomValues() provides cryptographically secure random bytes synchronously. CryptoKey objects are non-extractable by default — prevents key material from leaking to JavaScript variables.

Common Misconception

Math.random() and crypto.random() are equivalent for security — Math.random() is not cryptographically secure and is predictable; always use crypto.getRandomValues() for any security-sensitive random data.

Why It Matters

End-to-end encrypted browser applications require browser-native cryptography — Web Crypto provides standardised, hardware-accelerated operations with non-extractable keys, removing the need for untrusted third-party crypto libraries.

Common Mistakes

  • Math.random() for tokens, IDs, or any security-sensitive randomness
  • Storing private keys in localStorage — use non-extractable CryptoKey with IndexedDB
  • Not using authenticated encryption (AES-GCM) — AES-CBC without MAC allows ciphertext tampering
  • Hardcoded IVs — always generate a unique random IV per encryption operation

Code Examples

✗ Vulnerable
// Math.random for crypto — predictable and insecure:
const token = Math.random().toString(36).substring(2);
// Token can be predicted with knowledge of the PRNG state
✓ Fixed
// Cryptographically secure random token:
const bytes = crypto.getRandomValues(new Uint8Array(32));
const token = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');

// AES-GCM authenticated encryption:
async function encrypt(plaintext, key) {
    const iv      = crypto.getRandomValues(new Uint8Array(12)); // Unique per message
    const encoded = new TextEncoder().encode(plaintext);
    const ciphertext = await crypto.subtle.encrypt(
        { name: 'AES-GCM', iv },
        key,        // CryptoKey — non-extractable
        encoded
    );
    return { iv, ciphertext }; // Store IV alongside ciphertext
}

Added 16 Mar 2026
Edited 22 Mar 2026
Views 123
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 0 pings S 0 pings M
No pings yet today
No pings yesterday
ChatGPT 13 Google 10 Amazonbot 9 Ahrefs 9 SEMrush 6 Perplexity 5 PetalBot 4 Unknown AI 3 Scrapy 3 Applebot 3 Bing 2 Majestic 1 Claude 1 Meta AI 1 Twitter/X 1 Brave Search 1
crawler 68 crawler_json 4
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
JavaScript javascript The programming language of the browser — it reads and modifies the page (the DOM), reacts to user events, and fetches data without reloading.

JavaScript is the only language browsers execute, so every interactive behaviour on the web goes through it. Its two defining traits — single-threaded event loop and loose typing (== coercion) — explain the majority of both its bugs and its design patterns.

💡 Default to const, use === always, and reach for let only when a value genuinely reassigns.

Ask Codex about JavaScript →
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Use the Web Crypto API (crypto.subtle) for client-side cryptography — it's native, hardware-accelerated, and avoids shipping a JS crypto library; use for hashing, signing, and key derivation in the browser
📦 Applies To
javascript ES2015 web
🔗 Prerequisites
🔍 Detection Hints
Third-party JS crypto library (CryptoJS, forge) when Web Crypto API would suffice; Math.random() for cryptographic purposes in browser
Auto-detectable: ✓ Yes eslint semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-327 CWE-338


✓ schema.org compliant