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:
- 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.
- 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.