mirror of
https://github.com/Kong/insomnia.git
synced 2026-07-30 09:16:44 -04:00
* feat(templating): multi-file plugins via in-sandbox module map (M4)
esbuild is dev-only, so instead of bundling plugins at load time this reads the
plugin's own source files into a module map (readPluginModuleMap, host-side)
and teaches the in-sandbox require to resolve RELATIVE specifiers from that map
(./util, ../x, ./dir -> ./dir/index.js) with a CommonJS cache. Bare specifiers
still route through the grant-gated registry.
Security (the poison guarantee): the host walker reads ONLY within the plugin
directory — node_modules and dot-dirs are skipped, symlink-escapes dropped,
file count/size bounded — so a plugin's own node_modules is never consulted and
a bare require('uuid') always binds the vetted registry copy, never a plugin's
substitute. Plugin source now travels as envelope DATA (moduleFiles) compiled by
the loader via new Function; no host-side eval of plugin code. Single-file
callers keep working via a synthesized one-entry map.
Tests: multi-file-plugins.test.ts (7: relative/nested/dir-index resolution,
hybrid bare-uuid, CJS cache, not-found, syntax-error propagation, bare-vs-map
shadow) + readPluginModuleMap tests (map shape, node_modules-excluded poison
guarantee, custom main, entry-escape). E2E: multi-file resolution + poison
(fake node_modules/uuid ignored). Demo converted to multi-file
(require('./lib/greeting')). PERMISSIONS.md documents multi-file + the
require-vetted-libs-inside-run note.
No esbuild runtime dependency added.
* fix(templating): tighten M4 module-map byte guard and relative-path escape
Address review feedback on the multi-file plugin loader:
- readPluginModuleMap counted source.length (UTF-16 code units), which
undercounts multi-byte UTF-8 payloads against MAX_PLUGIN_MODULE_BYTES, and
the custom-"main" entry fallback was added to the map without counting its
bytes at all. Count Buffer.byteLength(...'utf8') via a shared addModule
helper used by both the walk and the entry fallback.
- __normalizeKey clamped above-root '..' traversal back into the plugin root,
so require('../../util') from a shallow dir could masquerade as an in-plugin
module. Return null for above-root traversal (unresolvable), matching Node
semantics; __resolveRelative propagates it as MODULE_NOT_FOUND.