Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/_indices/insomnia.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ sections:
- path: /insomnia/plugins/plugin-reference/
- path: /insomnia/plugins/context-object-reference/
- path: /insomnia/plugins/hooks-and-actions/
- path: /insomnia/plugins/sandbox-and-trust/
- path: /insomnia/plugins/permissions/
- path: /insomnia/plugins/troubleshooting/

- title: Authentication and authorization
items:
Expand Down
102 changes: 102 additions & 0 deletions app/insomnia/plugins/permissions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
title: Plugin permissions

description: "Declare the modules and host capabilities a sandboxed Insomnia plugin needs with the insomnia.permissions manifest, and learn the default-deny baseline and capability reference."

content_type: reference
layout: reference

products:
- insomnia

breadcrumbs:
- /insomnia/
- /insomnia/plugins/

tags:
- insomnia-plugins

search_aliases:
- insomnia.permissions
- plugin capabilities
- plugin modules
- sandbox permissions

related_resources:
- text: Plugins
url: /insomnia/plugins/
- text: Plugin sandbox and trust model
url: /insomnia/plugins/sandbox-and-trust/
- text: Context object reference
url: /insomnia/plugins/context-object-reference/
- text: Plugin troubleshooting
url: /insomnia/plugins/troubleshooting/
---

When a plugin runs sandboxed, it is **default-deny** on two axes: which modules it can `require()`, and which host capabilities it can call. Declare what your plugin needs in its `package.json` under the `insomnia.permissions` key.

```json
{
"name": "insomnia-plugin-example",
"insomnia": {
"permissions": {
"modules": ["crypto", "ajv"],
"capabilities": ["network", "storage"]
}
}
}
```

A plugin with no `permissions` block gets the baseline only (see below). Requesting anything beyond the baseline requires declaring it, or the call fails with an actionable error such as:

```
capability 'network' not granted — add it to insomnia.permissions.capabilities
```

## Baseline (no manifest)

A plugin that declares no permissions still gets a minimal, read-only baseline:

| Axis | Baseline grant |
|------|----------------|
| Modules | `path`, `crypto` |
| Capabilities | `render`, `models.read`, `util`, `crypto` |

Anything network, filesystem, credential, storage, or app/UI related must be declared explicitly.

## Capabilities reference

Values you can declare in `insomnia.permissions.capabilities`:

| Capability | Grants |
|------------|--------|
| `render` | Nested template rendering (`context.util.render`) |
| `models.read` | Read requests, workspaces, cookie jars, responses, settings, and OAuth 2.0 tokens |
| `util` | Encode/decode and host OS info helpers |
| `crypto` | The host-backed `crypto` module (hash, HMAC, random) |
| `network` | Outbound HTTP via `context.network.sendRequest` |
| `storage` | Plugin-scoped key/value store (`context.store`) |
| `fs-read` | Allow-listed file reads |
| `credentials` | Read and update stored cloud credentials |
| `app` | Dialogs, prompts, clipboard, and open-in-browser |

Check failure on line 81 in app/insomnia/plugins/permissions.md

View workflow job for this annotation

GitHub Actions / Vale

[vale] reported by reviewdog 🐶 [docs.Spelling] Did you really mean 'Dialogs'? Raw Output: {"message": "[docs.Spelling] Did you really mean 'Dialogs'?", "location": {"path": "app/insomnia/plugins/permissions.md", "range": {"start": {"line": 81, "column": 11}}}, "severity": "ERROR"}

{:.warning}
> `models.read` includes reading **OAuth 2.0 tokens**, which are live bearer credentials, and it's part of the baseline. Treat it as a credential-disclosure surface when reasoning about what a manifest-less plugin can access.

## Modules reference

Inside the sandbox, `require(name)` resolves **only** from Insomnia's curated registry — never your plugin's `node_modules`, and never raw Node.js built-ins. Declaring a module in `insomnia.permissions.modules` unlocks it; the registry is what provides a safe implementation.

Categories:

* **Baseline:** `path`, `crypto`
* **Polyfilled built-ins:** for example `events`

Check failure on line 93 in app/insomnia/plugins/permissions.md

View workflow job for this annotation

GitHub Actions / Vale

[vale] reported by reviewdog 🐶 [docs.Spelling] Did you really mean 'Polyfilled'? Raw Output: {"message": "[docs.Spelling] Did you really mean 'Polyfilled'?", "location": {"path": "app/insomnia/plugins/permissions.md", "range": {"start": {"line": 93, "column": 5}}}, "severity": "ERROR"}
* **Vetted libraries:** for example `ajv`, `uuid`

