Skip to content

feat(sandbox): services-layer capability-scope hardening - #10232

Open
kwburns-kong wants to merge 11 commits into
developfrom
sec/sandbox-services-fixes
Open

feat(sandbox): services-layer capability-scope hardening#10232
kwburns-kong wants to merge 11 commits into
developfrom
sec/sandbox-services-fixes

Conversation

@kwburns-kong

Copy link
Copy Markdown
Contributor

What this PR does

  • Reload the response by _id in getBodyBuffer instead of trusting a plugin-supplied path. This is used to block arbitrary file reads via models.read
  • Reload the credential by _id in cloudCredential.update and strip identity fields from the patch. This is used to block cross-collection writes via credentials.
  • Coerce id/parentId/key args to String(...) before they reach NeDB queries. This is used to block Mongo-operator injection ($ne, $where, etc.).
  • Require an exact match or separator-bounded prefix in secureReadFile's allowlist.
  • Resolve symlinks before checking secureReadFile's allowlist.

jackkav and others added 8 commits July 9, 2026 06:18
Every side-effecting bridge path maps to exactly one capability group
(BRIDGE_PATH_CAPABILITIES); filterByCapabilities wraps the handler map so an
ungranted path rejects with 'Capability X not granted — add it to
insomnia.permissions.capabilities', and an unmapped path fails closed. The
template-tag surface resolves baseline ∪ manifest.capabilities; bundle
(first-party) plugins get ALL_CAPABILITIES. Envelope carries
grantedCapabilities for C2.

Baseline capabilities: render, models.read, util, crypto (network/storage/
fs-read/credentials/app must be declared). 'util' (nodeOS/decode/encode) is
baseline — same info the built-in os/base64 tags already expose.

- unit: completeness test parses every __bridge() path from the bootstrap and
  asserts a capability mapping (new ungated path fails); filter matrix; e2e grant/deny/baseline
- e2e: plugin declaring 'storage' round-trips context.store; undeclared denied
  with the exact message; baseline util.render still works (per-capability)
- demo: capabilityprobe tag + storage grant

Deviations from plan letter: added 'util' baseline (canary needs nodeOS); used
storage not network for the positive-path e2e (cleaner than building a request).
…dules (C1)

- resolveTemplateTagCapabilities now drops declared names that aren't real
  Capability values, matching its docstring (keeps the envelope clean for the
  P1 ceiling intersection).
- Bundle (trusted first-party) plugins now receive ALL_SANDBOX_MODULES too, so
  the 'every module + capability' comment is accurate — they no longer silently
  run on the baseline module set.
…ary file read

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ock cross-collection write

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…list

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes a gap where a symlink inside an allowed directory could point
outside it and bypass the allowlist.
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

✅ Circular References Report

Generated at: 2026-07-09T20:21:25.670Z
Status: ✅ NO CHANGE

Summary

Metric Base (claude/sandbox-pr5-capability-context) PR Change
Total Circular References 9 9 0 (0.00%)
Click to view all circular references in PR (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx
Click to view all circular references in base branch (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx

Analysis

No Change: This PR does not introduce or remove any circular references.


This report was generated automatically by comparing against the claude/sandbox-pr5-capability-context branch.

kwburns-kong and others added 2 commits July 9, 2026 15:20
…s fixture

The 'invalid' dataFolders entry only worked by string-prefix coincidence
with invalid.cert/invalid.key, which the separator-boundary fix in
ebece69 correctly no longer allows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nstance

A disallowed or unreadable path on one client certificate threw out of
the forEach loop and aborted curl setup for the whole request, so a
single bad certificate silently dropped every other valid one too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kwburns-kong

Copy link
Copy Markdown
Contributor Author

The isPathAllowed allowlist was a loose string prefix (.../invalid). When tightening, a pre-existing bug was identified where createConfiguredCurlInstance threw on the first rejected certificate and aborted the whole request. Fixed by isolating each certificate's error so a rejection only passes, as per the original functionality.

…lders fixture

'certificates/client' isn't a real directory — client.crt/client.key are
flat files under certificates/. It only worked by the same string-prefix
coincidence the separator-boundary fix in ebece69 correctly no longer
allows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jackkav
jackkav force-pushed the claude/sandbox-pr5-capability-context branch from a6a21a3 to 630d1c0 Compare July 13, 2026 13:10
Base automatically changed from claude/sandbox-pr5-capability-context to develop July 13, 2026 14:14
@jackkav
jackkav requested a review from a team July 13, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants