Isolated Web Apps - jak przeglądarka staje się systemem operacyjnym (i dlaczego to dobrze)

Twój CTO mówi: „budujemy natywną aplikację desktopową". Pytasz dlaczego. Odpowiedź brzmi zawsze tak samo: „bo przeglądarka nie daje dostępu do socketów, nie ma izolacji, nie da się podpisać kodu, a użytkownik może otworzyć DevTools i zrobić co chce".

Fair enough. Tak było. Do niedawna.

W Chrome 120 (koniec 2023) pojawiła się flaga chrome://flags/#enable-isolated-web-app-dev-mode. Brzmi jak kolejny eksperyment Google, który umrze po dwóch kwartałach. Ale tym razem to coś innego - to fundament pod Isolated Web Apps (IWA), nowy model aplikacji webowych z poziomem bezpieczeństwa, o jakim PWA mogły tylko marzyć.

Czym są Isolated Web Apps

Klasyczna aplikacja webowa działa tak: przeglądarka pyta serwer o pliki, serwer je wysyła, przeglądarka je renderuje. Jeśli ktoś przejmie serwer - może podmienić kod, który trafia do przeglądarki. SSL/TLS chroni transmisję, ale nie chroni przed skompromitowanym serwerem. Twój użytkownik dostaje złośliwy JavaScript i nawet o tym nie wie.

Isolated Web Apps odwracają ten model:

  1. Aplikacja jest spakowana w Web Bundle (.swbn) - wszystkie pliki w jednym archiwum
  2. Pakiet jest podpisany kryptograficznie kluczem Ed25519 lub ECDSA P-256 - deweloper podpisuje, przeglądarka weryfikuje
  3. Tożsamość oparta na kluczu, nie na domenie - adres to isolated-app://<hash-klucza-publicznego>, nie https://example.com
  4. Izolacja od reszty przeglądarki - osobny kontekst storage, osobna polityka CORS, osobne cookies

Brzmi jak Electron, ale bez 300 MB Chromium w każdej aplikacji.

Co daje IsolatedWebAppDevMode

Flaga IsolatedWebAppDevMode to tryb deweloperski, który pozwala testować IWA bez pełnego pipeline'u podpisywania i dystrybucji. Bez niej - musisz mieć klucze, podpisany bundle i dystrybucję przez Chrome Enterprise.

Z nią dostajesz dwie ścieżki:

Dev Mode Proxy

Uruchamiasz lokalny serwer deweloperski (np. localhost:5173) i instalujesz go jako IWA bezpośrednio w Chrome. Bez bundlowania, bez podpisywania. Aplikacja działa z pełnymi politykami bezpieczeństwa IWA i ma dostęp do API niedostępnych dla zwykłych stron.

Signed Web Bundle (testowy)

Generujesz klucze, pakujesz aplikację i instalujesz bundle ręcznie. Pełna symulacja produkcyjnego pipeline'u.

# Generowanie kluczy Ed25519
openssl genpkey -algorithm Ed25519 -out private_key.pem
openssl pkey -in private_key.pem -pubout -out public_key.pem

# Bundlowanie aplikacji (npm)
npx wbn --dir ./dist --output app.wbn

# Podpisywanie bundle
npx wbn-sign \
  --input app.wbn \
  --output app.swbn \
  --private-key private_key.pem

Po instalacji aplikacja działa w isolated-app:// z izolowanym kontekstem - tak samo jak w produkcji.

Zalety, których brakowało w PWA

1. Ochrona przed kompromitacją serwera

To jest główny powód istnienia IWA. Zespół Signal (szyfrowany komunikator) stwierdził wprost: hostowanie aplikacji webowej na serwerze oznacza, że skompromitowany serwer = skompromitowany użytkownik. Dlatego Signal jest aplikacją natywną, nie webową.

IWA rozwiązują ten problem. Kod jest podpisany offline, klucze mogą leżeć w HSM (Hardware Security Module), a serwer w ogóle nie uczestniczy w dostarczaniu kodu aplikacji.

Wektor atakuKlasyczna web appPWAIWA
Kompromitacja serweraPełne przejęciePełne przejęcieBrak wpływu - kod z bundle
Man-in-the-MiddleTLS chroniTLS chroniTLS + podpis kryptograficzny
Podmiana kodu CDNPełne przejęciePełne przejęcieBrak wpływu - weryfikacja podpisu
XSS przez wstrzyknięcieZależy od CSPZależy od CSPZablokowany - strict CSP, brak inline scripts
Modyfikacja kodu w DevToolsMożliwaMożliwaOgraniczona - izolowany kontekst

2. Dostęp do API, które są „zbyt niebezpieczne" dla zwykłego weba

IWA odblokowują API, które przeglądarka słusznie blokuje dla zwykłych stron:

Direct Sockets API - surowe połączenia TCP i UDP prosto z przeglądarki:

// Połączenie TCP - wcześniej niemożliwe w przeglądarce
const socket = new TCPSocket("192.168.1.100", 9100);
const writer = socket.writable.getWriter();

// Wysyłanie danych do drukarki przemysłowej
await writer.write(new TextEncoder().encode("^XA^FO50,50^ADN,36,20^FDZamówienie #4521^FS^XZ"));
await writer.close();

To oznacza: klienty SSH w przeglądarce, komunikacja z urządzeniami IoT po TCP/UDP, połączenia z legacy systemami po surowych socketach - bez proxy, bez WebSocket bridge, bez serwera pośredniczącego.

Controlled Frame - bezpieczne osadzanie treści stron trzecich z pełną kontrolą:

// Osadzanie zewnętrznej strony z kontrolą polityk bezpieczeństwa
const frame = document.querySelector('controlledframe');
frame.request.onBeforeRequest.addListener(
  (details) => {
    // Blokujemy trackery i złośliwe skrypty
    if (details.url.includes('tracking.js')) {
      return { cancel: true };
    }
  },
  { urls: ["<all_urls>"] }
);

3. Strict CSP - wymuszony, nie opcjonalny

W zwykłej aplikacji webowej Content Security Policy to nagłówek, który możesz ustawić. W IWA to polityka wymuszona przez przeglądarkę:

Content-Security-Policy:
  default-src 'self';           # Tylko zasoby z bundle
  script-src 'self' 'wasm-unsafe-eval';  # Brak inline scripts
  connect-src https: wss:;      # Sieć tylko po HTTPS/WSS
  object-src 'none';            # Brak Flash, Java appletów
  base-uri 'none';              # Brak manipulacji base URL
  require-trusted-types-for 'script';  # TrustedTypes obowiązkowe

Nie da się tego wyłączyć. Nie da się dodać unsafe-inline. Nie da się wstawić eval(). Programista nie musi „pamiętać o bezpieczeństwie" - przeglądarka mu nie pozwoli o nim zapomnieć. Brzmi znajomo? To ta sama filozofia co w Phoenix - secure by default.

4. Cross-Origin Isolation - domyślna

IWA automatycznie wymuszają nagłówki:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin

To zamyka wektory ataków Spectre i Meltdown, a jednocześnie odblokowuje SharedArrayBuffer i precyzyjne timery - rzeczy potrzebne do wydajnych obliczeń w przeglądarce.

Od kiedy to działa i jaki jest stan dzisiaj

DataWydarzenie
2022Propozycja WICG (Web Incubator Community Group) - explainer na GitHubie
Q4 2023Chrome 120 - flaga IsolatedWebAppDevMode dostępna
2024IWA dostępne na urządzeniach ChromeOS zarządzanych przez Chrome Enterprise
2024–2025Direct Sockets API, Controlled Frame - nowe API wymagające IWA
2026 (teraz)Rozszerzenie dostępności poza Chrome Enterprise, praca nad specyfikacją multi-browser