<!-- TODO(before publish): replace the examples above with the canonical, generated module list
(ALL_SANDBOX_MODULES in the Insomnia source) so this reference can't drift. -->

Two distinct error messages tell you which problem you have:

* `Module 'X' not permitted by manifest` — the module exists in the registry, but you didn't declare it.
* `Module 'X' not available in sandbox` — you declared it, but it isn't in the registry.
94 changes: 94 additions & 0 deletions app/insomnia/plugins/sandbox-and-trust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: Plugin sandbox and trust model

description: "Understand how Insomnia runs plugin code — in-process versus the QuickJS sandbox — the pluginSandboxEnabled setting, per-plugin elevated access, and how to migrate an existing plugin."

content_type: reference
layout: reference

products:
- insomnia

breadcrumbs:
- /insomnia/
- /insomnia/plugins/

tags:
- insomnia-plugins

search_aliases:
- Insomnia plugin sandbox
- pluginSandboxEnabled
- elevated plugin
- full host access

related_resources:
- text: Plugins
url: /insomnia/plugins/
- text: Plugin permissions
url: /insomnia/plugins/permissions/
- text: Plugin troubleshooting
url: /insomnia/plugins/troubleshooting/
- text: Plugin reference
url: /insomnia/plugins/plugin-reference/
---

## How plugin code runs

Insomnia can run an installed (user) plugin's code in one of two places:

* **In-process** — directly in the app process, with full Node.js access (`fs`, `child_process`, arbitrary `require`, and so on). This is the original behavior.
* **In the QuickJS sandbox** — an isolated JavaScript runtime with no direct Node.js access. The plugin reaches the app only through a capability-gated bridge, and `require()` resolves only from a curated module registry. See [Plugin permissions](/insomnia/plugins/permissions/).

Which one is used depends on a global setting and a per-plugin opt-in.

## The `pluginSandboxEnabled` setting

In **Preferences > Scripting**, enable **Sandbox all plugin code**. When it's on, every untrusted (user) plugin surface — template tags, request and response hooks, actions, and load-time code — runs in the sandbox.

This setting supersedes the earlier experiment, **Run template tags in sandbox** (`templateTagSandboxEnabled`). During migration, *either* setting activates the sandbox, so if you already enabled the template-tag experiment, nothing changes for you. New guidance should refer only to `pluginSandboxEnabled`.

## Execution modes

For a given plugin, the resolved mode is one of:

| Mode | When | Runs | Host access |
|------|------|------|-------------|
| **Trusted** | First-party bundled plugin (ships with Insomnia) | In-process | Full (by design) |
| **Sandboxed** | User plugin, sandbox on, not elevated | QuickJS sandbox | Only declared capabilities |
| **Elevated** | User plugin, sandbox on, "Full host access" turned on | In-process | Full |
| **In-process** | User plugin, sandbox off | In-process | Full (legacy) |

**Preferences > Plugins** shows each plugin's mode as a badge next to its name.

## Full host access (elevated)

Some community plugins genuinely need native modules or host access the sandbox doesn't grant. For those, **Preferences > Plugins** provides a per-plugin **Full host access** toggle. It is:

* **Off by default** — a plugin is sandboxed unless you deliberately elevate it.
* **Per-plugin** — never global.
* **A trust decision** — an elevated plugin runs in-process with full Node.js access, exactly like the pre-sandbox behavior. Only elevate plugins you trust.

## Migrate an existing plugin

If your plugin worked before the sandbox and breaks when it's on:

1. **Does it `require()` `fs`, `child_process`, or an arbitrary npm package?** Those aren't reachable in the sandbox. Move to a registry module and declare it (see [Plugin permissions](/insomnia/plugins/permissions/)), or ask the user to enable **Full host access** for your plugin.
2. **Does it call `context.network`, read files, use storage, or read credentials?** Declare the matching capability in `insomnia.permissions.capabilities`. An undeclared call fails with an error naming the missing capability.
3. **Is it a multi-file plugin?** Your own `node_modules` is *not* consulted at runtime — third-party dependencies must be registry modules declared in `insomnia.permissions.modules`.

## Caveats

* **The Inso CLI has no sandbox.** Under the pure-Node CLI, user-plugin hooks run in-process regardless of the setting — CLI users are trusting their own plugins.
* **Bundled template tags** run in the sandbox only under the legacy `templateTagSandboxEnabled` experiment (a hardening opt-in); enabling `pluginSandboxEnabled` leaves trusted first-party plugins in-process.

## What changed

The sandbox is a deliberate hardening, not a set of regressions:

