# Memory & State Security Strategy

## Overview

This document explains the memory management and sensitive data security strategy for SeedPGP, addressing the fundamental limitation that **JavaScript on the web cannot guarantee memory zeroing**, and describing the defense-in-depth approach used instead.

## Executive Summary

**Key Finding:** JavaScript cannot explicitly zero heap memory. No cryptographic library or framework can provide 100% memory protection in JS environments.

**Strategic Response:** SeedPGP uses defense-in-depth with:

1. **Encryption** - Sensitive data is encrypted at rest using AES-256-GCM
2. **Limited Scope** - Session-scoped keys that auto-rotate and auto-destroy  
3. **Network Isolation** - CSP headers + user-controlled network blocking prevent exfiltration
4. **Audit Trail** - Clipboard and crypto operations are logged via ClipboardDetails component

---

## JavaScript Memory Limitations

### Why Memory Zeroing Is Not Possible

JavaScript's memory model and garbage collector make explicit memory zeroing impossible:

1. **GC Control Abstraction**
   - JavaScript abstracts away memory management from developers
   - No `Uint8Array.prototype.fill(0)` actually zeroes heap memory
   - The GC doesn't guarantee immediate reclamation of dereferenced objects
   - Memory pages may persist across multiple allocations

2. **String Immutability**
   - Strings in JS cannot be overwritten in-place
   - Each string operation allocates new memory
   - Old copies remain in memory until GC collects them

3. **JIT Compilation**
   - Modern JS engines (V8, JavaScriptCore) JIT-compile code
   - Sensitive data may be duplicated in compiled bytecode, caches, or optimizer snapshots
   - These internal structures are not under developer control

4. **External Buffers**
   - Browser APIs (WebGL, AudioContext) may have internal copies of data
   - OS kernel may page memory to disk
   - Hardware CPU caches are not directlycontrolled

### Practical Implications

| Attack Vector | JS Protection | Mitigation |
|---|---|---|
| **Process Heap Inspection** | ❌ None | Encryption + short key lifetime |
| **Memory Dumps** (device/VM) | ❌ None | Encryption mitigates exposure |
| **Browser DevTools** | ⚠️ Weak | Browser UI constraints only |
| **Browser Extensions** | ❌ None | CSP blocks malicious scripts |
| **Clipboard System** | ❌ None | Auto-clear + user alert |
| **Network Exfiltration** | ✅ **Strong** | CSP `connect-src 'none'` + user toggle |
| **XSS Injection** | ✅ **Strong** | CSP `script-src 'self'` + sandbox |

---

## SeedPGP Defense-in-Depth Architecture

### Layer 1: Content Security Policy (CSP)