Stan na dziś: IWA działają w Chrome/ChromeOS. Specyfikacja jest rozwijana w WICG. Tryb deweloperski (IsolatedWebAppDevMode) jest dostępny dla każdego od Chrome 120+. Produkcyjne wdrożenia wymagają Chrome Enterprise - ale to się zmienia.

Porównanie z alternatywami

Zanim ktoś powie „ale Electron robi to samo":

CechaElectronTauriPWAIWA
Rozmiar aplikacji150–300 MB5–20 MB0 (przeglądarka)0 (przeglądarka)
AktualizacjeRęczne / auto-updaterRęczneAutomatyczneAuto (co 4–6h)
Surowe sockety (TCP/UDP)Tak (Node.js)Tak (Rust)NieTak (Direct Sockets)
Podpis kryptograficzny koduOpcjonalnyOpcjonalnyBrakWymagany
Izolacja od OSSłaba (pełen dostęp)Średnia (allowlist)Silna (sandbox)Silna (sandbox + CSP)
Cross-platformWin/Mac/LinuxWin/Mac/LinuxWszędzieChrome (na razie)
Koszt utrzymaniaWysokiŚredniNiskiNiski
Dostęp do plików lokalnychPełnyKontrolowanyFile System Access APIFile System Access API

Electron to 300 MB Chromium, żeby wyświetlić formularz logowania. IWA to ten sam Chromium, który użytkownik już ma zainstalowany.

Wady i zagrożenia - bo nie jest różowo

1. Vendor lock-in na Chrome

Na dziś IWA to de facto standard Google. Specyfikacja jest w WICG, nie w W3C. Mozilla i Apple nie zadeklarowały implementacji. To jest największe ryzyko - jeśli inne przeglądarki nie adoptują standardu, IWA stają się „Chrome Apps 2.0". A Chrome Apps umarły w 2020.

Historyczne precedensy nie napawają optymizmem:

  • Chrome Apps (2013–2020) - spakowane aplikacje webowe. Zabite.
  • Firefox OS (2013–2016) - cały OS na aplikacjach webowych. Zabity.
  • Microsoft UWP JavaScript - aplikacje JS w Store. Marginalizowane.

2. Brak discoverable linking

IWA nie mają URL-i, które można wysłać komukolwiek. Nie wkleisz linka w Slacka. Nie zindeksujesz w Google. Nie wyślesz w mailu „kliknij tu". Użytkownik musi zainstalować aplikację - tak jak natywną. To łamie jedną z największych zalet weba: linkowanie.

To jest fundamentalna zmiana filozofii. Web działa, bo możesz otworzyć link i masz aplikację. IWA działa jak App Store - musisz wiedzieć, że aplikacja istnieje, znaleźć ją i zainstalować. Krok wstecz? Być może.

3. Wolniejsze aktualizacje

W klasycznym webie deploysz na serwer i użytkownik ma nową wersję natychmiast. W IWA:

  1. Budujesz nowy bundle
  2. Podpisujesz go
  3. Publikujesz manifest aktualizacji
  4. Chrome sprawdza manifest co 4–6 godzin
  5. Użytkownik dostaje aktualizację przy kolejnym uruchomieniu

Między deployem a aktualizacją u użytkownika mija nawet kilkanaście godzin. Krytyczny hotfix? Użytkownicy dalej mają starą wersję. W świecie, gdzie git push = deploy, to jest problem.

4. Zwiększona powierzchnia ataku przeglądarki

Direct Sockets API daje dostęp do surowych socketów TCP/UDP. To potężne narzędzie - i potężne ryzyko. Złośliwa IWA z dostępem do socketów może:

  • Skanować sieć lokalną
  • Łączyć się z urządzeniami IoT bez wiedzy użytkownika
  • Ustanawiać połączenia z C2 (Command & Control)
  • Omijać firewalle aplikacyjne (ruch po surowym TCP, nie po HTTP)

Google adresuje to przez wymaganie podpisu kryptograficznego i dystrybucji kontrolowanej - ale każdy mechanizm podpisu kodu w historii został obejśty. Podpisane malware istnieje od lat (Stuxnet miał podpis Realtek i JMicron).

