What a wrapped site can do
The wrapper posture every Studio wrap gets, verbatim from the runtime.
A site that would phish you in a browser tab can phish you in its window — the gate cannot fix
social engineering. The fix is wrapping sites you chose.
Can — the wrapper posture
- Window controls, app menus, tray icon
win.* · menu.* · tray.* - Native dialogs, notifications, sound
dialog.* · notify · sound.play - Its own storage, theme, system info
store.* · theme.get · system.* - Dock badge & progress, media state
app.badge · app.progress · nowplaying.* - Write the clipboard, open links outside
clip.write · shell.open
Cannot — outside the posture
- Read the filesystemrejected at the gate — verified live, T1
- Read the clipboardwrite-only posture — verified live, T2
- Reach secrets or automationdebug.get denied — verified live, T3
- Escape via file:, javascript: or path walksfile: re-keyed to the site origin — T5a
- Borrow the gate from an iframesubframes get no bridge at all — verified live, T6
- Pollute the app's store via __proto__stored as inert data — verified live, T7
The guarantees, and when they shipped
These are tinyjs runtime properties — the Studio surfaces and configures them; the runtime enforces them, in the backend, where a hostile page cannot edit the check.
| Deny-by-default per-origin capability gate | Unlisted origins get nothing; the gate re-keys on the frame's real origin, engine-attested — not what the page claims. | 0.38+ |
| Subframe gating | A hostile cross-origin iframe cannot reach the backend on any platform: Linux drops untokened subframe calls; WebView2 only delivers the top document's messages; macOS gates subframe calls behind a named api.origins key — presets and top-level lists alone give iframes nothing. #18, verified live by T6/T6b. | Linux 0.46 · macOS 0.50.1 |
| win.open confinement | Pages may only open http(s) URLs or files inside their own frontend dir; file:, javascript:, ../ walks and UNC paths refused. #29 | 0.46 |
| Authenticated transport | The app↔window pipe requires a one-time secret handshake; single-instance pipes are per-user with ACLs. Nothing listens on any port. #29 | 0.46 |
| Storage isolation | Every app gets its own cookies, localStorage and IndexedDB — no cross-app reading, which is also why two wraps of one site are two accounts. | macOS always · Windows 0.45 |
| Built apps scrub the environment | Inherited TINYJS_*/WEBVIEW2_* variables are dropped — no page replacement, script injection or debug flags through env. #29 | 0.45 |
| Supply-chain pins & store hardening | txiki.js downloads are hash-pinned; tiny.store treats __proto__ keys as inert data. #26 | 0.45 |
| Signed builds, verified updates | Codesigned, notarization-ready bundles; the self-updater checks sha256 and the code signature, swaps in place, rolls back on failure — and since 0.47 runs the bundled installer, no per-update code download. | pre-1.0 · 0.47 |
| printToPDF write zones | A wrapped page can render a PDF only into Downloads (bare names), the app data folder, or temp — anything else opens a save panel. #36, verified live by T8/T8b. | 0.48 |
| Malformed messages dropped | Junk wire shapes die in the launcher — nothing reaches the backend unchecked. Verified live by T10. | 0.47.1 |
| URL schemes policy-gated & proxy confined | mailto:-style schemes are blocked by default (policy decides); the tiny-media proxy serves only the app's own pages. #30 | 0.47 |
Known open items — not hidden, tracked
A published threat model with open items beats a marketing page with none. Each row flips to “fixed in X” as releases land.
#36 — printToPDF clobbering. Was: any page-named path. Now: Downloads/app-data/temp only, save panel elsewhere — proven from outside by our suite's T8/T8b pair.
#30 — hardening batch 2. tiny-media proxy confined, URL schemes policy-gated, bundled-installer updates, malformed messages dropped (0.47.1).
#40 — update zip hash comes from the same host as the zip. Integrity anchor for the self-updater is still same-origin.
#19 — Windows artifacts are unsigned — no provenance anchor yet (PR #33 closed unmerged).
DOM popups execute javascript: URLs in the opener's own origin — no privilege gain (same gate), but the 0.46 screening covers the bridge path only. Surfaced by T5b, re-verified on 0.50.
Who publishes this?
Tauri & Electron publish security models and checklists — for developers who build with them.
Nativefier · WebCatalog · Unite · Wavebox publish no threat model at all.
TinyJS App Studio — the only site-wrapper with a threat model, an attack suite, and its open holes on display.