Security Model

August 24, 2026 ยท View on GitHub

Repository contents, paths, AST patterns, LSP messages, and configured process output are untrusted.

Invariants

  1. Every requested path is resolved by ctx.fs and proven contained by the calling session's canonical workspace target.
  2. Reads are UTF-8-only, complete-file bounded, canonical-result bounded, and exact-byte versioned. Only complete visible lines enter the local observation store; the public whole-target observation event is withheld until accumulated same-version pages visibly cover the complete file.
  3. Range edits require the same owner, canonical target, exact version, and observed source lines. All operations are validated before one guarded atomic write.
  4. Filesystem mutations require an explicitly writable per-call sandbox policy. Read-only mode fails before the write and uses DSH's standard one-call escalation contract only with a sandbox-enforcing filesystem; bare providers cannot escalate. Generic approval never widens policy.
  5. Process-backed tools use one-shot user approval by default. Operators may disable that prompt, but the fully specified spawn plan, scrubbed environment defaults, forced read-only DSH policy, confinement eligibility gate, cancellation, time, and output bounds remain mandatory.
  6. Protocol frames are size-bounded before body allocation; pending requests and queues are capped.
  7. LSP server requests that could mutate or execute commands are rejected. workspace/applyEdit always returns applied: false.
  8. Cursors are random, server-stored, owner-scoped, query-bound, byte/count bounded, and expiring. They advance only across items admitted to the complete structured and rendered page; deduplication and deterministic sorting precede caps.
  9. Cordis disposal aborts in-flight starts, terminates every owned process tree, and clears byte/count/TTL-bounded cursors and observations.
  10. Before a guarded write commits, the tool proves that a fixed diff digest and meaningful bounded preview fit the applied-result envelope and persists a truncated full diff when spill storage is available. Every later failure is contained in explicit applied/landed warning evidence; intendedVersion remains distinct from optional verified newVersion, and diagnostics are suppressed unless landed bytes match. The tool does not throw a retry-inducing post-commit error.
  11. Versionless LSP diagnostics are never certified as fresh; versioned diagnostics must pass both version and post-sync sequence barriers.
  12. AST search processes receive only one stable provider-read file snapshot over stdin. Broad process-path scans, ast_edit, and DAP debugging remain disabled in the initial release.
  13. Settings UI writes pass the same strict schema and cross-field validation as profile configuration. Each independently committed nested settings field replaces one complete tool generation live; a multi-field Save is not atomic and can retain a safely ordered committed prefix if a later write fails. Approval tightening commits before protected-feature enablement, feature disablement precedes opt-outs, and reduced isolation plus approval opt-outs commit last. For every committed field, dispatch is guarded during transition, old calls are cancelled and drained, exact registrations are removed, process resources are quiesced, and stale cursors or observations are discarded. An activation or teardown failure leaves dispatch guarded and the tool set fail-closed rather than restoring a generation whose approval policy could differ from committed Settings.

Operator trust controls

approvals.editRanges and approvals.processStart default to true. Disabling them is an explicit operator decision suitable only for trusted workspaces and executables. The opt-out bypasses only the generic prompt: writable filesystem policy, exact-version observations, guarded atomic writes, absolute executable resolution, forced read-only process policy, and the confinement eligibility gate are unchanged. Explicit sandbox escalation always retains DSH approval.

processPolicy.allowWindowsPartialReadOnlyProcessConfinement is a separate trust control and defaults to false. With the exact opt-in enabled, DSH-reported partial confinement is eligible only on the native Windows Host and only after the resolved process policy is proven read-only. full remains accepted under read-only policy everywhere; none, unknown, malformed, non-Windows partial, and every writable policy fail closed.

The opt-in is a documented reduction, not full equivalence: Windows restricted-token enforcement retains Everyone-related ACL and NTFS hard-link write edge cases, FAT-class targets outside granted roots remain writable, and it does not isolate reads, network access, or process visibility. The plugin necessarily trusts the public sandbox provider's reported enforcement because that contract does not expose backend attestation.

Known public-contract gate

DSH currently exposes generic one-shot approval and managed subprocess services, but no atomic process-bound launch authorization or sandbox-backend attestation. With process approval enabled, the plugin resolves and confines the exact plan, then requests approval immediately before startup; partial enforcement is named explicitly in that approval warning. It fails closed if approval is unavailable, rejected, cancelled, or lacks a live agent. With approval disabled, the same read-only policy and enforcement gate still apply. Full enforcement is required unless the independent native-Windows partial-confinement opt-in is active.