Lesson 06
Security fundamentals
XSS, CSRF, CSP, JWT pitfalls. iGaming = audited. Get these right or fail compliance.
1 · XSS — Cross-Site Scripting
🧠 in plain english
Imagine a graffiti artist tagging the bathroom wall of your store. Now every customer sees the tag (e.g. “visit my site”) and some click it. XSS = the attacker injects JavaScript into your page that runs in another user's session. If they steal cookies, they hijack the user's account.
- Stored XSS — attacker saves payload in DB (e.g. profile bio), served to other users.
- Reflected XSS — payload in URL/query, echoed unsafely (e.g.
?q=<script>). - DOM-based XSS — JS reads from
location.hashand writes toinnerHTML.
React escapes by default. The only way to break it is
dangerouslySetInnerHTML with user input. Don't do that. Use a sanitizer like DOMPurify if you must render user HTML.2 · CSRF — Cross-Site Request Forgery
🧠 in plain english
Attacker sends you a link: “cute kittens”. You click. Behind the scenes, the page silently submits a form to your bank:
POST /transfer to=attacker amount=1000. Your browser includes your bank cookies. Boom. Money gone.SameSite cookies tell the browser “don't send these cookies on cross-site requests”.3 · CSP — Content Security Policy
🧠 in plain english
CSP = a bouncer at the door of your website. “Only let scripts from these specific URLs run. Block inline scripts. Block scripts from random other origins.” If an XSS payload tries to load a malicious script, the bouncer says no.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'; style-src 'self' 'unsafe-inline'; img-src 'self' https://cdn.example.com data:; connect-src 'self' wss://realtime.example.com; frame-src https://stripe.com https://game-vendor.com;
Use nonces or hashes for any inline scripts. Avoid
unsafe-inline in script-src.4 · JWT in localStorage = mistake
🧠 in plain english
Putting your JWT in
localStorage is like leaving your house key under the doormat. Any JS on your page can grab it (and any XSS gets in). HttpOnly cookies = the key is in a vault only the browser can open and only when sending it back to your server.localStorageis JS-readable → any XSS exfiltrates the token. Game over.- Use HttpOnly + Secure + SameSite=Lax cookie. JS can't read it. Browser sends it automatically.
- CSRF mitigated with SameSite + double-submit token if needed.
- Sensitive ops (deposits, withdrawals) should require step-up auth — re-auth or 2FA challenge.
📣 say this in the interview
“I never store JWTs in localStorage. Use HttpOnly + Secure + SameSite=Lax cookies. JavaScript can't read them, so XSS can't exfiltrate the token. CSRF is mitigated by SameSite plus a double-submit token for state changes.”
5 · OAuth 2.0 — code flow vs PKCE
🧠 in plain english
OAuth code flow assumes you have a server with a secret. SPA / mobile apps can't hide a secret in their bundle. PKCE adds a client-generated random verifier that gets sent back to the OAuth provider — proves you're the same client without needing a stored secret.
6 · PAM-specific security
- Idempotency keys on money ops — replay-safe (already covered in PAM lesson).
- Rate limiting on bet placement, login attempts, withdrawal requests.
- Geofencing — wrong jurisdiction = lose license. Edge middleware for region check, never client-side.
- KYC tokens — server-only, never exposed to client. SSR / RSC for KYC flow.
- Audit log on every state change. Regulators want this.
- VPN / proxy detection for fraud + jurisdiction enforcement.
⚡ quick check
A bot floods your login endpoint with 1000 attempts/sec from rotating IPs. Which is the BEST defense?