feat(templating): vetted npm libraries in the sandbox — uuid + ajv (M3) - #10244
Conversation
✅ Circular References ReportGenerated at: 2026-07-16T04:01:00.488Z Summary
Click to view all circular references in PR (9)Click to view all circular references in base branch (9)Analysis✅ No Change: This PR does not introduce or remove any circular references. This report was generated automatically by comparing against the |
91aabf8 to
00274d8
Compare
8284704 to
f0da42a
Compare
There was a problem hiding this comment.
Pull request overview
Adds support for shipping vetted npm libraries into the QuickJS template-tag sandbox as grant-gated registry modules, plus a generator + tests/docs to keep the vendored bundles deterministic and pinned.
Changes:
- Introduces “heavy” sandbox modules (
uuid,ajv) and generates vendored factory bundles viagenerate:sandbox-vendored, registering them only when granted. - Adds per-surface profiles (template-tag vs scripting) to enforce capability ceilings while keeping module gating at the registry/
requirelayer. - Adds unit + smoke coverage and user-facing permissions documentation/migration warning behavior.
Reviewed changes
Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/insomnia/src/templating/sandbox/vendored/uuid.generated.ts | Adds generated, pinned uuid bundle factory source for sandbox registration. |
| packages/insomnia/src/templating/sandbox/vendored-libs.test.ts | Unit tests for vendored libs (runtime smoke in QuickJS + version drift guard). |
| packages/insomnia/src/templating/sandbox/surface-profiles.ts | Adds surface profiles and grant resolution helpers (capability ceiling enforcement). |
| packages/insomnia/src/templating/sandbox/surface-profiles.test.ts | Tests profile invariants and grant resolution rules. |
| packages/insomnia/src/templating/sandbox/plugin-tag-sandbox.ts | Builds module registry source per-run based on granted modules; enriches denial errors. |
| packages/insomnia/src/templating/sandbox/plugin-tag-sandbox.test.ts | Updates tests to use surface profiles and adjusts capability-shape assertions. |
| packages/insomnia/src/templating/sandbox/PERMISSIONS.md | Documents insomnia.permissions modules/capabilities and new vendored libs + migration notes. |
| packages/insomnia/src/templating/sandbox/module-registry.ts | Adds heavy vendored module definitions, version pins, and buildModuleRegistrySource. |
| packages/insomnia/src/templating/sandbox/in-sandbox-bootstrap.ts | Adds structured error metadata (code, moduleName) for module denials. |
| packages/insomnia/src/main/templating-worker-database.ts | Adds manifest-less migration toast logic and routes grants through surface profiles. |
| packages/insomnia/src/main/tests/templating-worker-database.test.ts | Tests migration warning deduping and non-warning cases. |
| packages/insomnia/scripts/generate-sandbox-vendored.ts | New esbuild-based generator for checked-in vendored factory sources. |
| packages/insomnia/package.json | Adds generate:sandbox-vendored script. |
| packages/insomnia-smoke-test/tests/smoke/sandbox-template-tags.test.ts | Adds E2E coverage for profile ceilings, migration warning, and vendored libs. |
| packages/insomnia-smoke-test/fixtures/sandbox-vendored-collection.yaml | New smoke-test fixture for vendored-lib tags. |
| packages/insomnia-smoke-test/fixtures/sandbox-profile-collection.yaml | New smoke-test fixture for profile/migration tests. |
| examples/insomnia-plugin-sandbox-demo/README.md | Updates demo docs for capability ceiling + migration warning behavior. |
| examples/insomnia-plugin-sandbox-demo/package.json | Adds uuid to demo plugin’s declared module permissions. |
| examples/insomnia-plugin-sandbox-demo/index.js | Adds a demo template tag that uses the vendored uuid module. |
Comments suppressed due to low confidence (1)
packages/insomnia/src/templating/sandbox/module-registry.ts:142
- This comment says surface profiles will intersect module grants with a ceiling, but the current template-tag module resolution intentionally does not enforce a resolve-time ceiling (the registry +
__requireare the gate). The comment should be updated to match the new behavior to avoid future confusion.
/**
* The floor of module access every template-tag plugin receives, even with no manifest. Surface
* profiles (P1) will intersect the resolved grant with a ceiling; for now the effective grant is
* simply `baseline ∪ manifest.modules` (see `resolveTemplateTagModules`).
*/
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
f0da42a to
5a2dd5a
Compare
a74c5a6 to
1ae3bde
Compare
kwburns-kong
left a comment
There was a problem hiding this comment.
No notes on the changes. Given the size/eval of the bundle thats paid per render, perhaps we use minify? #10264
ajv
size (from 251,504 to 117,163 bytes) 53% smaller
eval median (from 14.25ms to 10.46ms) 1.36x improvement
uuid
size (from 32,218 to 14,855 bytes) 54% smaller
eval median (from 1.84ms to 1.34ms) 1.37x improvement
Real npm libraries, bundled once and pinned, made available inside the QuickJS sandbox as require()-able registry modules (granted like any other module). - scripts/generate-sandbox-vendored.ts: esbuild-bundles each vetted lib (platform=browser, target=es2020) into a CJS factory-source string, written to src/templating/sandbox/vendored/<name>.generated.ts with its pinned version. npm run generate:sandbox-vendored -w insomnia. - module-registry: uuid + ajv entries (heavy: true). buildModuleRegistrySource now includes a heavy lib only when the plugin's grant names it, so a render that doesn't use it never parses its (25KB/247KB) bundle. - uuid picks its browser build (crypto.getRandomValues, provided by M2); ajv's logger uses the bootstrap console. Both verified running end-to-end in QuickJS. - lodash deferred (not a dep; add in a later batch when a plugin needs it). Tests: vendored-libs.test.ts (uuid v4 + validate round-trip, ajv compile/validate, grant-filtered registration, version-pin drift guard vs installed dep). E2E: a plugin declaring uuid/ajv runs the lib; ajv-in-registry-but-undeclared is denied (registry presence ≠ grant). Docs: PERMISSIONS.md + generator checklist; demo declares uuid + vendoredprobe tag.
* fix(templating): isolate sandbox-vendored ajv/uuid from the app's own dependencies The sandbox previously bundled ajv/uuid from the app's ambient node_modules, so a routine app dependency bump could silently drift the sandbox's vetted versions with no way to distinguish an intentional upgrade from tampering. Give the sandbox its own exact-pinned install, isolated from npm workspace hoisting, with a guardrail ensuring its pin never exceeds the app's resolved version, a one-command upgrade path with chain-of-custody verification, and CI checks that catch staleness or hand-edits to the generated bundles. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * chore(ci): harden ci * dep(uuid): bump uuid 9.0.1 to 11.1.1 --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
The snapshot ids asserted throughout vcs.test.ts are sha1 hashes of the
backend project id, which comes from generateId('prj') -> uuid.v4(). The
shared setup mock (setup-vitest.ts) that replaces uuid.v4 with a fixed
pool is declared *after* a top-level `await` that loads the cross-package
insomnia-data graph, so in CI that mock is applied non-deterministically:
when it misses, generateId returns a real random uuid, every asserted hash
changes, and the file fails — which is why the same commit passed on one
Test run and failed on another (the failing runs' backend project ids are
real uuids absent from the mock array; the passing runs' are from it).
Pin generateId deterministically at its in-package module boundary with a
test-file-local vi.mock of insomnia's own ~/common/misc (the reliable mock
pattern, unaffected by the setup mock's cross-package race), backed by a
private counter over the same id array (now exported). generateId('prj')
is the only uuid consumer these tests exercise, so drawing the array in
order reproduces the exact sequence the assertions were recorded against.
8d264fc to
c008fbd
Compare
* fix: large responses now download correctly * fix: linting * chore: add e2e testing to prevent future regressions * fix: cloud sync test flaky (#10238) * fix: cloud sync test flaky * fix * fix args to be more concrete * Feat/basic components m0 (#10230) * refactor: components infra * fix * fix: data-* class * rename cn to cls * chore: emit and upload junit test results per shard (#10253) * chore: emit junit reports per e2e tests shard * chore: include retries in junit reporter * chore: test some stuff * chore: test again * chore: revert test * fix(import): always show collection picker (#10262) * feat(undo): broaden undo-history persistence via a stable historyKey (#10233) * feat: add a tooltip for show/hide secret on auth tab (#10263) * feat(templating): vetted npm libraries in the sandbox — uuid + ajv (M3) (#10244) * fix: stop reusing blank-row ids in key-value editors [INS-2598] (#10260) * fix: ensure unique blank IDs for environment key-value pairs to prevent stale state * test: add validation for blank row behavior after deleting committed rows in environment table editor * fix: restore visible keyboard focus indicators across the app (#10268) * feat: enhance focus-visible styles for input elements * feat: simplify focus-visible styles for form elements * update test * fix: route v3 spaces SDK through proxy-aware fetch (#10265) * feat: show error when fails download --------- Co-authored-by: Curry Yang <163384738+CurryYangxx@users.noreply.github.com> Co-authored-by: Fares Osman <43153226+fiosman@users.noreply.github.com> Co-authored-by: Ryan Willis <ryan.willis@konghq.com> Co-authored-by: Jack Kavanagh <jackkav@gmail.com> Co-authored-by: Shelby <13246465+shelby-moore@users.noreply.github.com> Co-authored-by: Pavlos Koutoglou <pkoutoglou@gmail.com> Co-authored-by: Alison Sabuwala <alison.sabuwala1024@gmail.com>
* fix: large responses now download correctly * fix: linting * chore: add e2e testing to prevent future regressions * fix: cloud sync test flaky (#10238) * fix: cloud sync test flaky * fix * fix args to be more concrete * Feat/basic components m0 (#10230) * refactor: components infra * fix * fix: data-* class * rename cn to cls * chore: emit and upload junit test results per shard (#10253) * chore: emit junit reports per e2e tests shard * chore: include retries in junit reporter * chore: test some stuff * chore: test again * chore: revert test * fix(import): always show collection picker (#10262) * feat(undo): broaden undo-history persistence via a stable historyKey (#10233) * feat: add a tooltip for show/hide secret on auth tab (#10263) * feat(templating): vetted npm libraries in the sandbox — uuid + ajv (M3) (#10244) * fix: stop reusing blank-row ids in key-value editors [INS-2598] (#10260) * fix: ensure unique blank IDs for environment key-value pairs to prevent stale state * test: add validation for blank row behavior after deleting committed rows in environment table editor * fix: restore visible keyboard focus indicators across the app (#10268) * feat: enhance focus-visible styles for input elements * feat: simplify focus-visible styles for form elements * update test * fix: route v3 spaces SDK through proxy-aware fetch (#10265) * feat: show error when fails download --------- Co-authored-by: Curry Yang <163384738+CurryYangxx@users.noreply.github.com> Co-authored-by: Fares Osman <43153226+fiosman@users.noreply.github.com> Co-authored-by: Ryan Willis <ryan.willis@konghq.com> Co-authored-by: Jack Kavanagh <jackkav@gmail.com> Co-authored-by: Shelby <13246465+shelby-moore@users.noreply.github.com> Co-authored-by: Pavlos Koutoglou <pkoutoglou@gmail.com> Co-authored-by: Alison Sabuwala <alison.sabuwala1024@gmail.com>
PR 7 of the sandbox plan (https://gist.github.com/jackkav/4bbf717954a18a6753b64f33ab678ad4) — ticket M3, batch 1. Stacked on #10242 (PR 6); only the last commit is new.
What
Makes real, vetted npm libraries available inside the QuickJS sandbox as
require()-able registry modules — bundled once, pinned, and granted like any other module.scripts/generate-sandbox-vendored.ts(npm run generate:sandbox-vendored -w insomnia): esbuild-bundles each vetted lib (platform=browser,target=es2020) into a CJS factory-source string, written tosrc/templating/sandbox/vendored/<name>.generated.tswith its pinned version. Checked in (reviewable, deterministic).uuid+ajvshipped. Both verified running end-to-end in QuickJS: uuid generates/validates v4s (its browser build usescrypto.getRandomValues, provided by M2); ajv compiles a schema and validates payloads (its logger uses the bootstrapconsole).buildModuleRegistrySource(grantedModules)includes a heavy lib's bundle only when the plugin declared it, so a render that doesn't useajvnever parses its ~247KB.lodashdeferred — it isn't a dependency and adds bulk; add in a later batch when a plugin needs it.User-verifiable value
A community plugin with a real npm dependency (schema validation via
ajv, ids viauuid) works under the sandbox once it declares the module — the first PR where a non-trivial plugin can run fully sandboxed.Tests
vendored-libs.test.ts(6):uuid.v4()shape +validate/versionround-trip,ajvcompile + validate two payloads (compiled-validator state), heavy-lib-registered-only-when-granted, and a version-pin drift guard (the recorded version must equal the installed dependency — a dep bump without regenerating fails it).uuidrendersuuid=ok; one declaringajvrendersvalid,invalid; a plugin that requiresajvwithout declaring it is denied "Module 'ajv' not permitted by manifest" (registry presence ≠ grant).npm run lint && npm run type-check && npm test— clean.Notes for review
vendored/ajv.generated.tsis a ~247KB checked-in bundle (few lines, one big string) — a deliberate vendored artifact, regenerable via the script, parsed at runtime only when a plugin grantsajv.