* fix: propagate system proxy settings to user requests (INS-2943)
When proxyEnabled is false in Insomnia Preferences, the request engine
(node-libcurl) now falls back to the OS system proxy via Electron's
session.defaultSession.resolveProxy(), matching the behavior of
Insomnia's internal API calls.
Previously, disabling the proxy toggle explicitly set CURLOPT_PROXY to
an empty string, which prevented libcurl from using any proxy including
the system proxy. This caused user requests to bypass the OS proxy while
Insomnia's own network calls (via Chromium's network stack) correctly
respected it.
Changes:
- Add parseResolvedProxy() helper to parse PAC-format proxy strings
- Call resolveProxy() inside createConfiguredCurlInstance() when proxy
is not explicitly configured
- Refactor api.protocol.ts to use the shared helper (removes ~50 lines
of duplicated proxy parsing logic)
* fix: catch resolveProxy errors and fall back to direct connection
* fix: catch resolveProxy errors in api.protocol.ts
* fix: remove redundant comment about proxy mode in updateProxy function
* feat(templating): seed ambient sandbox stdlib globals (M2)
Add always-present, ungated safe-equivalent globals to the QuickJS sandbox:
Buffer (from/alloc/concat/isBuffer + utf8/base64/hex/latin1), a frozen
process stub (platform/arch from the envelope, empty frozen env, microtask
nextTick), Web-Crypto crypto.getRandomValues + crypto.subtle.digest
(host-backed), and URL/URLSearchParams. Lives in sandbox-globals.ts, eval'd
after the bootstrap + host-crypto installs.
Because the sandbox now provides a process stub, the old
'typeof process === undefined' sandbox-detection heuristic no longer holds;
add a non-writable INSOMNIA_TEMPLATE_SANDBOX marker and switch the canary +
demo probe to it.
- +19 unit parity tests vs node: Buffer/subtle/URL/URLSearchParams/getRandomValues + escape + marker
- e2e: stdlibprobe renders each API; flag-off captured and asserted byte-identical
under the flag (parity), subtle pinned to a known hash, process.env '{}' + frozen sandbox-only
- smoke helpers wait for modal close + poll the post-toggle canary (re-open until
the flag propagates), de-flaking the mid-test toggle
- demo plugin gains a stdlibprobe tag
require() module wrappers (url/buffer/util/querystring/string_decoder/assert)
are the M2b follow-up; they mostly re-export these globals.
* test(sandbox): pass M2 global-probe values as tag args, not interpolated code
CodeQL flagged the runGlobal test helper for constructing eval'd plugin
source from interpolated values. Make body a constant literal at every call
site and thread dynamic values through the tag's args (envelope data, read as
arguments[1..]) so no test value is concatenated into sandbox-eval'd code.
* fix(sandbox): enforce WebCrypto 65536-byte quota in getRandomValues + review nits
- getRandomValues now throws past 65536 bytes (matching WebCrypto's
QuotaExceededError) instead of silently zero-filling the tail beyond the
host __cryptoRandomBytes clamp — no predictable output.
- Correct the enableSandbox comment: assertions are expect.soft (mandated by
the smoke ESLint config); the authoritative flag-applied signal is the
downstream polling canary.
- Fix a doc-comment typo: typeof process === "undefined" (quoted).
* fix(sandbox): M2 stdlib parity fixes + bridge hardening (#10224)
* fix(sandbox): plumb host arch into process stub
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sandbox): add crypto.randomUUID to ambient web crypto
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sandbox): URLSearchParams.set keeps first occurrence
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sandbox): support URLSearchParams copy-construct
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sandbox): guard bridge dispatch against inherited keys
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sandbox): hide raw host bridge from plugin code
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(lint): fixed linting issue
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The Edit menu's Undo/Redo used role: 'undo'/'redo', driving only the native
webContents stack. On macOS the menu accelerator swallows Cmd+Z before
CodeMirror's keymap, so CodeMirror surfaces had no working undo — two competing
stacks with the native one always winning and doing nothing useful for CM.
Menu Undo/Redo now send edit:undo/edit:redo to the focused window; a single
renderer handler (editor-undo.ts, wired in renderer-listeners.ts) routes by
focus: CodeMirror surfaces drive cm.undo()/redo(); everything else replays the
native execCommand, preserving prior plain-input behaviour. No double-fire: the
accelerator still keeps CM's own keymap from firing independently.
* tech_design
* tech-doc
* add directory to git repo model
* tech doc
* tech doc
* use directory picker to select an existing repo to clone from/to
* tech doc
* Open git repo
* tech doc
* Implement Git project local storage features and add e2e tests
* tech doc
* Implement folder opening as Git projects with user trust confirmation
* Add Git credential selection to project creation form and enhance repo file watcher for directory availability
* tech doc
* refactor: clean up code and remove references to GIT_LOCAL_REPOS_DESIGN.md
* fix: handle optional author name in Git credential display
* feat: enhance Git credential handling for local repositories
* feat: enhance Git project folder handling and improve test descriptions
* fix: update Git project mode button copy
Rename 'Clone from URL' to 'Clone from Remote' and 'Open existing
folder' to 'Open local folder'. Update the smoke test selector and a
stale comment accordingly.
* fix: align control heights and styling in Git clone form
Standardize the credential select, author email select, and clone
location box to match the repository/branch comboboxes: shared
--line-height-xs height, consistent label spacing, and input-sized
value text and padding.
* feat: show clone target path and remember last clone folder
Default the clone parent directory to the folder the user last cloned
into, and render the resulting target path middle-truncated with a full
path tooltip via a new MiddleTruncate component.
* fix: reorder and align Open local folder input layout
Move the helper text directly below the Folder label, and align the
folder box and Choose folder button to the shared control height with
middle-truncated path display.
* feat: warn when opening a folder already used by a project
Add a git.checkGitRepoDirectory IPC that resolves the project adopting
a folder. The Open local folder flow checks at folder-pick time and
shows a red, no-background warning below the input offering to open the
existing project, and blocks continuing while the warning is present.
* fix: top-align empty organization view and scroll the full page
Replace the vertically centered grid with a top-aligned, page-scrolling
layout so the new project form no longer jumps when switching project
types and the scrollbar spans the whole pane.
* fix: align project modal to top and match folder description color
Top-align the project modal overlay so it no longer jumps as the form
height changes, and drop the dimmer color override on the Open local
folder helper text so it matches the repository URL field description.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: always use getRepoBaseDir
* fix comment
* delete duplicate code
* fix: test
* test: add Git repository relocation tests
* fix: ensure selection change handler converts key to string
---------
Co-authored-by: Pavlos Koutoglou <pkoutoglou@gmail.com>
Co-authored-by: Curry Yang <163384738+CurryYangxx@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Curry Yang <1019yanglu@gmail.com>
* feat: adds some progress to fixing issue with invalid spectral rulesets being imported when creating git sync projects
* feat: surfaces ruleset import problem to the renderer in git sync projects
* test: adds additional test
* chore: formatting
* fix: ui
* feat(templating): manifest-gated module registry for the sandbox require (M1)
Replace the hardcoded path/crypto require shim with a curated module
registry (single source of truth in module-registry.ts) resolved by a
default-deny __require against the envelope's grantedModules:
- ungranted name -> "Module 'X' not permitted by manifest"
- granted, no impl -> "Module 'X' not available in sandbox"
Grants are the hardcoded path/crypto baseline until the manifest loader
(C3) lands. node:-prefixed aliases resolve to canonical names; exports
are cached per context. E2E: requireprobe tag asserts the baseline works
through the registry and that npm/builtin names fail with the exact
denial message in the tag Live Preview.
* sec(templating): capture envelope before plugin eval; lock registry; null-proto maps
- Inject __envelopeJSON/__tagName before the bootstrap, capture them into
closure state, and delete the globals — plugin top-level code can no
longer rewrite grantedModules (or any envelope field) before __invoke().
- delete __registerModule once the registry is populated so plugin code
cannot register or replace factories.
- Null-prototype registry/alias/cache maps so __proto__/constructor behave
as absent keys.
- Test helper defaults grants to TEMPLATE_TAG_BASELINE_MODULES; new tests
cover envelope tampering and prototype-chain module names.
* sec(templating): harden module gate against intrinsic tampering
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* sec(templating): lock sandbox-internal globals from plugin reassignment
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* sec(templating): enforce trusted-literal invariant for module factorySource
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Kyle <kyle.burns@konghq.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(templating): PoC run plugin template tags in a QuickJS-WASM sandbox
Behind a new `templateTagSandboxEnabled` setting (default off), route plugin
template-tag execution through a QuickJS-WASM sandbox instead of invoking the
plugin's `run()` directly in the main process.
Approach (per PR #10072): bulk-copy render state into the sandbox as JSON,
rebuild the plugin `context` API in pure JS inside the sandbox, and bridge only
async work back to the host via the existing `pluginToMainAPI` handlers.
`node:crypto` is exposed as synchronous host functions so `require('crypto')`
works without a sync/async mismatch.
- templating/sandbox/: quickjs-runtime, marshal, host-bridge, in-sandbox-bootstrap,
plugin-tag-sandbox (+ parity tests vs in-process tags and node:crypto)
- main/templating-worker-database.ts: route execute handlers through the sandbox
when the flag is on; legacy path unchanged otherwise
- esbuild: keep quickjs-emscripten external so its .wasm resolves at runtime
- settings + scripting-settings UI toggle
- examples/insomnia-plugin-sandbox-demo: manual E2E fixture
Scope: template tags only; sandbox runs in main. require shim covers path + crypto
(other modules throw a clear error — follow-up work).
* test(smoke): e2e canary for the template-tag sandbox flag
Installs an inline probe plugin, renders its tags via the tag editor Live
Preview, and asserts the execution path flips main-process -> sandbox when
templateTagSandboxEnabled is toggled in Preferences > Scripting, with a
require('crypto') sha256 workload staying byte-identical across both paths.
* test(sandbox): suppress hardcoded-hmac-key semgrep finding on parity fixture
The HMAC key is a test vector for sandbox-vs-node:crypto parity, not a
credential; rename it to make that self-evident and add the repo-standard
nosemgrep suppression.
* fix(templating): contain sandbox plugin entry resolution to the plugin directory
Reject a package.json "main" that resolves outside the plugin's own folder
and bundled-plugin names that look like paths, so the sandbox source loader
cannot be steered into reading arbitrary files.
* fix(review): inline nosemgrep placement, plugin-load error context, cross-arch-safe canary
- Move the hardcoded-hmac-key suppression onto the flagged line (line-above
placement was not honored by the scanner).
- Wrap getPluginEntrySource failures with the plugin name for diagnosability.
- Derive the canary's expected arch from the Electron main process instead of
the Playwright runner so cross-arch setups can't flake the assertion.
* sec(templating): QuickJS template-tag sandbox additions (#10209)
* fix(sandbox): enforce timeout on synchronous plugin loops
QuickJS's executePendingJobs() blocks the host thread until a synchronous
call returns, so the wall-clock deadline in drivePromiseToString was never
checked during a tight sync loop in plugin code, hanging the Electron main
process indefinitely. Add a QuickJS interrupt handler, which is polled
during synchronous execution, to enforce the deadline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): clamp crypto.randomBytes size to prevent OOM
hostCrypto.randomBytes(size) passed the sandboxed number straight to
Node's crypto.randomBytes with no upper bound, letting a plugin request
a multi-GB allocation (e.g. crypto.randomBytes(2 ** 31)) and crash the
host process. Clamp to 64KB before the call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): cap QuickJS heap to prevent unbounded allocation
QuickJS.newContext() had no memory limit, so a plugin allocating without
bound could exhaust the WASM heap and crash the host process. Set a 32MB
ceiling via ctx.runtime.setMemoryLimit().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): resolve symlinks before validating plugin entry path
getPluginEntrySource's containment check compared raw path strings, so a
plugin directory with a symlinked entry (e.g. index.js -> ../../../etc/secret)
passed the check while fs.readFileSync followed the symlink and read the
out-of-directory target. Re-run the check against fs.realpathSync'd paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): close util.render sandbox escape
context.util.render() bridged to the shared render() pipeline, whose Liquid
engine dispatches any registered tag's real run() directly, in-process,
regardless of templateTagSandboxEnabled. A sandboxed plugin could hand it a
string containing "{% anyTag %}" (including its own tag) and have that tag
execute completely unsandboxed. Verified with a PoC that reached
child_process execution from inside a plugin tag with no require() or Node
access.
util.render is now restricted to plain {{ variable }} interpolation (the
only real existing use, confirmed against all built-in tag call sites) via
a second Liquid engine with no tags registered; {% tag %} syntax now fails
to parse instead of dispatching. Default render() behavior is unchanged for
every other caller.
Also drops the dead renderDepth field's misleading doc comment: within one
sandboxed execution the envelope's renderDepth is always 0, so depth could
never exceed 1 regardless of enforcement — it couldn't have caught this
recursion anyway.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sandbox): fixed linting issue
* fix(sandbox): fixed linting issue
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: kwburns-kong <kyle.burns@konghq.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(Git Credentials): refactor repository deletion logic and filter projects by user organization
* Update method name
* fix(git-credentials): handle organization loading errors and return unfiltered projects if organizations are unavailable
* refactor: enhance RepoFileWatcher with improved debounce handling and workspace ID resolution
* refactor: improve path validation and symlink handling in RepoFileWatcher
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* refactor: implement path-traversal guard in RepoFileWatcher
* refactor: enhance error handling and fallback mechanism in RepoFileWatcher
* refactor: use lstat to handle symlinks in RepoFileWatcher and prevent unnecessary imports
* refactor: add debounce handling for project-level lint ruleset flush in RepoFileWatcher
* refactor: add BaseModel import to enhance type definitions in RepoFileWatcher
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* feat: focus and keyboard navigation improvements [INS-2552]
Make common create/edit flows land the cursor where you'd start typing,
and let the navigation sidebar expand/collapse folders with the arrow keys.
- New request focuses the URL bar
- Adding a query param / header focuses the new row's Name cell
- Opening the KV environment editor focuses the trailing blank row's Name
- Create/rename/settings dialogs focus the Name field
- Sidebar Left/Right arrows collapse/expand the focused folder
- Cmd/Ctrl-N creates the request inside the selected folder
OneLineEditor gains autoFocus/onAutoFocus. The editor focus is deferred a
frame so it wins against React Aria ListBox focus restoration, and the
"new request" signal is module-level (read in render, cleared on focus) to
stay correct under React StrictMode double-mounting.
Adds focus-and-keyboard smoke tests to guard against regressions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: make autofocus survive React Aria ListBox focus restoration [INS-2552]
The param/header/environment grids wrap their inputs in a React Aria
ListBox, which restores DOM focus to the row right after the editor focuses
itself. A single deferred focus won this race locally but lost on slower
headless CI, so the grid/env focus smoke tests flaked.
Re-assert focus across a short bounded window (rAF, up to 500ms), re-grabbing
only when focus was bounced to a non-editable element (the row) and never when
the user moved to another field, until the editor holds focus or the window
elapses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor: key grid autofocus off the new pair id, not a shared flag [INS-2552]
The previous module-level boolean was shared across every KeyValueEditor
instance, so a concurrently mounting/remounting grid could consume it and
focus an unrelated row. Store the specific new pair's id instead (it survives
the async save and the remount) so only the newly added row can autofocus,
and clear it once that exact row focuses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Fix test
* Fix test
* Fix test
* Fix tests
* Typo
* Fix tests
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: add native git credential provider and update related components
- Introduced a new NativeGitCredential type to support system git credential manager.
- Updated GitCredentials model to include native provider type.
- Implemented NativeProvider class to handle authentication via OS git credential manager.
- Refactored git service and utils to accommodate new repoPath parameter for native credentials.
- Enhanced UI components to support native credential setup and display.
- Updated migrations to ensure native credential singleton exists on startup.
- Adjusted various components to handle optional chaining for author fields.
* feat: enhance git credential migration and improve native provider path handling
* fixup: address feedback
* fix spawn error pipe on windows
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* refactor: update import path for GitCredentials type in NativeProvider
* feat: update project page to explicitly select custom Git credentials during project creation
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>