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:
- Aplikacja jest spakowana w Web Bundle (
.swbn) - wszystkie pliki w jednym archiwum - Pakiet jest podpisany kryptograficznie kluczem Ed25519 lub ECDSA P-256 - deweloper podpisuje, przeglądarka weryfikuje
- Tożsamość oparta na kluczu, nie na domenie - adres to
isolated-app://<hash-klucza-publicznego>, niehttps://example.com - 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.pemPo 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 ataku | Klasyczna web app | PWA | IWA |
|---|---|---|---|
| Kompromitacja serwera | Pełne przejęcie | Pełne przejęcie | Brak wpływu - kod z bundle |
| Man-in-the-Middle | TLS chroni | TLS chroni | TLS + podpis kryptograficzny |
| Podmiana kodu CDN | Pełne przejęcie | Pełne przejęcie | Brak wpływu - weryfikacja podpisu |
| XSS przez wstrzyknięcie | Zależy od CSP | Zależy od CSP | Zablokowany - strict CSP, brak inline scripts |
| Modyfikacja kodu w DevTools | Możliwa | Możliwa | Ograniczona - 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ązkoweNie 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-originTo 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
| Data | Wydarzenie |
|---|---|
| 2022 | Propozycja WICG (Web Incubator Community Group) - explainer na GitHubie |
| Q4 2023 | Chrome 120 - flaga IsolatedWebAppDevMode dostępna |
| 2024 | IWA dostępne na urządzeniach ChromeOS zarządzanych przez Chrome Enterprise |
| 2024–2025 | Direct 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":
| Cecha | Electron | Tauri | PWA | IWA |
|---|---|---|---|---|
| Rozmiar aplikacji | 150–300 MB | 5–20 MB | 0 (przeglądarka) | 0 (przeglądarka) |
| Aktualizacje | Ręczne / auto-updater | Ręczne | Automatyczne | Auto (co 4–6h) |
| Surowe sockety (TCP/UDP) | Tak (Node.js) | Tak (Rust) | Nie | Tak (Direct Sockets) |
| Podpis kryptograficzny kodu | Opcjonalny | Opcjonalny | Brak | Wymagany |
| Izolacja od OS | Słaba (pełen dostęp) | Średnia (allowlist) | Silna (sandbox) | Silna (sandbox + CSP) |
| Cross-platform | Win/Mac/Linux | Win/Mac/Linux | Wszędzie | Chrome (na razie) |
| Koszt utrzymania | Wysoki | Średni | Niski | Niski |
| Dostęp do plików lokalnych | Pełny | Kontrolowany | File System Access API | File 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:
- Budujesz nowy bundle
- Podpisujesz go
- Publikujesz manifest aktualizacji
- Chrome sprawdza manifest co 4–6 godzin
- 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 WorkeremKiedy 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ć:
| Rok | Co przeglądarka „nie umiała" | Co umie dziś |
|---|---|---|
| 2010 | Geolokalizacja | Standardowa funkcja |
| 2012 | Offline | Service Workers, Cache API |
| 2014 | Push notifications | Web Push API |
| 2015 | Bluetooth | Web Bluetooth API |
| 2016 | USB | WebUSB API |
| 2018 | Płatności | Payment Request API |
| 2020 | Dostęp do plików | File System Access API |
| 2021 | GPU compute | WebGPU |
| 2023 | Surowe sockety | Direct 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.