Skip to content

Security And Current Limits ​

An installed Mantis extension runs your code inside the Mantis page. This page explains what it can reach, what constrains it, and what is not supported yet.

Trust model ​

Only install extensions from sources you trust.

An extension can:

  • run JavaScript inside its extension host
  • run JavaScript inside its panel
  • access Mantis data covered by granted permissions
  • create bags if granted bags:write
  • open and close panels if granted panels:write
  • register and execute commands if granted commands:execute
  • store extension state through workspaceState and globalState
  • invoke its Python backend if granted backend:invoke
  • run Python dependencies declared in requirements
  • access the network from its backend if network is true

The install dialog shows the declared permissions, contributed panels, backend status, and backend network request.

Browser access ​

Host and panel code must use mantis / window.mantis to communicate with Mantis. Permissions are checked on SDK calls. If permission is missing, the call fails.

The extension host runs in a Web Worker. Panels run in sandboxed iframes with sandbox="allow-scripts" only (no allow-same-origin). That keeps the panel on an opaque origin so it cannot read the parent’s cookies, localStorage, or DOM. Do not add allow-same-origin for extension panels without a full security review.

For durable UI state, panels should use window.mantis.workspaceState / window.mantis.globalState (see SDK reference). That storage is handled in the parent page over the RPC bridge, like the host worker's context.workspaceState / globalState.

They are separate browser execution contexts, but they are still trusted extension code.

Hard limits ​

These are the edges an author actually hits. None of them are configurable from a package.

LimitValueWhat happens when you exceed it
RPC timeout, panel and host30 sThe promise rejects with Mantis extension RPC timeout: <method>.
Command invocation timeout30 sThe promise rejects with a command timeout.
Python backend execution30 s by defaultThe invocation fails. Combined with the RPC cap, a synchronous long analysis is not possible.
Package size25 MBImport is refused.
Single file size5 MBImport is refused.
File encodingUTF-8 text onlyImport is refused with "Extension file must be UTF-8 text". No images, fonts, or wasm can be shipped in a package; inline them as data URIs or fetch them at runtime.
Versions of one idNewest onlyOlder versions stay on the server but the workspace loads only the highest version of each extension id.

Extension state (workspaceState and globalState) is localStorage in the Mantis page, not account state. It is per-browser-profile, is not synced across devices, and is lost when site data is cleared.

Backend execution ​

Python backends run with additional safeguards. Mantis:

  • validates backend paths
  • installs requirements into a per-extension cache
  • applies execution timeouts
  • defaults backend network mode to no network

These safeguards reduce accidental damage, but they do not make unknown code safe. Treat backend code as trusted.

Permissions are not a marketplace review ​

Permissions limit access at runtime, but they do not prove an extension is safe. A malicious extension with maps:read can still read map data visible through that permission.

Before installing, check:

  • who published it
  • why it needs each permission
  • whether backend network is requested
  • whether requirements are expected
  • whether the package source is trusted

Current limits ​

The current extension system is beta. It now has background activation, durable commands, deactivate hooks, manifest.main, activationEvents, and basic extension state.

Not supported yet:

  • writing the point selection. selection:write is defined in the frontend permission enum and gates selection.set(), but the install validator rejects it, so a package declaring it does not install at all. Extensions can read the selection and create bags; they cannot set the selection.
  • calling native Mantis commands. The native command allowlist is empty (see below).
  • menus contribution point
  • settings contribution point
  • binary assets in a package
  • marketplace signing
  • verified publishers
  • extension dependency graph
  • stable SDK compatibility field like engines.mantis
  • secret storage
  • extension update channels
  • CSP-per-extension origin isolation

Command lifetime limit ​

Commands can be registered from the extension host:

js
exports.activate = async function activate(context) {
  const disposable = await mantis.commands.registerCommand(
    'demo.sample-panel.refresh',
    refresh,
  );

  context.subscriptions.push(disposable);
};

Host-registered commands survive panel close and are cleaned up when the host deactivates.

Panels may still register commands:

js
const disposable = await window.mantis.commands.registerCommand(
  'demo.sample-panel.refresh',
  refresh,
);

Panel-registered command handlers live with that panel instance. If the panel closes, those handlers are disposed.

Native command execution ​

window.mantis.commands.execute can execute commands that an extension registered. Native Mantis commands go through an allowlist, and that allowlist is currently empty, so the effective answer today is that no built-in Mantis action is reachable from an extension. Anything not registered by an extension throws.

commands:execute therefore grants far less than its name suggests. It does not let an extension drive the Mantis UI.

Data handling guidance ​

Extension authors should:

  • request the smallest permission set possible
  • avoid sending sensitive data to external services
  • keep backend network disabled unless required
  • validate payloads before processing
  • show clear errors instead of silently swallowing failures
  • document what the extension reads and writes

Future direction ​

The contribution points reserved in the manifest (menus, settings) suggest where the platform is headed, and a native command allowlist exists in code waiting to be populated. Nothing on that list has a ship date, so build against what is documented above rather than what is reserved.