mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 16:13:15 +00:00
52 lines
2.4 KiB
TypeScript
52 lines
2.4 KiB
TypeScript
// Single source of truth for which execution tier a plugin runs in.
|
|
//
|
|
// The decision is security-critical: granting 'privileged' creates a
|
|
// same-origin iframe (full WebCrypto + IndexedDB + access to the host origin),
|
|
// so it must NEVER be granted to an unsigned or unapproved bundle. This helper
|
|
// is called by BOTH the loader (load gate, before the same-origin iframe is
|
|
// created) and the plugin store (enable gate), so the rules live in one place.
|
|
//
|
|
// A plugin that *requests* privileged but fails any gate is REFUSED (returns
|
|
// `{ tier: null, error }`), never silently downgraded — a crypto plugin cannot
|
|
// run in a null-origin sandbox, and a silent downgrade would mask tampering.
|
|
|
|
import type { InstalledPlugin, PluginTier } from '../plugin-types';
|
|
|
|
export type TierResolution =
|
|
| { tier: PluginTier; error?: undefined }
|
|
| { tier: null; error: string };
|
|
|
|
/**
|
|
* Resolves the execution tier for a plugin. Returns `{ tier }` on success or
|
|
* `{ tier: null, error }` when a requested tier cannot be granted (the caller
|
|
* should put the plugin into an error state and NOT create an iframe).
|
|
*
|
|
* Privileged tier gates (ALL required):
|
|
* 1. Manifest declares the umbrella high-risk permission `crypto:full`.
|
|
* 2. An admin installed it (`managed`). Admin installs are the operator's
|
|
* decision, so there is no separate approval or per-user consent step.
|
|
* 3. Its bundle verifies against the signature made at install time; the
|
|
* download refuses an unsigned or mis-signed privileged bundle.
|
|
*/
|
|
export function resolvePluginTier(plugin: InstalledPlugin): TierResolution {
|
|
if (plugin.tier !== 'privileged') {
|
|
return { tier: 'untrusted' };
|
|
}
|
|
|
|
// 1. Must declare the umbrella high-risk permission.
|
|
if (!plugin.permissions.includes('crypto:full')) {
|
|
return { tier: null, error: 'Privileged tier requires the "crypto:full" permission' };
|
|
}
|
|
|
|
// 2. Only an admin can install a privileged plugin. A plugin the user
|
|
// uploaded is never privileged, whatever its manifest claims; installing
|
|
// over an admin plugin's id is refused (see installPlugin). The bundle
|
|
// itself must carry the signature made at admin install time, which the
|
|
// bundle download checks for privileged plugins (downloadManagedBundle).
|
|
if (!plugin.managed) {
|
|
return { tier: null, error: 'Privileged tier requires a signed bundle delivered through the admin channel' };
|
|
}
|
|
|
|
return { tier: 'privileged' };
|
|
}
|