**File:** [index.html](index.html#L9-L19)

```html
<meta http-equiv="Content-Security-Policy" content="
  default-src 'none';
  script-src 'self' 'wasm-unsafe-eval';
  connect-src 'none';
  form-action 'none';
  frame-ancestors 'none';
  base-uri 'self';
  upgrade-insecure-requests;
  block-all-mixed-content
" />
```

**What This Protects:**

- `connect-src 'none'` → **No external network requests allowed** (enforced by browser)
- `script-src 'self' 'wasm-unsafe-eval'` → **Only self-hosted scripts** (blocks external CDN injection)
- `form-action 'none'` → **No form submissions** (blocks exfiltration via POST)
- `default-src 'none'` → **Deny everything by default** (whitelist-only model)

**Verification:** Integration tests verify CSP headers are present and restrictive.

### Layer 2: Network Blocking Toggle

**File:** [src/App.tsx](src/App.tsx#L483-L559) `blockAllNetworks()`

Provides user-controlled network interception via JavaScript API patching:

```typescript
1. fetch() → rejects all requests
2. XMLHttpRequest → constructor throws
3. WebSocket → constructor throws
4. sendBeacon() → returns false
5. Image.src → rejects external URLs
6. ServiceWorker.register() → throws
```

**When to Use:**

- Maximize security posture voluntarily
- Testing offline-first behavior
- Prevent any JS-layer network calls

**Limitation:** CSP provides the real enforcement at browser level; this is user-perceived security.

### Layer 3: Session Encryption

**File:** [src/lib/sessionCrypto.ts](src/lib/sessionCrypto.ts)

All sensitive data that enters React state can be encrypted:

**Key Properties:**

- **Algorithm:** AES-256-GCM (authenticated encryption)
- **Non-Exportable:** Key cannot be retrieved via `getKey()` API
- **Auto-Rotation:** Every 5 minutes OR every 1000 operations
- **Auto-Destruction:** When page becomes hidden (tab switch/minimize)

**Data Encrypted:**

- Mnemonic (seed phrase)
- Private key materials
- Backup passwords
- PGP passphrases
- Decryption results

**How It Works:**

```
User enters seed → Encrypt with session key → Store in React state
User leaves → Key destroyed → Memory orphaned
User returns → New key generated → Can't decrypt old data
```

### Layer 4: Sensitive Data Encryption in React

**File:** [src/lib/useEncryptedState.ts](src/lib/useEncryptedState.ts)

Optional React hook for encrypting individual state variables:

```typescript
// Usage example (optional):
const [mnemonic, setMnemonic, encryptedBlob] = useEncryptedState('');

// When updated:
await setMnemonic('my-12-word-seed-phrase');

// The hook:
// - Automatically encrypts before storing
// - Automatically decrypts on read
// - Tracks encrypted blob for audit
// - Returns plaintext for React rendering (GC will handle cleanup)
```

**Trade-offs:**

- ✅ **Pro:** Sensitive data encrypted in state objects  
- ✅ **Pro:** Audit trail of encrypted values
- ❌ **Con:** Async setState complicates component logic
- ❌ **Con:** Decrypted values still in memory during React render

**Migration Path:** Components already using sessionCrypto; useEncryptedState is available for future adoption.

### Layer 5: Clipboard Security

**File:** [src/App.tsx](src/App.tsx#L228-L270) `copyToClipboard()`

Automatic protection for sensitive clipboard operations:

```typescript
✅ Detects sensitive fields: 'mnemonic', 'seed', 'password', 'private', 'key'
✅ User alert: "⚠️ Will auto-clear in 10 seconds"
✅ Auto-clear: Overwrites clipboard with random garbage after 10 seconds
✅ Audit trail: ClipboardDetails logs all sensitive operations
```

**Limitations:**

- System clipboard is outside app control
- Browser extensions can read clipboard
- Other apps may have read clipboard before auto-clear
- Auto-clear timing is not guaranteed on all systems

**Recommendation:** User education—alert shown every time sensitive data is copied.

---

## Current State of Sensitive Data

### Critical Paths (High Priority if Adopting useEncryptedState)

| State Variable | Sensitivity | Current Encryption | Recommendation |
|---|---|---|---|
| `mnemonic` | 🔴 Critical | Via cache | ✅ Encrypt directly |
| `privateKeyInput` | 🔴 Critical | Via cache | ✅ Encrypt directly |
| `privateKeyPassphrase` | 🔴 Critical | Not encrypted | ✅ Encrypt directly |
| `backupMessagePassword` | 🔴 Critical | Not encrypted | ✅ Encrypt directly |
| `restoreMessagePassword` | 🔴 Critical | Not encrypted | ✅ Encrypt directly |
| `decryptedRestoredMnemonic` | 🔴 Critical | Cached, auto-cleared | ✅ Already protected |
| `publicKeyInput` | 🟡 Medium | Not encrypted | Optional |
| `qrPayload` | 🟡 Medium | Not encrypted | Optional (if contains secret) |
| `restoreInput` | 🟡 Medium | Not encrypted | Optional |

### Current Decrypt Flow

```
Encrypted File/QR
    ↓
decrypt() → Plaintext (temporarily in memory)
    ↓
encryptJsonToBlob() → Cached in sessionCrypto
    ↓
React State (encrypted cache reference)
    ↓
User clicks "Clear" or timer expires
    ↓
destroySessionKey() → Key nullified → Memory orphaned
```

**Is This Sufficient?**

- ✅ For most users: **Yes** - Key destroyed on tab switch, CSP blocks exfiltration
- ⚠️ For adversarial JS: Depends on attack surface (what can access memory?)
- ❌ For APT/Malware: No—memory inspection always possible

---

## Recommended Practices

### For App Users

1. **Enable Network Blocking**
   - Toggle "🔒 Block Networks" when handling sensitive seeds
   - Provides additional confidence

2. **Use in Offline Mode**
   - Use SeedPGP available offline-first design
   - Minimize device network exposure

3. **Clear Clipboard Intentionally**
   - After copying sensitive data, manually click "Clear Clipboard & History"
   - Don't rely solely on 10-second auto-clear

4. **Use Secure Environment**
   - Run in isolated browser profile (e.g., Firefox Containers)
   - Consider Whonix, Tails, or VM for high-security scenarios

5. **Mind the Gap**
   - Understand that 10-second clipboard clear isn't guaranteed
   - Watch the alert message about clipboard accessibility

### For Developers

1. **Use Encryption for Sensitive State**

   ```typescript
   // Recommended approach for new features:
   import { useEncryptedState } from '@/lib/useEncryptedState';
   
   const [secret, setSecret] = useEncryptedState('');
   ```

2. **Never Store Plaintext Keys**

   ```typescript
   // ❌ Bad - plaintext in memory:
   const [key, setKey] = useState('secret-key');
   
   // ✅ Good - encrypted:
   const [key, setKey] = useEncryptedState('');
   ```

3. **Clear Sensitive Data After Use**

   ```typescript
   // Crypto result → cache immediately
   const result = await decrypt(encryptedData);
   const blob = await encryptJsonToBlob(result);
   _setEncryptedMnemonicCache(blob);
   setMnemonic(''); // Don't keep plaintext
   ```

4. **Rely on CSP, Not JS Patches**

   ```typescript
   // ✅ Trust CSP header enforcement for security guarantees
   // ⚠️ JS-level network blocking is UX, not security
   ```

---

## Testing & Validation

### Integration Tests

**File:** [src/integration.test.ts](src/integration.test.ts)

Tests verify:

- CSP headers are restrictive (`default-src 'none'`, `connect-src 'none'`)
- Network blocking toggle toggles all 5 mechanisms
- Clipboard auto-clear fires after 10 seconds
- Session key rotation occurs correctly

**Run Tests:**

```bash
bun test:integration
```

### Manual Verification

1. **CSP Verification**

   ```bash
   # Browser DevTools → Network tab
   # Attempt to load external resource → CSP violation shown
   ```

2. **Network Blocking Test**

   ```javascript
   // In browser console with network blocking enabled:
   fetch('https://example.com') // → Network blocked error
   ```

3. **Clipboard Test**

   ```javascript
   // Copy a seed → 10 seconds later → Clipboard contains garbage
   navigator.clipboard.readText().then(text => console.log(text));
   ```

4. **Session Key Rotation**

   ```javascript
   // Browser console (dev mode only):
   await window.runSessionCryptoTest()
   ```

---

## Limitations & Accepted Risk

### What SeedPGP CANNOT Protect Against

1. **Memory Inspection Post-Compromise**
   - If device is already compromised, encryption provides limited value
   - Attacker can hook into decryption function and capture plaintext

2. **Browser Extension Attacks**
   - Malicious extension bypasses CSP (runs in extension context)
   - Our network controls don't affect extensions
   - **Mitigation:** Only install trusted extensions; watch browser audit

3. **Supply Chain Attacks**
   - If Vite/TypeScript build is compromised, attacker can exfiltrate data
   - **Mitigation:** Verify hashes, review source code, use git commits

4. **Timing Side-Channels**
   - How long operations take may leak information
   - **Mitigation:** Use cryptographic libraries (OpenPGP.js) that implement constant-time ops

5. **Browser Memory by Device Owner**
   - If device owner uses `lldb`, `gdb`, or memory forensics tools, any plaintext extant is exposed
   - **For Tails/Whonix:** Memory is wiped on shutdown by design (us-relevant)

### Accepted Risks

| Threat | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Browser compromise | Low | Critical | CSP + offline mode |
| Device compromise | Medium | Critical | Encryption provides delay |
| Malicious extension | Medium | High | CSP, user vigilance |
| User social engineering | High | Critical | User education |
| Browser DevTools inspection | Medium-Low | Medium | DevTools not exposed by default |

---

## Future Improvements

### Potential Enhancements

1. **Full State Tree Encryption**
   - Encrypt entire App state object
   - Trade: Performance cost, complex re-render logic
   - Benefit: No plaintext state ever in memory

2. **Service Worker Encryption Layer**
   - Intercept state mutations at service worker level
   - Trade: Requires service worker registration (currently blocked by CSP)
   - Benefit: Transparent to components

3. **Hardware Wallet Integration**
   - Never import private keys; sign via hardware device
   - Trade: User experience complexity
   - Benefit: Private keys never reach browser

4. **Proof of Concept: Wasm Memory Protection**
   - Implement crypto in WebAssembly with explicit memory wiping
   - Trade: Complex build, performance overhead
   - Benefit: Stronger memory guarantees for crypto operations

5. **Runtime Attestation**
   - Periodically verify memory is clean via TOTP or similar
   - Trade: User experience friction
   - Benefit: Confidence in security posture

---

## References

### Academic Content

- **"Wiping Sensitive Data from Memory"** - CWE-226, OWASP
- **"JavaScript Heap Analysis"** - V8 developer documentation
- **"Why JavaScript Is Unsuitable for Cryptography"** - Nadim Kobeissi, CryptoParty

### Specifications

- **Content Security Policy Level 3** - <https://w3c.github.io/webappsec-csp/>
- **Web Crypto API** - <https://www.w3.org/TR/WebCryptoAPI/>
- **AES-GCM** - NIST SP 800-38D

### Community Resources

- **r/cryptography FAQ** - "Why use Tails for sensitive crypto?"
- **OpenPGP.js Documentation** - Encryption recommendations
- **OWASP: A02:2021 – Cryptographic Failures** - Web app best practices

---

## Frequently Asked Questions

**Q: Should I trust SeedPGP with my mainnet private keys?**  
A: No. SeedPGP is designed for seed phrase entry and BIP39 mnemonic generation. Never import active mainnet keys into any web app.

**Q: What if I'm in Tails or Whonix?**  
A: Excellent choice. Those environments will:

- Burn RAM after shutdown (defeating memory forensics)
- Bridge Tor automatically (defeating location tracking)
- Run in VM (limiting HW side-channel attacks)

SeedPGP in Tails/Whonix with network blocking enabled provides strong security posture.

**Q: Can I fork and add X security feature?**  
A: Absolutely! Recommended starting points:

- `useEncryptedState` for new state variables
- Wasm encryption layer for crypto operations
- Service Worker interception for transparent encryption

**Q: Should I use SeedPGP on a shared device?**  
A: Only if you trust all users. Another user could:

- Read clipboard history
- Inspect browser memory
- Access browser console history

For high-security scenarios, use dedicated device or Tails USB.

---

## Contact & Questions

See [README.md](README.md) for contact information and support channels.
