Frontend Labs
⋯

Part XII — Client-side security, authentication and the OWASP lists in JavaScript

Part VII showed what client-side encryption can and can't protect against, and §51 covered the browser's own defenses. This Part is the application side: the mistakes JavaScript developers actually ship, the code that prevents each one, and the tests that keep it prevented. Every defense here is implemented in Support Desk (§63) and asserted by its Playwright suite (§77).

64. The browser threat model, and the OWASP "top 20"

People often ask for the "OWASP Top 20". There is no single list by that name. For a modern JavaScript application with an AI feature, two OWASP lists apply, and together they make twenty risks:

  • OWASP Top 10:2025: the web application risks. It was released at OWASP Global AppSec in November 2025, replacing the 2021 edition.
  • OWASP Top 10 for LLM Applications 2025: the risks specific to apps that call language models.
# Risk Where it bites a JavaScript app Chapter
A01 Broken Access Control (now includes SSRF) IDOR in APIs, "admin" checks only in the UI, CORS reflecting any origin §65
A02 Security Misconfiguration missing CSP/HSTS/COOP, public source maps, debug routes in prod §65
A03 Software Supply Chain Failures (new) compromised npm packages, hijacked CDN scripts, install scripts §65
A04 Cryptographic Failures Math.random() tokens, secrets in bundles, homemade crypto §65, §46
A05 Injection DOM XSS sinks, prototype pollution, NoSQL/SQL injection in Node §65
A06 Insecure Design refund-twice logic, no limits on business flows §65
A07 Authentication Failures brute force, session fixation, tokens in localStorage §65, §67
A08 Software or Data Integrity Failures no SRI, unchecked postMessage, JWT alg: none §65
A09 Security Logging and Alerting Failures no CSP reports, no client error telemetry, secrets in logs §65
A10 Mishandling of Exceptional Conditions (new) fail-open catch blocks, stack traces to clients, crashed Node processes §65
LLM01 Prompt Injection instructions hidden in pages, emails or docs the agent reads §66
LLM02 Sensitive Information Disclosure PII and secrets sent to the model or echoed back §66
LLM03 Supply Chain unverified model weights, poisoned packages §66
LLM04 Data and Model Poisoning tampered RAG documents and fine-tuning data §66
LLM05 Improper Output Handling model output rendered as HTML, run as SQL or code §66
LLM06 Excessive Agency agents with more tools and permissions than the task needs §66
LLM07 System Prompt Leakage secrets or authorization rules inside the prompt §66
LLM08 Vector and Embedding Weaknesses cross-tenant retrieval, leaky embeddings §66
LLM09 Misinformation confident wrong answers presented as facts §66
LLM10 Unbounded Consumption no token, rate or cost limits §66, §62

The threat model, drawn

                       ┌──────────────── your origin (https://app.example) ────────────────┐
  malicious site ──────┤ CSRF, clickjacking, postMessage spoofing, XS-Leaks                │
  (any tab)            │                                                                    │
                       │   your JS  ◄── npm packages / CDN scripts (A03: supply chain)      │
  network ─────────────┤   DOM      ◄── data from APIs, URLs, storage, model output (A05,   │
  (Wi-Fi, proxy)       │                LLM05: everything that can become markup)           │
                       │   storage  ◄── extensions and XSS can read localStorage/IndexedDB   │
                       └───────┬────────────────────────────────────────────────────────────┘
                               │ fetch with cookies / tokens
                       ┌───────▼──────── server / edge ─────────┐
                       │ the ONLY place security decisions are   │
                       │ enforced (A01, A06, A07, LLM06)         │
                       └─────────────────────────────────────────┘

Two principles cover most of the Part:

  1. The browser is not a trust boundary. Anything in client JavaScript (hidden buttons, disabled fields, prices, roles in a JWT you decode client-side, an agent's "decision") can be changed by the user with DevTools. The client gives good UX and defense in depth; the server enforces.
  2. XSS is game over (§47). Script running in your origin can do anything your code can: call your APIs with the user's cookies, read storage, ask your crypto worker to decrypt. CSP, Trusted Types and context-aware output handling prevent XSS. Nothing on the client can survive it.

Generated from real-life-JS-guide.md · 8 Oct 2026 16:36