Concept in Installation
Isolated Web Apps
Published
An Isolated Web App is an application built with web technologies that is packaged into a Web Bundle, signed by its developer, and distributed to users instead of being hosted on a live web server and fetched over HTTPS. The WICG explainer proposes the model for applications whose threat model includes the application server itself being compromised, and for applications that need capabilities the ordinary web security model cannot grant.
How it works
Section titled “How it works”The explainer describes the core of the proposal as making application updates explicit. Unlike TLS keys, which have to be available online to establish new connections, the key used to sign the Web Bundle can be kept securely offline and is used infrequently, and the channel through which updates are distributed creates another point where new resources can be checked for potentially malicious content.
Packaging and signing
Section titled “Packaging and signing”Google’s ChromeOS documentation,
Isolated Web Apps, states that pages and
assets for an Isolated Web App are not served from live servers and are not fetched over
the network like normal web applications, and that the app’s resources are packaged into a
Signed Web Bundle, a .swbn file that concatenates the bundled resources with an integrity
block. It gives the signing keys as Ed25519 or ECDSA P-256 key pairs, the private key
signing the bundle and the public key verifying it.
That same page states a consequence for architecture: a site must be able to serve each of its pages while offline, so server-rendered pages are excluded, and statically generated or client-rendered sites are the architectures to consider.
Identity and the isolated-app scheme
Section titled “Identity and the isolated-app scheme”The explainer gives the reason the identity cannot stay a DNS name: a name is vulnerable to
a temporary loss of control over the domain or over the infrastructure used to validate
ownership of it, and the authors also wanted to avoid building an alternative to certificate
authorities sharing the same namespace. Isolated Web Apps therefore use a new scheme,
tentatively isolated-app://, whose authority section is based on the public key used to
sign the Web Bundle.
The explainer splits the detail into companion documents: the
Scheme Explainer describes
the isolated-app: scheme and signed web bundle IDs, and the
Updates Explainer describes
the version and update_manifest_url manifest fields and the updating process.
The ChromeOS page draws the practical conclusion: because identity is tied to the signing key, each app needs its own key, and the same app signed with different keys is treated as different apps. The signing tool prints the resulting Web Bundle ID and origin, and the page notes that Isolated Web Apps open in their own window without a URL bar, like a PWA, so users are unlikely to see that origin.
Manifest fields and updates
Section titled “Manifest fields and updates”The ChromeOS documentation states that an Isolated Web App’s Web App Manifest is not linked
from the HTML, because it has to be discoverable at install time: it must be located at
/.well-known/manifest.webmanifest and included in the package. It records two additional
fields beyond the manifest keys a PWA uses:
| Field | Status | What it holds |
|---|---|---|
version |
required for Isolated Web Apps | a string of one or more integers separated by a dot, matching the regular expression ^(\d+.?)*\d$ |
update_manifest_url |
optional but recommended | an HTTPS URL, or localhost for testing, where a Web Application Update Manifest can be retrieved |
The same page records that display behaves differently in this model: browser and
minimal-ui are both forced into a minimal-ui display, fullscreen and standalone are
both forced into a standalone display, and additional display_override options work as
expected. For downgrade protection, the explainer states that implementations may require
either a version manifest field or the signature timestamp to be monotonically increasing.
Policies applied to the app
Section titled “Policies applied to the app”Both documents list the headers that make the model hold. The explainer gives the Content
Security Policy applied to resources loaded from the bundle, in which 'self' refers to
resources from the bundle and excludes blob:, filesystem: and other local schemes as
well as inline script. It also gives the cross-origin isolation headers
Cross-Origin-Opener-Policy: same-origin, Cross-Origin-Embedder-Policy: require-corp,
Cross-Origin-Resource-Policy: same-origin and Content-Security-Policy: frame-ancestors 'self'.
Further restrictions follow from that. Both documents state that cross-origin navigations
into the application are disallowed to prevent sequence breaking attacks, so the application
is launched through a well-defined entry point such as its start_url, a protocol handler,
a Share Target, or a launch handler. And the ChromeOS page states that Isolated Web Apps
block all permission requests by default, with the developer opting in through a
permissions_policy manifest field; adding a permission there does not grant it, it makes
the permission available to be requested.
Availability
Section titled “Availability”The ChromeOS documentation carries a version note reading ChromeOS version: 128, and
states that the initial release of Isolated Web Apps, and any high-trust APIs that require
them, will be available to Chrome Enterprise administered ChromeOS devices and select
development partners, with an intention to expand to additional partners and to unmanaged
and cross-platform devices in the future. For local testing the same page asks for Chrome
or ChromeOS 120 or later with the Isolated Web App flags enabled.
The underlying platform concept is specified separately: Isolated Contexts is a Draft Community Group Report, published by the Web Platform Incubator Community Group, that defines isolated contexts so that implementers and specification authors can enable certain features only when minimum standards of isolation and integrity are met. It states that it is not a W3C Standard and is not on the W3C Standards Track.
Examples
Section titled “Examples”The snippets below cover the manifest an Isolated Web App needs, the permissions field, and a runtime check that keeps shared code working outside the model.
A minimal manifest for an Isolated Web App
Section titled “A minimal manifest for an Isolated Web App”The ChromeOS page’s minimal example adds version and update_manifest_url to the keys a
PWA manifest already carries, and the file is shipped at
/.well-known/manifest.webmanifest inside the bundle rather than linked from the HTML.
{ "name": "IWA Kitchen Sink", "version": "0.1.0", "update_manifest_url": "https://example.com/updates.json", "start_url": "/", "icons": [ { "src": "/images/icon.png", "type": "image/png", "sizes": "512x512", "purpose": "any" }, { "src": "/images/icon-mask.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" } ]}A Web Application Update Manifest is a JSON file describing each version of the
application. The
Updates Explainer gives it
a single JSON object with a top-level versions field holding a list, which is the key the
ChromeOS page’s own example uses. Each entry in the list carries at least version and
src: version is a string in the format of the manifest’s own version field, and src
is a URL resolved relative to the location of the update manifest, which must be an HTTPS
URL or a localhost HTTP URL for testing. The explainer marks channels optional — a list of
Update Channel identifiers, treated as ["default"] when it is not set.
Declaring the permissions the app may request
Section titled “Declaring the permissions the app may request”The ChromeOS page’s fleet-tracking example allows the app and one embedded map origin to request geolocation, and any origin to request fullscreen.
{ "permissions_policy": { "geolocation": ["self", "https://map.example.com"], "fullscreen": ["*"] }}Because the field makes a permission requestable rather than granted, the app still calls the ordinary permission API and still handles a refusal. A capability absent from this object is blocked before the request reaches the user.
Detecting the model at runtime
Section titled “Detecting the model at runtime”Code shared between a site and its Isolated Web App build needs to know which one it is running in. The scheme and cross-origin isolation are both documented properties of the model, so the check reads them rather than sniffing a user agent.
function runsInIsolatedAppRuntime() { if (!('crossOriginIsolated' in window)) { // No cross-origin isolation signal: treat this as an ordinary web page. return false; } return window.crossOriginIsolated && location.protocol === 'isolated-app:';}
if (runsInIsolatedAppRuntime()) { document.documentElement.dataset.runtime = 'isolated-app';} else { // Ordinary web page: the high-trust APIs are absent, so keep the network code path. document.documentElement.dataset.runtime = 'web';}What the check reports is the runtime, not how the app was delivered. A Dev Mode Proxy
install runs on isolated-app: under the same policies while pointing at a development
server rather than a bundle, so it answers isolated-app here too. The protocol and
crossOriginIsolated signals used above do not separate those two delivery paths, so code
that needs to tell a signed bundle from a proxied development install has to carry its own
marker, such as a build-time flag.
Use the result to pick a code path, not to assume a capability: a permission still has to be
present in both the permissions_policy field and the bundle’s headers before the app can
request it.
Observed behaviour
Section titled “Observed behaviour”The development path is reachable without an enterprise enrolment, and the strings below are the ones the documentation prints for it.
The page states that a Dev Mode Proxy install can point at any URL, including a local development server, without bundling it, and that the app installed that way is assigned a random identifier. So an origin observed during development is not the origin the signed build will have.
See also
Section titled “See also”- Installability criteria
- Trusted Web Activity
- PWAs on ChromeOS (launcher and shelf)
- display manifest member
- Isolated Web Apps Explainer (github.com)
- Isolated Web Apps Updates Explainer (github.com)
- Isolated Web Apps (chromeos.dev)
- Isolated Contexts (wicg.github.io)
Specifications
| Specification | Status |
|---|---|
| None. | |