| Change | Kind | Effect for plugin authors |
|--------|------|---------------------------|
| User plugins run in the QuickJS sandbox when the sandbox is on | Hardening | Plugin code no longer has raw Node.js; it reaches the app only through declared capabilities |
| `require()` resolves only from a curated registry | Hardening | Arbitrary npm or `node_modules` requires fail unless the module is in the registry *and* declared |
| Default-deny permissions (baseline only unless declared) | Hardening | A plugin that used network, filesystem, or credentials without declaring them must add an `insomnia.permissions` block |
| Load failures now show as a disabled row with a reason | Fix | A plugin that fails to load (or whose name collides with another) no longer silently disappears — see [Troubleshooting](/insomnia/plugins/troubleshooting/) |
61 changes: 61 additions & 0 deletions app/insomnia/plugins/troubleshooting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: Plugin troubleshooting

description: "Diagnose Insomnia plugin problems — plugins that fail to load now show a disabled row with a reason instead of disappearing — plus current sandbox known limitations."

content_type: reference
layout: reference

products:
- insomnia

breadcrumbs:
- /insomnia/
- /insomnia/plugins/

tags:
- insomnia-plugins

search_aliases:
- plugin disappeared
- plugin failed to load
- plugin not showing

related_resources:
- text: Plugins
url: /insomnia/plugins/
- text: Plugin sandbox and trust model
url: /insomnia/plugins/sandbox-and-trust/
- text: Plugin permissions
url: /insomnia/plugins/permissions/
---

## A plugin disappeared from the list

A plugin that fails to load **no longer silently disappears**. Instead it appears in **Preferences > Plugins** as a disabled row with a reason:

* Open **Preferences > Plugins** and look for a row marked **Failed to load plugin** (a warning icon, and no enable checkbox). Expand it to see the exact error.

Common reasons and fixes:

| Reason shown | Cause | Fix |
|--------------|-------|-----|
| `Cannot find module '…'` | A `require()` failed (a missing dependency, or a module that isn't in the sandbox registry) | Add the dependency as a registry module in `insomnia.permissions.modules`, or fix the missing dependency. See [Plugin permissions](/insomnia/plugins/permissions/). |
| `Multiple plugin folders declare the name "…"` | Two folders under your plugin paths declare the same plugin `name` | Remove or rename the duplicate folder. While a name is claimed by more than one folder, *none* of them load — this is deliberate, to avoid an ambiguous trust grant. |
| Other load-time error | The plugin's top-level code threw | Read the message. If the plugin needs host access the sandbox doesn't grant, consider **Full host access** — see [Plugin sandbox and trust model](/insomnia/plugins/sandbox-and-trust/). |

### A plugin stayed broken even after I fixed the error

Older versions cached the plugin and render engine for the whole session, so a plugin that failed once stayed broken until you restarted the app. This is fixed. Use **Preferences > Plugins > Reload plugins** (or the plugin-reload keyboard shortcut): reloading now rebuilds the render engine and re-scans the registry, so a plugin recovers once its underlying error is fixed. You no longer need to reinstall it into a fresh folder.

## Known limitations

### `context.app.dialog()` with a DOM element

`context.app.dialog(title, body, options)` currently expects `body` to be a live DOM element. When an action runs in the isolated plugin window, that element can't be passed across Electron IPC to the main window (DOM nodes aren't structured-cloneable), so the call fails with `An object could not be cloned` (tracked in [Kong/insomnia#10292](https://github.com/Kong/insomnia/issues/10292)).

Until this is addressed, avoid passing DOM nodes across the boundary — prefer serializable content, or a template tag / other UI affordance for now.

Check failure on line 57 in app/insomnia/plugins/troubleshooting.md

View workflow job for this annotation

GitHub Actions / Vale

[vale] reported by reviewdog 🐶 [docs.Spelling] Did you really mean 'affordance'? Raw Output: {"message": "[docs.Spelling] Did you really mean 'affordance'?", "location": {"path": "app/insomnia/plugins/troubleshooting.md", "range": {"start": {"line": 57, "column": 130}}}, "severity": "ERROR"}

Check failure on line 57 in app/insomnia/plugins/troubleshooting.md

View workflow job for this annotation

GitHub Actions / Vale

[vale] reported by reviewdog 🐶 [docs.Spelling] Did you really mean 'serializable'? Raw Output: {"message": "[docs.Spelling] Did you really mean 'serializable'?", "location": {"path": "app/insomnia/plugins/troubleshooting.md", "range": {"start": {"line": 57, "column": 79}}}, "severity": "ERROR"}

## Still stuck?

[Open an issue](https://github.com/Kong/insomnia/issues) with the exact text from the plugin's disabled-row reason and your `package.json` `insomnia` block.
Loading