5. Fragmentacja ekosystemu webowego

Web działa, bo jest jeden model: URL → HTTP → HTML/CSS/JS. IWA wprowadzają drugi model: bundle → podpis → isolated-app://. Dwa modele to dwa zestawy narzędzi, dwa pipeline'y CI/CD, dwa sposoby testowania, dwa mentalne modele dla programistów.

Jeden web jest lepszy niż dwa. To jest realne ryzyko.

Kiedy IWA to dobry wybór

Czy Twoja aplikacja wymaga surowych socketów (TCP/UDP)?
├── Tak → IWA (Direct Sockets API)

Czy ochrona przed kompromitacją serwera jest krytyczna?
├── Tak (komunikatory E2E, finanse, medycyna) → IWA

Czy potrzebujesz dystrybucji jak aplikacja natywna?
├── Tak, ale bez Electron/Tauri → IWA

Czy potrzebujesz SEO i linkowania?
├── Tak → Klasyczna web app / PWA

Czy Twoja grupa docelowa używa głównie Chrome?
├── Nie → Klasyczna web app / PWA

Domyślnie → PWA z Service Workerem

Kiedy NIE używać IWA

Bądźmy uczciwi - IWA to nie jest rozwiązanie na wszystko:

  • Strony informacyjne i blogi - SEO i linkowanie są ważniejsze niż izolacja
  • Aplikacje SaaS z szeroką grupą użytkowników - nie każdy używa Chrome
  • MVP i prototypy - overhead podpisywania i bundlowania zabija prędkość iteracji
  • Aplikacje, które nie potrzebują API wymagających wysokiego zaufania - jeśli nie potrzebujesz Direct Sockets, PWA wystarczy
  • Zespoły bez doświadczenia z kryptografią - zarządzanie kluczami podpisywania to poważna odpowiedzialność

Przyszłość należy do weba

Oto trend, którego nie da się zignorować:

RokCo przeglądarka „nie umiała"Co umie dziś
2010GeolokalizacjaStandardowa funkcja
2012OfflineService Workers, Cache API
2014Push notificationsWeb Push API
2015BluetoothWeb Bluetooth API
2016USBWebUSB API
2018PłatnościPayment Request API
2020Dostęp do plikówFile System Access API
2021GPU computeWebGPU
2023Surowe socketyDirect Sockets API (w IWA)

Każdy rok przynosi API, które wcześniej „wymagało aplikacji natywnej". Każdy rok zmniejsza przewagę Electrona, Fluttera, Qt. Każdy rok przesuwa granicę tego, co da się zrobić w przeglądarce.

IWA to nie rewolucja - to kolejny logiczny krok. Przeglądarka przestaje być „narzędziem do wyświetlania stron" i staje się platformą uruchomieniową dla aplikacji z gwarancjami bezpieczeństwa, których wcześniej nie miała.

Czy IWA zastąpią Electrona? Nie od razu. Czy zastąpią natywne aplikacje? Nie wszystkie. Ale kierunek jest jasny: web zjada kolejne kawałki tortu, który kiedyś należał wyłącznie do aplikacji natywnych.

WebAssembly dał przeglądarce wydajność. Service Workers dały jej offline. WebGPU dał jej GPU. IWA dają jej zaufanie - podpisany, zweryfikowany, izolowany kod, który nie zależy od serwera.

Za 5 lat nikt nie będzie pakował 300 MB Chromium do Electrona, żeby wyświetlić dashboard. Będzie IWA - albo coś, co wyrośnie z tego samego pomysłu.

Przeglądarka wygrywa. Zawsze wygrywała. Czasem wolniej, niż byśmy chcieli - ale kierunek jest jeden.


Budujesz aplikację, która wymaga więcej niż standardowy web? Porozmawiajmy - pomożemy wybrać architekturę, która nie zmusi Twoich użytkowników do instalowania 300 MB runtime'u.