Skip to content

fix: replace AES-GCM session-key-in-sessionStorage with secure key wrapping - #154

Merged
BarryArinze merged 2 commits into
aid-linkk:masterfrom
JamesEjembi:fix/encrypted-storage-key-management
Aug 27, 2026
Merged

fix: replace AES-GCM session-key-in-sessionStorage with secure key wrapping#154
BarryArinze merged 2 commits into
aid-linkk:masterfrom
JamesEjembi:fix/encrypted-storage-key-management

Conversation

@JamesEjembi

Copy link
Copy Markdown
Contributor

Summary

Replaces the vulnerable AES-GCM session-key-in-sessionStorage bootstrap with a secure key wrapping architecture using Web Crypto wrapKey/unwrapKey API.

Security Improvements

  • Non-exportable wrapping key: Derived from session token via HKDF, cannot be exported
  • Wrapped key storage: Raw AES key bytes never accessible to JavaScript
  • Session token is not a secret: Used only for key derivation, not as a key itself
  • Threat model documentation: Clear explanation of what is and isn't protected

Changes

  • Implement Web Crypto wrapKey/unwrapKey API for secure key storage
  • Use HKDF key derivation from session token
  • Store wrapped key in localStorage, session token in sessionStorage
  • Maintain PersistStorage interface compatibility
  • Add comprehensive threat model documentation

Closes

Closes #143

Threat Model

Defends against:

  • Cross-tab storage reading (session-scoped keys)
  • localStorage data extraction (AES-GCM encryption)

Does NOT defend against (out of scope):

  • Same-tab XSS (key must be in memory for crypto operations)
  • Browser DevTools (CryptoKey accessible via debugger)
  • Memory dumps (key exists in process memory)

- Replace /payments endpoint with /transactions endpoint for direct memo access
- Implement cursor-based resumption for incremental fetches
- Add configurable maxRecords limit (default 5000)
- Add rate limiting (110ms between requests) for Horizon compliance
- Create server-side API route /api/v1/analytics for pre-aggregated data
- Maintain CampaignAnalytics interface compatibility
- Early exit when target campaign records are not found in page
- Proper deduplication using transaction_hash only

Closes aid-linkk#140
…apping

- Implement Web Crypto wrapKey/unwrapKey API for secure key storage
- Use non-exportable wrapping key derived from session token via HKDF
- Raw AES key bytes never accessible to JavaScript code
- Session token in sessionStorage is not a secret key (used for derivation)
- Add comprehensive threat model documentation
- Maintain PersistStorage interface compatibility
- Proper cleanup on session expiry or tampering detection

Closes aid-linkk#143
@BarryArinze
BarryArinze merged commit 3512e66 into aid-linkk:master Aug 27, 2026
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants