Storage Origin Isolation — Per-Origin localStorage, sessionStorage, Cookies #101

Closed
opened 2026-06-19 12:09:49 +00:00 by Artur · 0 comments
Owner

Issue #101 — Storage Origin Isolation — Per-Origin localStorage, sessionStorage, Cookies

Problembeschreibung

Storage ist nicht nach Origin isoliert. Aktuell gibt es:

  • LocalStorage (src/storage/local-storage.ts) — eine globale Instanz pro Page
  • SessionStorage (src/storage/session-storage.ts) — eine globale Instanz pro Page
  • CookieJar — per-URL gespeichert, aber ohne SameSite/Path-Prüfung
  • Keine Origin-Isolation: Ein iFrame auf anderer Origin sieht gleichen Storage wie Parent

Spec-konform muss sein:

  • localStorage['https://site-a.com']localStorage['https://site-b.com']
  • sessionStorage ist pro Tab/Page, geteilt zwischen iFrames gleicher Origin
  • Cookies: SameSite, Secure, Path, Domain korrekt ausgewertet
  • StorageEvent bei Cross-Tab-Änderungen (vereinfacht)
  • document.cookie liest/schreibt nur Cookies für aktuelle Origin + Path

Lösung — Storage Origin Buckets

src/storage/
├── storage-manager.ts    (Singleton: Map<Origin, StorageBucket>)
├── storage-bucket.ts      (localStorage + sessionStorage per Origin)
├── storage-event.ts       (StorageEvent für Cross-Bucket-Sync)
└── cookie-jar.ts          (erweitert: SameSite, Path, Domain, Secure)

StorageBucket:

class StorageBucket {
    readonly origin: string
    localStorage: Record<string, string>
    sessionStorage: Record<string, string>
}

class StorageManager {
    private buckets = new Map<string, StorageBucket>()
    
    getBucket(origin: string): StorageBucket {
        if (!this.buckets.has(origin)) {
            this.buckets.set(origin, new StorageBucket(origin))
        }
        return this.buckets.get(origin)!
    }
}

Akzeptanzkriterien

  • localStorage pro Origin isoliert (site-a.com ≠ site-b.com)
  • sessionStorage pro Page, geteilt zwischen iFrames gleicher Origin
  • Cookies: SameSite=Lax blockiert Cross-Site-Requests
  • Cookies: Secure wird nur über HTTPS gesendet
  • Cookies: Path=/foo matcht nur /foo und /foo/bar
  • Cookies: Domain=.example.com matcht sub.example.com
  • document.cookie schreibt nur für aktuelle Origin + Path
  • StorageEvent bei localStorage Änderung (vereinfacht)
  • Cookie-Max-Age/Expires wird ausgewertet
  • Session-Cookies werden nicht auf Disk persistiert
  • Keine Memory-Leaks bei vielen Origins

Betroffene Dateien

Datei Änderung Status
src/storage/local-storage.ts Ersetzen Ändern
src/storage/session-storage.ts Ersetzen Ändern
src/storage/storage-manager.ts Neu Neu
src/storage/storage-bucket.ts Neu Neu
src/storage/storage-event.ts Neu Neu
src/network/cookies.ts Erweitern Ändern
src/runtime-isolation.ts StorageManager Integration Ändern
tests/unit/storage-origin.test.ts Neu Neu

Testplan

  • 20 Unit Tests
  • 10 Integration Tests (iFrame, Cross-Origin, Cookie-Path)
# Issue #101 — Storage Origin Isolation — Per-Origin localStorage, sessionStorage, Cookies ## Problembeschreibung Storage ist **nicht nach Origin isoliert**. Aktuell gibt es: - `LocalStorage` (`src/storage/local-storage.ts`) — eine globale Instanz pro Page - `SessionStorage` (`src/storage/session-storage.ts`) — eine globale Instanz pro Page - `CookieJar` — per-URL gespeichert, aber ohne SameSite/Path-Prüfung - **Keine Origin-Isolation**: Ein iFrame auf anderer Origin sieht gleichen Storage wie Parent **Spec-konform muss sein:** - `localStorage['https://site-a.com']` ≠ `localStorage['https://site-b.com']` - `sessionStorage` ist pro Tab/Page, geteilt zwischen iFrames gleicher Origin - Cookies: `SameSite`, `Secure`, `Path`, `Domain` korrekt ausgewertet - `StorageEvent` bei Cross-Tab-Änderungen (vereinfacht) - `document.cookie` liest/schreibt nur Cookies für aktuelle Origin + Path ## Lösung — Storage Origin Buckets ``` src/storage/ ├── storage-manager.ts (Singleton: Map<Origin, StorageBucket>) ├── storage-bucket.ts (localStorage + sessionStorage per Origin) ├── storage-event.ts (StorageEvent für Cross-Bucket-Sync) └── cookie-jar.ts (erweitert: SameSite, Path, Domain, Secure) ``` **StorageBucket:** ```ts class StorageBucket { readonly origin: string localStorage: Record<string, string> sessionStorage: Record<string, string> } class StorageManager { private buckets = new Map<string, StorageBucket>() getBucket(origin: string): StorageBucket { if (!this.buckets.has(origin)) { this.buckets.set(origin, new StorageBucket(origin)) } return this.buckets.get(origin)! } } ``` ## Akzeptanzkriterien - [ ] `localStorage` pro Origin isoliert (site-a.com ≠ site-b.com) - [ ] `sessionStorage` pro Page, geteilt zwischen iFrames gleicher Origin - [ ] Cookies: `SameSite=Lax` blockiert Cross-Site-Requests - [ ] Cookies: `Secure` wird nur über HTTPS gesendet - [ ] Cookies: `Path=/foo` matcht nur /foo und /foo/bar - [ ] Cookies: `Domain=.example.com` matcht sub.example.com - [ ] `document.cookie` schreibt nur für aktuelle Origin + Path - [ ] `StorageEvent` bei localStorage Änderung (vereinfacht) - [ ] Cookie-`Max-Age`/`Expires` wird ausgewertet - [ ] Session-Cookies werden nicht auf Disk persistiert - [ ] Keine Memory-Leaks bei vielen Origins ## Betroffene Dateien | Datei | Änderung | Status | |-------|----------|--------| | `src/storage/local-storage.ts` | Ersetzen | Ändern | | `src/storage/session-storage.ts` | Ersetzen | Ändern | | `src/storage/storage-manager.ts` | Neu | Neu | | `src/storage/storage-bucket.ts` | Neu | Neu | | `src/storage/storage-event.ts` | Neu | Neu | | `src/network/cookies.ts` | Erweitern | Ändern | | `src/runtime-isolation.ts` | StorageManager Integration | Ändern | | `tests/unit/storage-origin.test.ts` | Neu | Neu | ## Testplan - 20 Unit Tests - 10 Integration Tests (iFrame, Cross-Origin, Cookie-Path)
Artur closed this issue 2026-06-19 16:17:06 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
glow-all/true-headless-browser#101
No description provided.