Progressive Web Apps occupy an interesting security space. They look and feel like native applications but run in a browser sandbox. They can work offline, send push notifications, and access device hardware. They are distributed through URLs rather than app stores, which means no review process stands between the developer and the user.
For security teams, PWAs combine the attack surface of web applications with the persistence of native apps. Understanding the specific risks is essential for organizations deploying or allowing PWAs.
The PWA Threat Model
No App Store Gatekeeper
Native mobile applications go through store review before reaching users. PWAs are installed directly from a website. If a user visits a malicious website that presents an install prompt, they can install a malicious PWA with a single tap.
The installed PWA appears in the app launcher alongside native applications. Users may not distinguish between a PWA and a native app, which means they may trust it with the same level of confidence.
Service Worker Persistence
Service workers are the core technology that makes PWAs work offline and feel app-like. Once registered, a service worker runs in the background, intercepts network requests, and can execute code even when the user is not actively using the application.
A malicious or compromised service worker can intercept all requests made by the PWA and read or modify the responses, cache malicious content for offline use, and persist on the device until explicitly unregistered.
Service workers update automatically when the server provides a new version. If an attacker compromises the server, they can push a malicious service worker update to every user.
Origin-Based Security
PWA security is tied to the web origin model. A PWA at https://app.example.com has access to all data stored for that origin: cookies, localStorage, IndexedDB, and Cache API contents. Any cross-site scripting (XSS) vulnerability in the PWA gives an attacker access to all of this data.
This is different from native apps, which have application-level sandboxing. A vulnerability in one native app does not typically expose data from another native app.
Key Security Concerns
Offline Data Storage
PWAs store data locally using Cache API, IndexedDB, and localStorage. This data persists across sessions and is available offline. If the device is compromised, all locally stored data is accessible.
Encrypt sensitive data before storing it locally. Do not store authentication tokens, personal data, or business-critical information in plaintext in IndexedDB or localStorage.
Implement data expiration to ensure cached data does not persist indefinitely. Stale cached data can contain information the user expected to be deleted.
Content Integrity
PWAs load resources from the network and cache them for offline use. If an attacker can modify these resources, either through a man-in-the-middle attack or by compromising the CDN, they can inject malicious code that persists in the cache.
Use Subresource Integrity (SRI) for third-party resources to ensure they have not been tampered with.
Serve everything over HTTPS to prevent network-level tampering. Service workers require HTTPS (except on localhost), which provides a baseline level of transport security.
Implement Content Security Policy (CSP) to restrict which resources the PWA can load. A strict CSP prevents injected scripts from executing.
Push Notification Abuse
PWAs can send push notifications, which creates a phishing vector. A malicious PWA can display notifications that look like they come from a trusted source, directing users to phishing sites or prompting them to enter credentials.
Users should be cautious about granting push notification permissions to PWAs from untrusted sources. Organizations should educate users about this risk.
Background Sync
The Background Sync API allows PWAs to defer actions until the device has a stable network connection. A compromised PWA can use background sync to exfiltrate data when connectivity is available, making detection harder because the data transfer does not happen during active use.
Hardening PWA Deployments
Implement Strict CSP
A strict Content Security Policy is the most important security control for PWAs:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com
This prevents inline script injection, restricts resource loading to your own origin, and limits API connections to your backend.
Service Worker Scope Restriction
Limit the service worker scope to the minimum necessary path. A service worker scoped to / intercepts requests for the entire origin. A service worker scoped to /app/ only intercepts requests under that path.
Credential Management
Use the Web Credentials API and HttpOnly cookies instead of storing authentication tokens in localStorage or IndexedDB. HttpOnly cookies are not accessible to JavaScript, which means XSS cannot steal them.
Regular Security Audits
Audit your PWA with the same rigor as any other web application. Include the service worker in your security review. Test for XSS, CSRF, and injection vulnerabilities in both online and offline modes.
Monitor Service Worker Registration
For enterprise environments, monitor which service workers are registered on managed devices. Unexpected service worker registrations may indicate phishing or malware installation.
How Safeguard.sh Helps
Safeguard.sh provides supply chain analysis for web applications, including PWAs. It scans the JavaScript dependencies bundled in your PWA, identifies vulnerable packages, and generates SBOMs that catalog every component in your application. When a vulnerability is discovered in a JavaScript library your PWA depends on, Safeguard.sh identifies the affected applications and tracks the remediation process.