Specification
Draft 1. An .applet is a zip of static web files plus a manifest.json. Appverse unpacks it in the browser and runs it in a locked-down sandbox.
Manifest
| Field | Required | Meaning |
|---|---|---|
applet | yes | Format version, currently 1. |
id | yes | Reverse-domain id, e.g. com.example.notes. |
title, author, version | yes | Shown on the permission card. |
entry | yes | HTML file to load, normally index.html. |
width, height | no | Preferred frame size in CSS pixels. |
permissions | no | List from the table below. Shown to the user before the app runs. |
Permissions
| Permission | Gives the app |
|---|---|
storage | appverse.storage.get/set/remove, a per-app key-value store kept in the visitor's browser. |
fullscreen | Ability to ask for fullscreen, on a user gesture. |
clipboard | Write to the clipboard, on a user gesture. |
network (planned) | Requests to an allowlist of hosts declared in the manifest and shown to the user. |
The sandbox
- The package is read and unpacked in the browser; nothing is uploaded. The zip reader rejects path traversal, duplicate names, encrypted or zip64 entries, bad CRCs, entries larger than declared, and packages over the file-count and size caps.
- The app runs in
<iframe sandbox="allow-scripts">, with noallow-same-origin, popups or top navigation, so it has an opaque origin and cannot touch the host page, cookies or storage. - In production the frame is served from a separate origin (for example
*.appverse-apps.lol) so a sandbox escape does not reach the main site. - Appverse rewrites the entry HTML on load and inserts a CSP
<meta>as the first element of<head>:
The package's files are inlined into that one document: scripts and stylesheets become inline code, and images, fonts and media becomedefault-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: blob:; media-src data: blob:; font-src data:; worker-src blob:; connect-src 'none'; frame-src 'none'; form-action 'none'; base-uri 'none'data:URLs. A reference to anything outside the package (http:,//host) or to a missing file is an error. Bundle your JavaScript into plain scripts: ES moduleimportof other files does not work. A package whose HTML already has a CSP meta tag is rejected. - The only way out is a small
postMessagebridge, gated by the manifest permissions.
Known limits
- An app can use a lot of CPU or memory. Stop destroys the frame.
- An app can show misleading content, such as a fake sign-in form. The frame is labelled as untrusted, and the player says never to enter passwords. Only run apps from people you trust.
- CSP and sandbox behaviour differ slightly between browsers, so the test suite checks the escape routes (
fetch, images, CSSurl(), forms, WebRTC,sendBeacon, popups, navigation) in each engine.