🔒 security, published — not promised

A wrapped site can do exactly
what you allow. Nothing else.

Every claim on this page links the tinyjs release or issue behind it, and the adversarial suite attacks our own wraps on camera — including the holes that are still open.

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 iconwin.* · menu.* · tray.*
  • Native dialogs, notifications, sounddialog.* · notify · sound.play
  • Its own storage, theme, system infostore.* · theme.get · system.*
  • Dock badge & progress, media stateapp.badge · app.progress · nowplaying.*
  • Write the clipboard, open links outsideclip.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 gateUnlisted origins get nothing; the gate re-keys on the frame's real origin, engine-attested — not what the page claims.0.38+
Subframe gatingA 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 confinementPages may only open http(s) URLs or files inside their own frontend dir; file:, javascript:, ../ walks and UNC paths refused. #290.46
Authenticated transportThe app↔window pipe requires a one-time secret handshake; single-instance pipes are per-user with ACLs. Nothing listens on any port. #290.46
Storage isolationEvery 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 environmentInherited TINYJS_*/WEBVIEW2_* variables are dropped — no page replacement, script injection or debug flags through env. #290.45
Supply-chain pins & store hardeningtxiki.js downloads are hash-pinned; tiny.store treats __proto__ keys as inert data. #260.45
Signed builds, verified updatesCodesigned, 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 zonesA 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 droppedJunk wire shapes die in the launcher — nothing reaches the backend unchecked. Verified live by T10.0.47.1
URL schemes policy-gated & proxy confinedmailto:-style schemes are blocked by default (policy decides); the tiny-media proxy serves only the app's own pages. #300.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.

fixed 0.48

#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.

fixed 0.47

#30 — hardening batch 2. tiny-media proxy confined, URL schemes policy-gated, bundled-installer updates, malformed messages dropped (0.47.1).

open

#40 — update zip hash comes from the same host as the zip. Integrity anchor for the self-updater is still same-origin.

open

#19 — Windows artifacts are unsigned — no provenance anchor yet (PR #33 closed unmerged).

observation

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.

Read it all, attack it yourself

The full threat model, the adversarial suite and the reporting policy are in the repo.

Threat model Adversarial suite Report a vulnerability