How do you design a secure PWA for sensitive data?
Progressive Web App (PWA) Developer
answer
A secure PWA starts with universal HTTPS enforcement (HSTS, upgrade-insecure-requests) and a strict Content Security Policy that forbids inline scripts, limits sources, and uses nonces. Store secrets with WebAuthn or OS-backed Credential Management and keep tokens short-lived in memory, never long-term in localStorage. Use CSRF tokens for cookie sessions or avoid cookies with header-only Bearer tokens. Harden service workers, sanitize user input, escape output, and lock down permissions and install prompts.
Long Answer
Designing a secure PWA for sensitive data means assuming hostile networks and untrusted browsers, then applying layered controls that reduce attack surface and impact. The pillars are HTTPS enforcement, safe credential storage, strict Content Security Policy, and comprehensive mitigations for XSS and CSRF, all aligned with least privilege and zero trust.
1) HTTPS enforcement everywhere
All PWA features (service workers, push, Background Sync) require secure contexts, so force HTTPS at every layer. Use HSTS with preload on apex and subdomains to prevent downgrade attacks. Add upgrade-insecure-requests and eliminate mixed content. Ensure the service worker is served over HTTPS and pinned to a narrow scope (for example, /app/), so it cannot intercept unrelated paths.
2) Authentication and credential storage
Never persist long-lived secrets in localStorage or IndexedDB. Prefer WebAuthn passkeys for phishing-resistant login. For session models, use HttpOnly, Secure, SameSite cookies plus CSRF tokens. For pure API models, send short-lived access tokens in Authorization: Bearer headers and store them only in memory; refresh with a secure, rotation-based flow using an httpOnly cookie or a one-time code exchange. If the Credential Management API is used, restrict to federated credentials or public key credentials; never auto-replay passwords without explicit user intent.
3) Content Security Policy that blocks injection
A strong CSP is the cheapest insurance against XSS in a secure PWA. Disallow unsafe-inline and unsafe-eval. Use nonces or hashes for every script; deny dynamic script creation where possible. Restrict connect-src to required API origins, img-src and media-src to trusted CDNs, and frame-ancestors 'none' to prevent clickjacking. Send require-trusted-types-for 'script' and define Trusted Types policies to neuter DOM injection sinks in modern browsers. Combine with Referrer-Policy, Permissions-Policy, and X-Content-Type-Options: nosniff.
4) XSS prevention in code and templates
CSP helps, but XSS must be prevented at the source. Encode output contextually (HTML, attribute, URL). Sanitize rich text with an allowlist sanitizer and store only the cleaned version. Avoid dangerouslySetInnerHTML and direct innerHTML; route dynamic content through safe templating. Validate and normalize all inputs at boundaries; apply strict types and length limits to reduce gadget surface.
5) CSRF models for browser flows
If you use cookie-based sessions, issue per-request CSRF tokens tied to the session and verify on every state-changing request. Keep SameSite=Lax or SameSite=Strict for cookies, and combine with double-submit or token-in-header patterns. For token-based APIs, do not send cookies across origins; require header-only authentication to remove CSRF risk entirely.
6) Service worker hardening
The service worker is powerful and persistent. Scope it narrowly, audit fetch handlers, and avoid caching authenticated API responses indiscriminately. Encrypt at rest is not available in the cache, so cache only public assets and employ cache keys that exclude credentials. Validate responses before caching, implement cache poisoning protections (origin checks), and provide a kill switch: versioned service workers that immediately skipWaiting() and clients.claim() on security updates.
7) Least privilege for PWA capabilities
Ask for minimal permissions and only at the point of need. Gate notifications, geolocation, and sensors behind user actions and clear value. Restrict manifest.json to required scopes; avoid wide scope that could intercept sensitive routes. For installability, ensure the app will function in a reduced-privilege mode if installation is declined.
8) Secure transport and zero trust
Use modern TLS, certificate pinning via Expect-CT history or platform features, and mutual Transport Layer Security for enterprise endpoints if applicable. Treat every request as untrusted: validate authorization on the server, enforce fine-grained scopes, and bind tokens to device or session context where possible. Keep server-side audit logs for authentication, token rotation, and permission escalations.
9) Storage and offline constraints
A secure PWA should minimize sensitive data stored offline. If regulatory requirements permit, store only opaque identifiers or encrypted blobs without keys in the browser. For document caches, adopt per-user cache partitions keyed by a non-extractable session binding and apply strict eviction on sign-out. Never rely on client-side encryption alone for compliance; sensitive processing belongs server-side.
10) Monitoring, headers, and response hygiene
Send Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy when applicable to isolate browsing contexts. Use Cache-Control: private, no-store for authenticated responses to prevent proxy caching. Implement Subresource Integrity for static scripts and styles. Monitor CSP reports, network errors, and service worker exceptions with telemetry that redacts PII. Add anomaly alerts for sudden CSP violations, push permission spikes, or token-reuse events.
11) Secure build and dependency hygiene
Lock dependencies, enable supply-chain scanning, and serve only hashed, immutable assets. Use template linting that flags inline handlers and dangerous sinks. In CI, fail builds if CSP nonces are missing, SRI is absent, or bundle contains eval. Regularly rotate keys and secrets, and invalidate old service workers on key changes.
12) Incident response and rollback
Pre-plan revocation: global sign-out, cookie invalidation, service worker hot replacement, and token chain revocation. Provide a read-only degraded mode if authentication fails. Document recovery runbooks and practice them.
This layered blueprint delivers a secure PWA that preserves usability while defending sensitive data: strict HTTPS, rigorous CSP, careful credential storage, robust XSS/CSRF protections, hardened service workers, and disciplined permissions—backed by monitoring and rapid response.
Table
Common Mistakes
Storing long-lived access tokens in localStorage or IndexedDB, enabling trivial theft via XSS. Allowing inline scripts or unsafe-eval in CSP, nullifying defenses. Mixing cookie sessions with permissive Cross-Origin Resource Sharing and forgetting CSRF tokens. Overbroad service worker scope that intercepts sensitive routes and caches private responses. Requesting notifications or sensors on first load, training users to click “Allow.” Caching personalized API responses with Cache-Control: public. Shipping third-party scripts without Subresource Integrity and tight CSP. Treating offline as a license to store sensitive data unencrypted. Failing to rotate tokens and keys or to provide a kill switch for compromised service workers.
Sample Answers (Junior / Mid / Senior)
Junior:
“I enforce HTTPS and HSTS for the whole site. I keep access tokens in memory and use httpOnly cookies for refresh. My CSP uses nonces and blocks inline scripts. For cookie sessions I verify a CSRF token on every write. The service worker caches only public assets.”
Mid:
“I implement WebAuthn for strong authentication, memory-only Bearer tokens, and rotation-based refresh. CSP has nonces, Trusted Types, and strict connect-src. Cookies are SameSite and I add a per-request CSRF header. The service worker scope is /app/, fetch handlers validate origin, and I use SRI for third-party assets.”
Senior:
“I design a zero-trust secure PWA: HSTS preload, strict CSP with nonces and Trusted Types, WebAuthn plus least-privilege tokens in memory, and cookie flows with strong CSRF. The service worker never caches authenticated responses and can be revoked instantly. Permissions are requested only on action. Monitoring ingests CSP reports and service worker crashes, and incident runbooks cover global sign-out and hot replacement.”
Evaluation Criteria
Strong answers enforce HTTPS with HSTS, forbid inline scripts with nonce-based CSP, and store credentials safely (WebAuthn, httpOnly refresh, memory-only access tokens). They distinguish CSRF models: tokens for cookie sessions, header-only tokens for APIs. They scope and harden the service worker, avoid caching private data, apply SRI and restrictive headers, and ask for permissions only when needed. They mention monitoring (CSP reports, service worker telemetry) and incident playbooks. Red flags: localStorage tokens, unsafe-inline CSP, no CSRF for cookie flows, broad service worker scope, and caching authenticated responses.
Preparation Tips
Build a demo secure PWA that logs in with WebAuthn plus a short-lived access token stored in memory and a rotation-based refresh in an httpOnly cookie. Add a nonce-based CSP (no inline or eval), Trusted Types, SRI on scripts, and frame-ancestors 'none'. Implement cookie sessions with per-request CSRF tokens on writes, and a token-only API path without cookies. Scope the service worker to /app/, cache only static assets, and add a versioned kill switch. Configure HSTS preload, nosniff, Permissions-Policy, and strict connect-src. Instrument CSP report endpoints and service worker error logging. Run Lighthouse and a security scanner; verify mixed-content failures and CSP violations are blocked in CI.
Real-world Context
A healthcare secure PWA removed localStorage tokens after a minor XSS revealed theft risk; switching to memory-only access tokens and httpOnly refresh limited exposure and allowed instant revocation. A fintech tightened CSP with nonces and Trusted Types, eliminating entire classes of content injection and reducing bug bounty findings by half. An e-commerce PWA once cached authenticated responses; scoping the service worker and caching only public assets fixed leakage and improved Core Web Vitals. Across teams, HSTS preload and precise permission prompts reduced social engineering risk, while CSP report monitoring enabled rapid detection of regressions.
Key Takeaways
- Enforce HTTPS end to end with HSTS and no mixed content.
- Store credentials safely: WebAuthn, memory-only access tokens, httpOnly refresh.
- Use strict CSP with nonces and Trusted Types; add SRI.
- Choose the right CSRF model: tokens for cookies or header-only auth for APIs.
- Harden service workers, minimize permissions, and monitor with CSP and telemetry.
Practice Exercise
Scenario:
You are shipping a secure PWA that shows sensitive account data, supports offline shell, and must resist XSS and CSRF while enabling fast re-authentication.
Tasks:
- Configure HSTS with preload, remove mixed content, and serve the service worker over HTTPS with scope /app/.
- Implement WebAuthn login. Issue a five-minute access token kept in memory and a rotation-based refresh token in an httpOnly, SameSite=Lax, Secure cookie. Revoke the chain on refresh reuse.
- Add a nonce-based CSP: no inline or eval, strict connect-src to your API and analytics, frame-ancestors 'none', Trusted Types, and SRI on third-party scripts.
- For cookie-backed pages, require a per-request CSRF token in a custom header; for API-only routes, remove cookies and accept header Bearer tokens only.
- Harden the service worker: cache static assets only with versioned keys; never cache authenticated responses; validate origin in fetch; implement skipWaiting() and clients.claim() for urgent revocation.
- Lock down permissions: request notifications only after a user action; omit unnecessary capabilities from manifest.json.
- Add security headers (nosniff, Referrer-Policy, Permissions-Policy).
- Instrument CSP report endpoint and service worker error logging; alert on spikes.
- In CI, fail builds if CSP contains unsafe-inline, if SRI is missing, or if Lighthouse flags mixed content.
Deliverable:
A working plan and demo that demonstrates HTTPS enforcement, safe credential storage, strict CSP, effective XSS/CSRF mitigations, hardened service worker behavior, and measurable monitoring in a secure PWA.

