* fix(ui): re-render url bar templates on project environment switch
The request URL bar's remount key only tracked the workspace
environment (activeEnvironment), so switching the project
environment (activeGlobalEnvironment) left stale nunjucks tag
values in the URL bar. The URL preview was unaffected since it
re-renders on any loader revalidation and refetches the render
context fresh from the DB.
* fix(ui): re-render mcp url bar templates on project environment switch
Same issue as the request URL bar: the remount key only tracked
the workspace environment, so switching the project environment
left stale nunjucks tag values.
* fix(release): resolve previous tag by semver precedence, not publish order
GitHub's auto-detected previous tag for release notes ignores per-line
release branches, so out-of-order alpha/beta/hotfix tags can pull PRs
from an unrelated release into the notes. Compute the previous core@ tag
via real semver precedence instead, excluding a stable release's own
prereleases so it diffs against the prior stable release.
* fix(release): let ncipollo/release-action generate notes directly
Pass generateReleaseNotesPreviousTag to the release action instead of
calling GitHub's generate-notes API manually via curl - the action
already wraps the same endpoint with identical previous_tag_name
semantics, so this drops the redundant step.
* wip: sendRequest bridge fixes for QuickJS sandbox — known unresolved crash
Not working yet. insomnia.sendRequest() consistently crashes under the
real Electron/Worker/QuickJS environment with:
Aborted(Assertion failed: list_empty(&rt->gc_obj_list), at:
../../vendor/quickjs/quickjs.c,2036,JS_FreeRuntime)
on the FIRST real network round trip (via the
insomnia-templating-worker-database:// fetch bridge to
network.sendRequestWithoutSideEffects). This never reproduces in vitest
(mocked fetch, or a real Node http server) — only under real Electron
fetch() timing inside the dedicated Worker.
This commit includes three targeted fixes attempted so far, none of
which resolved it on their own or together:
1. insomnia.sendRequest('url string') omitted `headers` entirely; the
host handler doesn't default it, crashing
createConfiguredCurlInstance's `headers.find(...)` user-agent lookup.
This one IS a real, confirmed bug (unit-tested regression added) —
just not sufficient by itself to fix the crash above.
2. Deferred sendRequestViaFetch by one Promise.resolve().then() tick so
it doesn't run nested inside the QuickJS C-to-JS callback frame
(matching host-bridge.ts's installHostBridge pattern for the
template-tag sandbox).
3. executePendingJobs() returns a DisposableResult that must itself be
disposed — discarding it leaked a handle. Fixed in both
installSendRequestBridge and driveTaskToCompletion.
4. Added a disposedRef guard so a late-arriving fetch response after
vm.dispose() is a safe no-op instead of touching a dead context.
Also includes the smoke test (quickjs-script-sandbox.test.ts) that
reproduces the crash reliably — the second test in that file (worker
UI-responsiveness) passes; the sendRequest round-trip test does not.
Branched off PR 2 (37d19c1da8) per the rollout plan —
https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354 — so
this can be picked up independently without blocking PR 0/PR 1 landing.
Next step for whoever picks this up: bisect further with instrumented
console.error tracing of vm.alive at each step (deferred here, not
committed) to find exactly which call touches vm after disposal — my
three fixes were reasonable hypotheses but didn't close it.
* test: add __sendRequest to the globalThis allowlist after rebase
The merged globalThis-leak test's ALLOWED_EXTRA_GLOBALS predates this
branch's sendRequest bridge landing back on top of develop's rebase target;
without this the merged test fails since __sendRequest is now a real
bridged global.
* fix(quickjs): free bridge promise resolvers before disposing the VM
`vm.newPromise()` allocates three JSValues — the promise plus its `resolve`
and `reject` functions — and quickjs-emscripten frees the two functions only
from inside `resolve()`/`reject()`. `installSendRequestBridge` returned the
promise handle but could skip both (the `disposedRef` guard did exactly that),
so a `sendRequest()` still in flight at teardown left two live function objects
in the runtime and `JS_FreeRuntime` aborted on
`assert(list_empty(&rt->gc_obj_list))` — a native Emscripten abort that takes
down the Worker and the WASM module shared with the template-tag sandbox.
Track every unsettled deferred and dispose it before `vm.dispose()`, which is
the cleanup the library documents for this case. Guard the late-response path
on `vm.alive`/`deferred.alive` instead of a hand-rolled flag.
Also plumb the templating-db auth token from `run-script-quickjs.ts` through
the worker into the engine — it was accepted but never passed, so every bridge
fetch was rejected 401 by the protocol's auth gate.
The crash reproduces in vitest after all: the mocked fetch in the existing
tests settles in the same microtask checkpoint as the call, so the deferred was
always settled before teardown. Settling it on a later macrotask reproduces the
exact production abort, so the smoke test no longer needs `test.fail()`.
* fix(quickjs): return the response value from sendRequestWithoutSideEffects
The handler returned `new Response(JSON.stringify(result))` while every other
handler in `pluginToMainAPI` returns a plain value and lets the caller wrap it.
`resolveDbByKey` does `JSON.stringify(await handler(body))`, so a `Response`
stringified to `"{}"` — the sendRequest bridge received an empty object, and
`response.code` / `response.body` were undefined. The template-tag sandbox's
`network.sendRequestWithoutSideEffects` path was broken the same way.
Also record a second, unrelated `gc_obj_list` abort that the teardown fix does
not address and that predates this branch: allocation-heavy work performed
inside `executePendingJobs()` (anything after the script's first `await`) leaves
live GC objects and aborts at `JS_FreeRuntime`, from ~100k objects up. Reduced
to a reproducer with no bridge, no host functions, no interrupt handler, no
memory limit and no `resolvePromise`; unaffected by every host-side mitigation
tried, and present on both quickjs-emscripten sync variants. Tracked as a
`.fails()` test so it flips red when an engine bump fixes it.
The sendRequest bridge is what makes that latent engine bug routine — it is the
first thing to put multi-megabyte host data into the VM.
Corrects the "later run proves the module survived" comment: a fresh context on
the same WASM module succeeds even after an abort, so that assertion never
detected anything.
* fix(quickjs): address Copilot review feedback on sendRequest bridge
- Normalize request.header (singular, per RequestOptions) as well as
request.headers, and accept {key, value} header entries alongside
{name, value}.
- Coerce request.url to a string, since RequestOptions allows a
Url-like object there and the host handler needs a plain string.
- sendRequestViaFetch no longer unconditionally JSON.parses the
response body — a non-JSON body (empty response, HTML error page,
etc.) now surfaces a clear "non-JSON response"/status-based error
instead of an opaque SyntaxError masking the real failure.
- The callback-style rejection handler no longer assumes err is an
Error instance (guards on err && err.message).
The authToken concern from the same review round was already fixed by
5ad0278188 on this branch (plumbed from run-script-quickjs.ts through
the worker into the engine) before this commit.
Added unit test coverage for all four fixes.
* fix(quickjs): survive the WASM teardown abort instead of losing the run
Allocating ~100k+ objects after a script's first `await` — which a multi-MB
`insomnia.sendRequest()` response body does on its own — leaves QuickJS's
runtime un-freeable, and `JS_FreeRuntime` aborts the WASM module. The script
has already finished by then and everything we return is plain host-side JS, so
the abort was destroying a run whose result was intact.
Catch it at teardown, warn into the script's logs, and report it through a new
`onEngineFault` callback. Catching inside `finally` means a genuine script error
or timeout still wins. The worker forwards the fault as `engineFaulted` and the
client retires that worker, so no later script runs on a module that aborted.
Retirement is drain-aware: `self.onmessage` doesn't serialize, so a second
script can be mid-execution. The worker leaves rotation immediately but is only
terminated once its in-flight runs settle, and the crash handler now rejects
only its own worker's runs rather than every pending call.
Verified before implementing: the abort is catchable, host-collected data
survives it intact, and the module is still *correct* afterwards — arithmetic,
JSON, string and global operations all check out across repeated runs. Retiring
the worker anyway is defensive, since that only samples the behaviour we
happened to test.
This is containment, not a fix. The underlying defect is in quickjs-emscripten's
WASM build, not in QuickJS: the identical vendored engine source built natively
is clean well past the failing size at every optimization level, with and
without -fwrapv, with CONFIG_STACK_CHECK, and with the same raw-context
intrinsic subset the shim uses — while both WASM engines abort at both
optimization levels. Tracked upstream as
https://github.com/justjake/quickjs-emscripten/issues/269.
* fix(quickjs): close three sendRequest bridge findings (#10404)
* fix(quickjs): reject caller-controlled caCertficatePath/authentication in sendRequestWithoutSideEffects
* fix(quickjs): bound the script sandbox's runtime stack size
Unbounded guest recursion overflowed the host WASM stack before QuickJS's own
depth check could fire, masking the real error behind a fatal gc_obj_list
assertion at vm.dispose(). setMaxStackSize(256KB) lets QuickJS's own check win.
* fix(quickjs): deny multipart/file-upload bodies in the sendRequest bridge
network.sendRequestWithoutSideEffects's cacert/authentication fields are already
pinned regardless of caller input, but its `body` was forwarded unvalidated. A
multipart/form-data body's file parts (body.params[].fileName) reach
buildMultipart, which reads each part's fileName off disk with no ownership/
allowlist check -- unlike every other local-file read reachable from a request
definition. A script reaches this by calling the raw __sendRequest bridge global
directly, bypassing insomnia.sendRequest()'s wrapper, which only ever builds a
text/plain body.
Scoped the fix to the QuickJS bridge itself (assertSupportedSendRequestBody,
run before the bridge's fetch() is dispatched) rather than the shared handler,
since that handler is also used by the legacy hidden-window script sandbox and
the template-tag sandbox, each with its own already-privileged execution model
that should keep working as-is.
Two regression tests: one drives the real QuickJS bridge end-to-end and confirms
the request is now denied before it ever reaches curlRequest; the other drives
the legacy (non-QuickJS) sendRequestWithoutSideEffects implementation directly
and confirms it's unaffected -- the same multipart body still goes through.
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
* fix(ci): skip circular refs PR comment when count is unchanged
Avoids noisy comment creation/updates on the circular references check
when the PR introduces no change vs the base branch.
* fix(ci): delete stale circular refs comment when count returns to no-change
Prevents a stale "warning" comment lingering on a PR after circular
references introduced earlier are fixed and the count matches base again.
* poc: opt-in QuickJS sandbox for pre-request/after-response scripts
Adds settings.useQuickJsScriptSandbox (default off) and wires it into the
existing hidden-BrowserWindow dispatch point in concurrency.renderer.ts, so
scripts can optionally run in the QuickJS-WASM sandbox already used for
plugin template tags instead of the hidden window.
This PoC supports console, insomnia.environment/variables get/set, and
read-only insomnia.request; insomnia.sendRequest() and insomnia.test()/
pm.test() are not yet bridged and throw a clear error.
Full rollout plan (worker-boundary move, async host bridge, test-lifecycle
and request-mutation parity, security verification, telemetry/soak, and
eventually flipping the default to opt-out) is written up here:
https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* fix: address Copilot review feedback on QuickJS script sandbox PoC
- Timeout error now reports the configured duration instead of an epoch
deadline timestamp.
- insomnia.request is deep-frozen so mutation attempts are silently
no-ops consistently, rather than appearing to succeed inside the
script while never reaching the host.
- Fix operator-precedence bug in a test script (?? binds looser than +).
- Add an aria-label to the new sandbox toggle Switch for screen readers.
* poc: move QuickJS script execution to a dedicated Web Worker (PR 1)
Splits run-script-quickjs.ts into:
- quickjs-script-engine.ts: the pure QuickJS execution logic (unchanged
behavior), runnable from anywhere.
- quickjs-script.worker.ts: a Web Worker entry point that runs the engine
off the renderer's main thread.
- run-script-quickjs.ts: now a thin client that lazily creates the worker
(only when useQuickJsScriptSandbox is actually used) and correlates
postMessage/response pairs by id, matching the existing
templating-handler.ts/templating.worker.ts pattern used for template
tags.
A runaway script (e.g. an infinite loop) now blocks only the disposable
worker instead of the renderer's UI thread. A worker-level crash rejects
every in-flight call and the next call gets a fresh worker.
concurrency.renderer.ts is unchanged apart from continuing to import
runScriptInQuickJs by the same name/path.
Ref: PR 1 of the rollout plan — https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* style: formatting pass on quickjs worker-client test
* poc: async host bridge + insomnia.sendRequest() parity for QuickJS sandbox (PR 2)
Bridges insomnia.sendRequest() to a real HTTP request instead of throwing,
reusing the existing insomnia-templating-worker-database:// fetch protocol
and its network.sendRequestWithoutSideEffects handler (the same one the
template-tag sandbox already uses) rather than adding a second protocol
scheme. This is the same fetch-to-custom-protocol pattern
templating.worker.ts uses to reach the main process from a dedicated Web
Worker, generalized to a second async host bridge inside
quickjs-script-engine.ts (a VM promise resolved off a real fetch(),
settled via executePendingJobs() — no asyncify).
- quickjs-script-engine.ts: installSendRequestBridge() + BOOTSTRAP's
insomnia.sendRequest() now normalizes a URL string or a plain
{url, method, headers, body} object, calls the bridge, and rebuilds a
response object ({code, status, headers, body, responseTime, json(),
text()}) — supports both the Postman-style (error, response) callback
and awaiting the returned promise. insomnia.test()/pm.test() still
throws (unchanged).
- run-script-quickjs.ts (client): fetches the templating-db auth token
once via window.main.templatingDb.getAuthToken() (same pattern as
ui/worker/templating-handler.ts) and forwards it on every postMessage.
- quickjs-script.worker.ts: passes the auth token through to the engine.
Known gaps (documented in quickjs-script-engine.ts, deferred to a later
parity PR): no auth/client-certs/cookies/multipart-or-urlencoded bodies,
and the response object doesn't yet match the hidden-window Response
class's full surface (chai assertions, originalRequest, cookies).
Ref: PR 2 of the rollout plan — https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* Revert "poc: async host bridge + insomnia.sendRequest() parity for QuickJS sandbox (PR 2)"
This reverts commit 37d19c1da8.
* test: add e2e smoke test for QuickJS sandbox (PR 0 + PR 1 only)
Proves the opt-in QuickJS engine and Web Worker boundary work end to
end in the real Electron app, not just in vitest's mocked unit tests:
- console.log, insomnia.environment.get/set, and read-only
insomnia.request all work through the real Worker/QuickJS pipeline
(canary: `typeof require` confirms the script actually ran in
QuickJS, not the legacy hidden-window engine).
- A runaway (`while(true){}`) script blocks only its dedicated Worker —
the app UI stays responsive and interactive while it churns.
insomnia.sendRequest() (PR 2) is intentionally not exercised — it's
been split into its own WIP branch/PR (#10392) pending a real fix for
a QuickJSUseAfterFree crash that only reproduces under real Electron
timing.
Uses "testQueryParams", a request at the workspace root with no body
and no folder-inherited scripts. Every other candidate in this fixture
either references environment variables undefined until a script runs
(triggering Insomnia's "N environment variables are missing"
confirmation dialog) or inherits a folder-level after-response script
calling an API this minimal engine doesn't bridge, which turns an
otherwise-successful send into a displayed "Error" status. Asserting
via the Console tab (console.log output) instead of an echoed response
body sidesteps template rendering entirely.
Ref: PR 0/1 of the rollout plan — https://gist.github.com/jackkav/3ebf8768bf84be024a3a138874919354
* fix(scripting): guard __proto__/constructor/prototype keys in QuickJS env/var bridge (#10395)
A script-supplied "__proto__"/"constructor"/"prototype" key reaching the bridge's store object could rewire its prototype or shadow those names; the bridge now rejects these keys before assignment.
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
* feat: Enhance tab deletion behavior with fallback navigation and update context options
* feat: Implement fallback URL for request deletion in tab list
* feat: Add tests for request deletion fallback behavior in tab context
* feat: Exclude colocated unit tests from route discovery to prevent build issues
* fix: Import React alongside FC and PropsWithChildren types for consistency
* feat: Optimize tab deletion handling by using a ref for tabList to prevent unnecessary re-renders
* refactor: Simplify clientAction by removing unused parameters and redirect logic
* fix: Prevent project modal from blocking clicks by adding a close check during folder opening
* fix(deps): bump fast-uri to patch host-confusion SSRF vulnerabilities
fast-uri <3.1.5 is vulnerable to host confusion via backslash authority
delimiters and failed IDN canonicalization (GHSA advisories), which can
enable SSRF. ajv and @rjsf/utils already permit fast-uri ^3.x, so this
only required refreshing the lockfile resolution, no parent bump needed.
* fix(deps): bump undici to patch cookie/cache/desync vulnerabilities
undici <7.29.0 is affected by several advisories: Set-Cookie SameSite
downgrade via permissive substring matching, cross-user cache leakage
via whitespace bypass, downstream response desync via retry
interceptor, CRLF injection via blob-like body 'type', and cookie
attribute injection via unsanitized domain fields. The direct
dependency's existing ^7.25.0 range already permitted the fix, so this
only required refreshing the lockfile resolution.
Note: @connectrpc/connect-node@1.7.0 still bundles its own pinned
undici@^5.28.4 (resolves to 5.29.0), which remains vulnerable to the
older <6.24.0 advisories. Fixing that requires a major bump of
connect-node to 2.x, which needs its own review for breaking API
changes - tracked as a follow-up.
* fix(deps): bump builder-util-runtime to patch credential-leak vulnerability
builder-util-runtime <9.7.0 leaks PRIVATE-TOKEN and mixed-case
Authorization credentials on cross-origin redirects during
electron-updater's auto-update flow. electron-builder and
electron-builder-squirrel-windows pinned it exactly at 9.5.1, so
those parents needed bumping (26.8.1 -> 26.15.7) to pull the fix.
electron-updater's existing ^6.6.2 range already permitted 6.8.9,
which resolves the same fixed builder-util-runtime.
* fix(deps): bump liquidjs to patch memoryLimit bypass
liquidjs <=10.27.0's pop filter bypasses the memoryLimit accounting
enforced by its array-filter siblings, allowing a DoS via unbounded
memory growth in template rendering. Both consumers already declare
^10.27.0, which permits the fix, so this only required a lockfile
refresh (resolved to 10.28.0).
* fix(deps): bump ip-address to patch octal/decimal parsing SSRF
ip-address <=10.3.0 decodes Address4 leading-zero octets as decimal
while WHATWG URL host parsing, inet_aton, and getaddrinfo decode them
as octal, letting an attacker bypass IP-based trust boundaries and
achieve SSRF. express-rate-limit@8.3.2 pinned ip-address at an exact
10.1.0, so it needed bumping to 8.6.2 (still within @modelcontextprotocol/sdk's
^8.2.1 range) which declares ip-address ^10.2.0 and resolves to 10.4.0.
* fix(deps): bump tar to patch PAX parsing and recursion DoS issues
tar <=7.5.20 has multiple issues: process crash via PAX numeric path
type confusion, decompression/parse DoS via unlimited input, infinite
loop on negative entry size during archive replace, uncaught exception
via NUL bytes in PAX path/linkpath records, and uncontrolled recursion
in mapHas/filesFilter enabling stack-overflow DoS via crafted long-path
entries. node-gyp and @mapbox/node-pre-gyp already declare tar ^7.5.4 /
^7.4.0, which permit the fix, so this only required a lockfile refresh
(resolved to 7.5.22).
* fix(deps): bump ws to patch tiny-fragment memory exhaustion DoS
ws 8.0.0-8.20.1 bounds retained WebSocket message fragments via
maxFragments/maxBufferedChunks, but the defaults were set too high,
letting an attacker exhaust memory with many tiny fragments/chunks.
The direct ws dependency's ^8.18.1 range already permitted the fix;
socket.io/socket.io-client's bundled engine.io, engine.io-client, and
socket.io-adapter pinned ws with a `~8.20.1` tilde range that excluded
it, so those three needed bumping to pull in `~8.21.0` (still within
socket.io@4.8.3's own ~6.6.0/~6.6.1 ranges). All ws instances now
resolve to 8.21.2.
* fix(deps): bump hono to patch 33 advisories (cookie/CORS/routing/XSS)
hono <=4.12.33 accumulates a long list of fixes: cookie name validation
bypass on write/read paths, path traversal in toSSG() and serve-static
(including Windows backslash encoding), IP restriction bypass for
IPv4-mapped/non-canonical IPv6, JWT NumericDate/Bearer-scheme
validation gaps, cache middleware Vary header leakage, CORS wildcard
credential reflection, JSX SSR XSS via cx(), and a ReDoS in CORS's
Access-Control-Request-Headers handling, among others.
@modelcontextprotocol/sdk's existing ^1.17.5 range already permits
the fix; bumping it to 1.30.0 resolves hono to 4.13.0.
* fix(deps): bump valibot to patch flatten() TypeError on inherited keys
valibot <=1.4.1's flatten() helper throws a TypeError when validation
issues contain attacker-controlled object keys such as toString,
valueOf, or hasOwnProperty. @react-router/dev's existing ^1.2.0 range
already permits the fix, so this only required a lockfile refresh.
* fix(deps): bump dompurify to 3.4.13 (direct dep, lockfile refresh)
Direct dependency's existing ^3.4.10 range already permitted the fix;
this only required a lockfile refresh.
* fix(deps): bump morgan to 1.11.0 (transitive via @react-router/serve)
@react-router/serve@7.15.0's existing ^1.10.1 range already permitted
the fix, so this only required a lockfile refresh. Brings on-finished
along from ~2.3.0 to ~2.4.1 as a nested dependency bump.
* fix(deps): bump uuid from v9 to v11 to patch buffer bounds check
uuid <11.1.1 is missing a buffer bounds check in v3/v5/v6 when a buf
is provided, which can lead to memory corruption. insomnia-data,
insomnia-scripting-environment, and insomnia-smoke-test were still on
^9.0.1 (packages/insomnia already used ^11.1.1). This is a major
version bump, but the only APIs in use across these packages are v4()
and validate(), whose signatures are unchanged between v9 and v11, so
no code changes were needed. All three now resolve to uuid@11.1.1.
* fix(deps): bump csv-parse from v6 to v7
csv-parse 6.x is flagged for update to 7.0.2. This is a major version
bump (ESM/CJS dual-package modernization), but the sync `parse()` API
that packages/insomnia-scripting-environment and the sandbox's
require-interceptor (exposing it to user scripts as
'csv-parse/lib/sync') both rely on is unchanged - verified with an
identical before/after parse() smoke test. No code changes needed.
* fix(deps): bump react-router family to 7.18.2 to patch CSRF/XSS/DoS advisories
react-router 6.0.0-7.18.0 accumulates several advisories: CSRF via
PUT/PATCH/DELETE document requests, open redirect via backslash in
<Link>/useNavigate, RSCErrorHandler missing protocol validation (XSS),
arbitrary constructor injection via deserializeErrors() in SSR
hydration, and unauthenticated DoS via inefficient route matching.
react-router, @react-router/dev, @react-router/fs-routes,
@react-router/node, and @react-router/serve were all exact-pinned at
7.15.0 and needed bumping together (they're a version-locked family)
to 7.18.2 - a non-major fix version per npm audit.
One additional react-router advisory (RSC Mode CSRF Bypass, fixed only
in 8.3.0+) doesn't apply here: this app doesn't use React Server
Components (no react-server-dom-webpack/@vitejs/plugin-rsc usage in
the codebase), so the RSC-specific code path is never exercised.
As a side effect, @react-router/serve's bundled express moved from
4.22.1 to 4.22.2, which also fixes a body-parser DoS advisory
(silently-disabled size limit on invalid `limit` values) for that one
instance. Two other body-parser instances (smoke-test's own express,
and the MCP SDK's bundled express) remain on vulnerable body-parser
versions - tracked as a follow-up.
* fix(deps): bump socket.io-parser to patch zero-attachment memory exhaustion
socket.io-parser 4.0.0-4.2.6 lets a specially crafted packet make the
server wait for a large number of binary attachments and buffer them,
exhausting memory. socket.io@4.8.3's existing ~4.2.4 range already
permitted the fix, so this only required a lockfile refresh.
* fix(deps): bump body-parser (via smoke-test's express) to patch limit-bypass DoS
body-parser <1.20.6 silently disables its size-limit enforcement when
given an invalid `limit` value, allowing a DoS via unbounded request
bodies. insomnia-smoke-test's express (^4.21.2) already permitted the
fix; bumping it to 4.22.2 resolves body-parser to 1.20.6.
Note: @modelcontextprotocol/sdk still bundles express@5.2.1 with a
vulnerable body-parser@2.2.2 (needs >=2.3.0). Left unfixed for now -
Insomnia only uses the SDK's client-side StreamableHTTPClientTransport
(packages/insomnia/src/main/mcp/transport-streamable-http.ts), never
the SDK's server/express code path, so this instance is unreachable
in practice. A prior attempt to patch it via manual lockfile surgery
left package-lock.json in an inconsistent state (a resolved package
missing its "packages" entry, so `npm ci` wouldn't reproduce it) and
was reverted. Tracked as a follow-up to fix through a supported
mechanism (e.g. once @modelcontextprotocol/sdk relaxes its body-parser
range, or via a clean full lockfile regeneration reviewed on its own).
* fix(deps): bump form-data to patch CRLF injection (2 of 3 instances)
form-data <2.5.6 and >=4.0.0 <4.0.6 are vulnerable to CRLF injection
via unescaped multipart field names/filenames. @types/request's
^2.5.5 and jsdom's ^4.0.0 ranges already permitted the fix, resolving
to 2.5.6 and 4.0.6 respectively via lockfile refresh.
Note: httpsnippet@3.0.10 (the latest available release) exactly pins
form-data at 4.0.4, which stays vulnerable. There's no newer
httpsnippet version to bump to yet - this is upstream-blocked, not
fixable without an override. Tracked as a follow-up to revisit once
httpsnippet ships a fix.
* fix(deps): bump @customerio/cdp-analytics-browser to patch nested js-cookie + uuid
Bumps the pinned ^0.3.9 to ^0.5.9. This single bump fixes two
findings that were previously nested inside this analytics SDK and
not independently reachable:
- js-cookie: was exactly pinned at 3.0.1 (<=3.0.5 is vulnerable to a
per-instance prototype hijack in assign() enabling cookie-attribute
injection); now ^3.0.7, resolving to 3.0.8.
- uuid: customerio-gist-web bundled uuid@^8.3.2 (missing buffer bounds
check in v3/v5/v6, <11.1.1); now declares ^14.0.0, resolving to
14.0.1. This was the residual instance noted as a follow-up in the
earlier uuid v9->v11 commit.
The AnalyticsBrowser API surface used in use-cio.tsx (load/track/
identify/page/reset) is unchanged between 0.3.19 and 0.5.9.
* fix(deps): bump body-parser to 2.3.0 for the MCP SDK's bundled express
Fixes the remaining body-parser instance (via @modelcontextprotocol/sdk's
express@5.2.1, which declares ^2.2.1 - already permitted the fix).
This is the instance noted as unreachable/deferred in the prior
body-parser commit; the dependency graph has since shifted (from the
react-router and customerio bumps) enough that a plain `npm update
body-parser` now resolves it cleanly via a proper lockfile entry,
unlike the earlier attempt that left a broken lockfile via manual
surgery. All three body-parser instances are now fixed.
* refactor(templating): retire templateTagSandboxEnabled, unify on pluginSandboxEnabled
The experimental `templateTagSandboxEnabled` toggle only ever gated
template-tag execution and had been superseded by `pluginSandboxEnabled`,
which sandboxes every untrusted plugin surface. Retire the legacy flag:
- drop it from the Settings type + defaults
- simplify `isSandboxEnabled` to read only `pluginSandboxEnabled`
- bundle plugins are trusted, so their tags always run in-process (the
legacy all-modules/all-caps bundle sandbox branch is removed)
- remove the "Run template tags in sandbox" Preferences toggle
- carry a user's prior opt-in forward via a settings migration
(templateTagSandboxEnabled === true -> pluginSandboxEnabled = true),
then delete the stale field
Smoke helpers repointed to the surviving `toggle-plugin-sandbox`; the now
-duplicate `enablePluginSandbox` helper is folded into `enableSandbox`.
* refactor(plugins): rename 'trusted' execution mode to 'internal'
'trusted' is an internal-only PluginExecutionMode label for built-in
bundled plugins the user can't install or change; it's never surfaced in
the UI (the Plugins badge shows 'In-process'). Rename it to the more
neutral, descriptive 'internal' to match the docs. Distinct from the
plugin *registry* trust concept (resolveTrustedPlugin, the 'trusted-plugin'
guard), which is unchanged.
* sandbox: reject bundle-plugin name impersonation, remove stale doc (#10376)
* docs(settings): simplify 'Sandbox all plugin code' toggle description
Address review nit: drop implementation jargon (QuickJS-WASM, default-deny)
from the Preferences copy in favour of plain language, keeping the coverage
list and the full-host-access escape-hatch pointer.
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
* feat(settings): add proxyIntegrations option for first-party integrations
* fix(proxy): improve handling of integration host URLs in insomniaIntegrationHosts function
* feat(proxy): enhance proxy integration handling for various services and update settings help text
* feat(proxy): introduce ProxyScope to manage proxy usage for requests and all traffic
* refactor(proxy): rename ProxyScope to ProxyScopes and update references throughout the codebase
* feat(push): add retry mechanism for failed pushes after successful commits
* feat(git): enhance branch management with warnings and create branch option on push failure
* feat(git): optimize branch creation and enhance error handling for push failures
* feat(git): enhance push error handling with authentication checks and banner support
Toggling markdown write<->preview or the pre/after-response script tabs unmounts
and remounts a CodeEditor while it is hidden. Undo (and, for markdown, the
content) was clobbered:
- persistState bailed out early when the hidden editor reported a zero-size
viewport, so it never saved the undo history. Now it always persists history
(and cursor/selections/marks); only the layout-dependent scroll position is
skipped when invalid.
- The editor-state cache now also persists the editor VALUE plus the defaultValue
baseline it was cached against (valueSeed). On remount the cached value + history
are reused ONLY when the current defaultValue is consistent with what was cached
— it equals the cached value (the model caught up / saved that content, e.g. the
markdown editor's debounced onChange landed) or the seed (unsaved edits on an
unchanged model). If it matches neither, the model changed externally between two
mounts sharing a historyKey (a script/sync updated the environment/response, or a
.spectral.yaml edit changed a ruleset), so the fresh defaultValue wins and the
stale value/history are dropped. Read-only editors never cache a value; they are
always authoritative from defaultValue.
- The request-pane description and pre/after-response script editors used a
volatile React key that remounted them on every revalidation, resetting state
and clobbering undo. They now use stable per-request keys (content does not
depend on env/response).
Also corrects the markdown editor's TabList aria-label (was 'Request scripts tabs').
Covered by an e2e smoke test: both markdown write/preview and pre/after-response
script toggles keep undo working after switching back.
* Hide empty iterations/requests in runner results if there are no tests matching the filter
* Add an empty state in case there are no tests/requests matching the selected filter
* Add tests to cover changes in runner filter behavior
* fix: minor improvements
* chore: rewording
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: George He <hexxa@outlook.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* feat: add sidebar focus setting for collections in General settings
* feat: add depthOffset prop to EmptyNode and RequestNode for sidebar focus adjustment
* feat: add sidebar collection-focus-mode swipe transitions animations
* feat: clear focus state when exiting collection focus mode
* feat: implement backToAllProjects method and update tests for sidebar navigation
* feat: enhance workspace active state check with polling mechanism
* feat: update cloud sync test to include navigation back to all projects before branch actions
* feat: add sidebar focus mode onboarding with dismissal persistence
* feat: update onboarding text for sidebar focus mode to clarify navigation
* fix: correct typo in onboarding text for sidebar focus mode
* feat: implement seedSettings function to pre-seed settings for tests and update sidebar focus mode onboarding tests
* feat: record enterprise-plan actions for request/document creation
* chore: address copilot feedback
* feat: adds enterprise plan type guard
* chore: formatting
* refactor: clean up
* chore: use proper types
* refactor: clean up
* chore: clean up
* 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(templating): resolve the QuickJS sandbox engine module before any plugin's code runs
traversePluginPath's elevated/unsandboxed branch nodeRequires a plugin's entry module
synchronously, and folder order is fully attacker-controlled (a plugin author names their own
folder). quickjs-emscripten is required lazily and only once per process, the first time a
sandboxed plugin's discovery/tag/hook/action path reaches it, and the resolved module is memoized
forever. A plugin loaded before that first real require gets a window to patch
Module.prototype.require and substitute a forged quickjs-emscripten module for every other,
sandboxed plugin's sandbox for the rest of the session.
getPlugins() now eagerly resolves the real quickjs-emscripten module, in the real main process
only, before traversePluginPath ever runs — so no plugin's code gets a chance to patch the loader
before the host's own capture happens.
Add regression tests: a real Playwright smoke test and unit test driving the fix's ordering and
memoization guarantees directly, plus broader regression coverage for how far one plugin's code
can reach into another plugin's state or the shared process (the plugin registry, the request/
response hook chain, shared JS globals, the module loader, and the settings cache) — each pinning
what's actually reachable today so a future change is caught here instead of going unnoticed.
* test(plugins): make the require.cache reachability regression prove the real claim
The empty registryCandidates result also occurs under Vitest's own module loader regardless of
production esbuild bundling, so it couldn't by itself distinguish "bundled" from "not required
the way Vitest happens to load it". Adds a self-contained static check against the esbuild config,
and reports the bundle-existence check as skipped (not a silent pass) when no local build artifact
is present.
* fix(templating): reload plugins in the persistent render worker
The persistent templating worker caches its Liquid engine and plugin tags
once per session; Settings > Plugins Reload never invalidated it, nor the
separate plugin registry cache in templating-worker-database.ts. A plugin
missing on the first render stayed broken all session. Adds a reload
message to invalidate the worker's cache and a plugin.reloadPlugins
endpoint for the registry, plus regression tests.
* fix(templating): fetch a fresh auth token for the reload message
The reload message needs an auth token normally only set by a render job's
payload, so clicking Reload before sending any request silently failed.
Fetch a token specifically for the reload message instead.
* fix(plugins): surface load-error and name-collision plugins instead of dropping them
Kong/insomnia#10295: a plugin whose require() throws, or whose name
collides with another folder, used to vanish silently. Both now show as a
disabled row with a visible reason, and Settings > Plugins gains an
expandable details panel (display name, description, effective permission
set, warnings).
* fix(plugins): resolve symlinks before trusting a plugin folder's location
traversePluginPath's containment check was purely lexical, so a plugin
folder that was itself a symlink to somewhere outside the configured
plugin path passed it and got require()'d from its real target with the
sandbox off. Re-check against the realpath-resolved base.
* fix(templating): reconcile #10317 with merged S1 inventory + order-independent collision policy
Post-merge fixes so #10317 is consistent with what landed on develop (S1 #10320, #10326):
- Add a templating-worker-database-inventory.ts row for the new plugin.reloadPlugins handler this PR
introduces (S1's G1 no-drift gate requires every pluginToMainAPI handler to have a row). Classified
sandbox-orchestration / host-only / registry-lookup (no caller input; triggers a trusted rescan).
- Update plugin-vanish-name-collision smoke test to the order-independent collision policy this
branch now uses after the merge: a name claimed by two folders loads NEITHER active (both disabled
with a collision marker), instead of first-folder-wins. Keeps a colliding folder from inheriting
another's name-keyed `elevated` grant via load order (#10326), while still surfacing both (P0-B).
* fix(plugins): close prefix-match symlink bypass + fix per-row detail expansion
- traversePluginPath's realpath re-check used startsWith() instead of the
isContainedIn() helper, reintroducing the exact prefix-match bypass that
helper was written to prevent (e.g. a plugin folder symlinked to
/plugins-evil would pass a startsWith('/plugins') check). Reuse
isContainedIn on the realpath-resolved paths instead.
- Settings > Plugins keyed the details-expansion Set by plugin.name, but
colliding folders intentionally share a name, so expanding one row
expanded every row with that name. Key by plugin.directory instead,
which is already used as the row's unique GridList id.
Flagged by Copilot and Aikido on Kong/insomnia#10317.
* fix(plugins): (#10295 follow-ups) route plugin_reload shortcut through worker reload; null-proto plugin maps (#10346)
Two same-bug-class follow-ups to the #10295 fix:
- use-global-keyboard-shortcuts.ts: the `plugin_reload` shortcut called only plugins.reloadPlugins(),
bypassing the render-worker cache invalidation (reload()) that the Settings→Plugins button does — a
live instance of the P0-A staleness bug. It now rescans AND invalidates the Liquid-engine cache.
- plugins/index.ts: pluginMap and nameCounts are now Object.create(null). With a plain {}, a plugin
named `toString`/`valueOf`/`hasOwnProperty`/etc. matches an inherited prototype member, which could
skew duplicate detection and — via `name in pluginMap` in the load-error handler — silently drop a
failed plugin instead of surfacing a disabled row (a P0-B hole for prototype-method names).
* fix(plugins): re-check duplicate names before running a plugin's code
The duplicate-name scan in getPlugins() takes a snapshot before the load
pass's own walk, which has await points of its own. A folder claiming an
already-elevated plugin's name that appears after the snapshot but before
the load pass reaches it wasn't caught, since the "unique name" success path
overwrote pluginMap unconditionally. Re-run the same scan immediately before
a folder's code executes, so a name that's since become ambiguous is routed
into the same disabled row the initial scan already produces.
---------
Co-authored-by: jackkav <jackkav@gmail.com>
* add package
remove workspaceCount from rootLoaderData
move unrelevant loaders out
add query context
adapt tanstack query
fix som issues
add new ways to load data
initial changes
clean code
remove and fix code
add a method to get organization data in main
refine the way to get data from tanstack
fix issue
fix issues
fix duplicate calling issue
fix unsubscribe issue
fix merge issue
fix listen issue
fix find organization issue for workspace
support workspatemeta in tanstack query
update types
move logic to insomnia-data services
remove things
change to use service
fix the loader bug
remove a file
fix type issues
refine code for workspace-children
change style import
fix main type issue
fix type issue
fix data fetching
fix delete project issue
cache the sidebar data in main
add unit tests
update cache and cache service
fix issues from comment
revert organization change
fix issues from comment
fix test failures
fix test failures
add comments and refine way to get workspace children
fix dedup and import issue
remove useless code
add duplicate id check
fix type failures
fix mock server issue
resolve conflict
1.remove main process cache
add renderer level app data
fix issues
* fix issues from review