Security Boundaries
Kawaikara renders untrusted third-party websites inside Electron. The runtime therefore treats remote documents differently from application-owned renderers.
Baseline
Kawaikara renders untrusted third-party websites inside Electron. The runtime therefore treats remote documents differently from application-owned renderers.
- Node.js is never exposed to a remote site.
- The full Kawaikara IPC API is never exposed to a remote site.
- Main-process operations are presented as narrow capabilities.
- Navigation, new windows, external URLs, and PiP entry pass through Provider policy.
- Cookies, login, script injection, header interception, and external helper installation are sensitive operations.
Renderer isolation
Viewer, overlay, and popup web preferences use:
{
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
}
The capability surface still differs by renderer:
| Surface | Preload exposure | Purpose |
|---|---|---|
| Remote SiteView | Restricted viewer preload | File-drop capture, editable-focus reporting, and the internal Video bridge only where applicable |
| Overlay | Typed app preload | App-owned menu, preferences, media, update, and profile operations |
| OAuth popup | No app bridge | Provider page isolated with the current site Session |
| External browser | Separate browser process/profile | Login when embedded authentication is rejected |
The viewer preload must remain small. A helper needed by a remote page is not automatically safe to add to window.
Plugin trust model
SiteContext is deliberately narrower than Electron, but the current plugin module is imported into the Main process. It is therefore trusted application code.
A third-party JavaScript Bundle cannot be treated as untrusted merely because its Provider receives
SiteContext. If the Bundle is imported by Main, it can potentially access Node.js through its own module code.
Before arbitrary user-installed plugins are supported, the project needs a defensible execution model such as a utility process, a proven sandbox, or a declarative integration format. Publisher identity, signature validation, updates, rollback, and user consent also remain unresolved.
Permission metadata
Providers can declare:
navigationinternal-viewplugin-viewscript-injectioncookiesnetwork-interceptionexternal-browser
These values are runtime capability boundaries as well as installation consent metadata. Navigation and internal-view calls reject missing permissions; cookies, page injection, and browser identity are omitted from the Provider context when undeclared; action URLs and external-browser calls reject missing permissions.
flowchart LR
Plugin --> Scoped["Permission-scoped SiteContext"]
Scoped -->|allowed| Capability
Scoped -->|denied| Error
Script injection
context.page operations run with the target page’s authority. Integration code should:
- Never interpolate user input or untrusted DOM text directly into source strings.
- Serialize values with
JSON.stringify(). - Install a document marker so repeated DOM/load hooks remain idempotent.
- Inject the smallest possible interceptor instead of a large application runtime.
- Avoid writing passwords, tokens, cookies, or authentication callback data to the DOM or console.
- Restore modified styles, controls, user agents, and listeners during unload or PiP exit.
Action URLs
kawaikara-action://invoke/<action> is input from a remote document.
WindowManageralways prevents the navigation itself.- Only the active Provider receives the action.
createUrl()rejects malformed action names.- Unknown actions must return
false. - Any future payload needs a schema, size limit, and explicit encoding rules before it is accepted.
Cookies, profiles, and external login
External login copies only cookies from a temporary Chrome/Edge profile into the Electron Session selected for the site. The runtime never logs cookie values, never reuses an external browser profile, removes the temporary profile when the flow ends, and deletes state left by the retired persistent-profile implementation. Electron’s selected Session is the sole persistent owner of imported authentication cookies.
Site-specific persistent isolation is the default. A plugin default or user assignment can intentionally place multiple sites in the same Session. This shares cookies, cache, local storage, and potentially DRM-sensitive state. The preference UI warns when a DRM-marked site is assigned to a shared profile, but does not prohibit the assignment.
For services sensitive to cross-site state, including Netflix-style E100 failures, keep the site isolated unless shared sign-in is known to be safe. OAuth popups use the opener site’s Session; they do not create a new shared identity boundary.
New windows and OAuth
The default Provider policy preserves browser popup semantics in a sandboxed child window using the current site Session. This is necessary because OAuth often starts on a first-party callback URL before redirecting to the identity provider, so the first URL cannot always be recognized by an authentication host allowlist. Providers that know their navigation surface should narrow it.
- Use
viewerfor ordinary same-service navigation. - Use
popupfor login and other flows that need opener semantics. - Use
externalonly when the OS is intentionally responsible for the URL. - Use
denyfor unneeded windows.
Allowlist checks must parse the URL and compare protocol and hostname. A substring such as includes('example.com') also matches attacker-controlled lookalike domains.
Downloader installation
The external downloader installer is an application-owned privileged workflow even though it does not request administrator access.
- Manifest and artifacts must use HTTPS.
- Artifacts are restricted to the project’s GitHub release path.
- The downloaded file’s SHA-256 must match the release manifest.
- On macOS, the app bundle identity is checked before installation.
- Installation is limited to
~/Applications. - Existing installations are moved to Trash rather than recursively overwritten.
- Quarantine removal is performed only after an explicit user confirmation and only for the verified download and staged app bundle.
This is not a general-purpose package installer and must not accept arbitrary hosts, paths, bundle IDs, or shell arguments.
Security review checklist
- Can a remote page invoke a new Main capability directly?
- Are IPC values and URLs validated at runtime?
- Are scheme and hostname checks exact allowlists?
- Are listeners, popups, temporary profiles, timers, object URLs, and injected styles cleaned up?
- Could logs contain a cookie, token, email address, or sensitive URL query?
- Do declared permissions match actual capabilities used?
- Does an error path fall back to a more privileged behavior?
- Does shared Session state create a DRM or authentication interaction between sites?
- Does an installer verify identity and integrity before modifying an application directory?