chainlesschain 0.163.1 → 0.163.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-Cn7quRgL.js → AIOps-DnGsmsqJ.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-YqMX3ueH.js → ActionButton-CrO6fcQ7.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-Bxmy1b7Y.js → Analytics-DsBdOaP2.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-DBOw69jE.js → AppLayout-DmQslKUB.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-mq1nyzN1.js → Artifacts-BvyrT_QQ.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-mMiKtZ0D.js → Audit-prndoLiC.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-WBUjpYVh.js → BackgroundAgents-DOTFyA55.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-c25OoJgs.js → Backup-9zOnPp_8.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-BbfWhZ4-.js → BaseInput-C4PC6sAG.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-CVVzsTwU.js → Chat-BBAF-W9v.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CVCjZJ04.js → ChatBubbleRenderer-CWhvvloO.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-C9o2HK-1.js → Checkbox-BI9iculd.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-B7X5LfKc.js → Codegen-3DP9BCKb.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-jpPj2Pur.js → Col-df-2TnJX.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-Dti6bHxN.js → Community-CHs8gG_A.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-S4ZsLt3W.js → Compact-CDfF6q7V.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Bge0sQ3O.js → Compliance-CthrDnO7.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-C4XyzVI7.js → Cowork-HjIqsWJw.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-CPR0v2xy.js → Cron-BKc196fb.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-DAX8lDaj.js → Crosschain-CJnjdc8W.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-fBHPa0QH.js → DID-BHUy-8Q2.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-vvaUTafU.js → Dashboard-QDB7sKeY.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-DyaQM63v.js → Dropdown-DStcVK11.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-CAF0wiU2.js → EmailListRenderer-BwSUskMJ.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-ia-WzDRs.js → FamilyGuardDashboard-DgF_kurT.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-Cz3gHoT5.js → Federation-k8wvv-wN.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CJQDJr4Q.js → FormItemContext-C11qoq2r.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-B05BZlQp.js → GenericCardRenderer-BIIpr9kg.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DT0YcQnI.js → Git-BlA1exTe.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-Bqbl6m5Q.js → Governance-CYa1ZYM4.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BdebLR0N.js → Inference-6_kKVIt6.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-M36b8YYV.js → KnowledgeGraph-CB4AwxYy.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-5LN_XL43.js → Logs-xf7nHFAe.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-Bf3DEqP6.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-BkIin-QY.js → Marketplace-aPg8e4Jt.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-Bkppx8Uj.js → McpTools-C-TNlVUf.js} +5 -5
  38. package/src/assets/web-panel/assets/{Memory-Qk9wg_Ib.js → Memory-DMTPIpGa.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BsTDU3Aj.js → MobileBridge-BxyvveRq.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-CrZW5I28.js → MobileProjects-DyPCrAyQ.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-BMkmgtsA.js → Mtc-BdhqNXp6.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-6m4CC0Yn.js → MtcAudit-Cz-HFxzW.js} +5 -5
  43. package/src/assets/web-panel/assets/{Multisig-BZ8yB7QV.js → Multisig-CIUaFNsx.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CxitAMIO.js → NLProgramming-CWe6-J17.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-Bv0msnHu.js → Notes-vYAKeviU.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-DeVMqM3P.js → NotificationSettings-DQL9-2d7.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-CXBSWa3R.js → OrderTableRenderer-DnXj1jBn.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-b_G5Vs1Q.js → Organization-B3spU8AN.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-DW7riOmA.js → Overflow-DgEwo7vm.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CtpQNYjL.js → P2P-hujMRH8X.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-Ba63yT4l.js → PdhVaultBrowser-C_qhdg9h.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-DnzyeB67.js → Permissions-vp7LMcSf.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-DbPZ7HWw.js → PersonalDataHub-Dxr5Hgnq.js} +3 -3
  54. package/src/assets/web-panel/assets/{Pipeline-gs_HOThJ.js → Pipeline-DEPZqqH4.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-CZlQ1EjE.js → Privacy-DTpDiKPe.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DQp__Ccb.js → ProjectInit-jDJsRWmF.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-C7h2sOWZ.js → ProjectSettings-Dhor5RWH.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-DdCpNRNt.js → Projects-08xUDZGt.js} +1 -1
  59. package/src/assets/web-panel/assets/Providers-BGs47s1a.js +1 -0
  60. package/src/assets/web-panel/assets/{QrScannerModal-B_8M1-FC.js → QrScannerModal-CjIw-wIb.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-Bpycr8WD.js → QuickAsk-DX6jcqoi.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Z4TrcNzs.js → Recommend-DopXkhar.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-BD6TsJlS.js → RemoteSession-BLvqJE9c.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-IKxDXHEu.js → Reputation-DhRj2Me7.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-DbmR20tJ.js → Row-DQ53vuPq.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-CLjA5PPf.js → RssFeed-BslvwiBD.js} +2 -2
  67. package/src/assets/web-panel/assets/{Search-Bm3owbIU.js → Search-DJKBDNKZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CY4RyOuq.js → Security-COhpxHER.js} +3 -3
  69. package/src/assets/web-panel/assets/{Services-CYO9qrd_.js → Services-dbulD6cI.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-ClF51Go6.js → Skeleton-ciIVNfhC.js} +1 -1
  71. package/src/assets/web-panel/assets/Skills-AiRTkTCk.js +1 -0
  72. package/src/assets/web-panel/assets/{Sla-zqpDUxzP.js → Sla-DDMcWYBc.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-DPSi8Qco.js → SpeechSettings-BPxWbpXO.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-CqABopsQ.js → SyncSettings-BoEOXCyg.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-4dbAJng4.js → Tasks-CEYFJwmr.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-Dzl6f0M2.js → Templates-UowY8Ixe.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-XeZkw40a.js → Tenant-DauSLQXN.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-CYw2YzPm.js → Terminal-DBj7Jneq.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-Bc2pko4i.js → TimelineRenderer-UMrPwoZC.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-CfCenOHx.js → Tokens-4ea96-bn.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-DTz-_YqV.js → Trigger--ISCqt4b.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-CB3tt3Z6.js → Trust-D4GVimRJ.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-y1ykmMvU.js → UkeySign-Ci-nXRQc.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-UlZ_lX0e.js → VideoEditing-Cjk7mKPw.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-DMBaHTha.js → Wallet-BgOLOO3Z.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-Cksm-hBI.js → WebAuthn-CCX0K29i.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-BhOa40sX.js → WorkflowEditor-Ch3zgIsE.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-DNbeSTDO.js → chat-DKOU_2Vb.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-9zz8gBmW.js → colors-6OVo4u3C.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-D7aoVv-5.js → compact-item-BH78Hlsq.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DYg7B8nd.js → createContext-CFRpSbbC.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-DEMblAIm.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-BNbhkcoI.js → hasIn-DNQhgcVi.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-gNKj00Fx.js → index--rq90rL9.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-FlBuITVG.js → index-7TC3S8SN.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-nnmo3ipi.js → index-AuBhLqOm.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-Dn-JFqEi.js → index-BDSR7ecX.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DUWmZ059.js → index-BHa4WyTZ.js} +1 -1
  99. package/src/assets/web-panel/assets/index-BTvq-36D.js +1 -0
  100. package/src/assets/web-panel/assets/{index--TvoQ6UC.js → index-BYrnm5Ob.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CpEIwp4A.js → index-B_Z-YoxX.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DnTM8FWK.js → index-BaVE6E8y.js} +3 -3
  103. package/src/assets/web-panel/assets/{index-67GdrUx2.js → index-Bb6kDrUx.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BPojutcZ.js → index-BepBTpa8.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CV06YdPO.js → index-BkN3iTTp.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CN6-OEgS.js → index-BnnXQot_.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DHskwmwI.js → index-BujsOZfc.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-B9zUawcE.js → index-BxRy5LPR.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-C8LC0nvw.js → index-CFPJ8yzF.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DMrqEsOS.js → index-CNuCHHQT.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Da0SysnX.js → index-CaYqY35Z.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Cq3l0L7C.js → index-CkNEMANR.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DIljkSt9.js → index-CkqHgG-b.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CYu-F-gp.js → index-CrcLHN2F.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DtQzs0hH.js → index-Cu3L4r5l.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-SmEIFaRm.js → index-D3RtTT4K.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-ZPDbEh-L.js → index-D84id2Y4.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CzDDeZBo.js → index-DKN2noIF.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Bdxe0nrD.js → index-DaDgdJYj.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-uc8Rz96X.js → index-Du0rnksC.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Cqy-hqD9.js → index-DvHGtNnF.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-B9TzVW7i.js → index-Eag8e_mA.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BRd1zkLB.js → index-HNGGVF6o.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-jS6NASar.js → index-Y9MJv28e.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DIMVe3HJ.js → index-bKm3TUDp.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-B8irlIUK.js → index-caye7AOE.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CRKukX1W.js → index-cdf7fd7d.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DeD1wWA8.js → index-dDkoL4Pe.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CA72qB1n.js → index-hPY0fFrd.js} +1 -1
  130. package/src/assets/web-panel/assets/index-hUpvk6Jl.js +1 -0
  131. package/src/assets/web-panel/assets/{index-_-Vt1Wqk.js → index-nbfHl1oV.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-m2pXS3W2.js → index-sm7W8AXy.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-D0mTMUGz.js → initDefaultProps-BZ9w6jPL.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-DK16p4-o.js → motion-BnwUiOho.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-DalC20HC.js → move-ByUKJnNm.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-B5RusszF.js → mtc-parser-V7yK1KEl.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-C9Mhitht.js → omit-BEXBBt4j.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-51xQLgwM.js → pickAttrs-qDm_46Gi.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-CJzIqp8u.js → placementArrow-BIbhEo_0.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-HQvC19u4.js → responsiveObserve-NbPbDgA_.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-C6hhabOp.js → slide-BnUWglZ0.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-Q1r48-oc.js → statusUtils-BX8_wZI5.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-UakVWrHs.js → styleChecker-BV4OycQX.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Dmv94cxx.js → useFlexGapSupport-Od_H5llY.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DrxOnt_V.js → useFs-BWI-PyiX.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-BVf2M-Hg.js → usePersonalDataHub-BqMuhG3g.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-BzzW9qKH.js → vnode-DNd23z6f.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-C1ZvMgAZ.js → zoom-Cjaxnm7l.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/mcp.js +29 -1
  151. package/src/data/changelog.json +15 -2
  152. package/src/harness/mcp-client.js +15 -2
  153. package/src/lib/cowork-mcp-tools.js +1 -0
  154. package/src/lib/cowork-task-templates.js +1 -0
  155. package/src/lib/mcp-stdio-executable-identity.js +75 -11
  156. package/src/lib/mcp-stdio-execution-authority.js +5 -0
  157. package/src/lib/process-execution-broker/index.js +316 -22
  158. package/src/lib/process-execution-broker/platform-sandbox.js +481 -20
  159. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  160. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  161. package/src/lib/process-execution-broker/windows-sandbox.cs +5 -4
  162. package/src/lib/skill-mcp.js +10 -0
  163. package/src/runtime/mcp-config.js +3 -0
  164. package/src/assets/web-panel/assets/MarkdownRenderer-BCb1Dm8l.js +0 -1
  165. package/src/assets/web-panel/assets/Providers-CyvtUkUf.js +0 -1
  166. package/src/assets/web-panel/assets/Skills-CCCEmSf5.js +0 -1
  167. package/src/assets/web-panel/assets/devWarning-uadaGF_y.js +0 -1
  168. package/src/assets/web-panel/assets/index-C7zhie9M.js +0 -1
  169. package/src/assets/web-panel/assets/index-Cmbg0Wbr.js +0 -1
@@ -169,7 +169,14 @@ const LINUX_EXECUTABLE_SNAPSHOT_SOURCE_MODE = 0o500;
169
169
  const LINUX_MCP_CAPSULE_BACKEND = "linux-fd-code-snapshot";
170
170
  const LINUX_MCP_RUNTIME_SNAPSHOT_SCOPE = "mcp-node-runtime-executable";
171
171
  const LINUX_MCP_CAPSULE_SNAPSHOT_MECHANISM =
172
- "verified-o_tmpfile-copy-inherited-fd-exec-v1";
172
+ "verified-o_tmpfile-copy-inherited-fd-module-compile-v1";
173
+ const MACOS_MCP_CAPSULE_BACKEND = "macos-fd-code-snapshot";
174
+ export const MCP_STDIO_FD_ENTRY_BOOTSTRAP =
175
+ 'const fs=require("node:fs");const Module=require("node:module");const filename="/chainlesschain/mcp-capsule.cjs";const source=fs.readFileSync(4,"utf8");process.argv.splice(1,0,filename);const target=new Module(filename,module);target.filename=filename;target.paths=[];target._compile(source,filename);';
176
+ export const MCP_STDIO_FD_ENTRY_BOOTSTRAP_SHA256 = crypto
177
+ .createHash("sha256")
178
+ .update(MCP_STDIO_FD_ENTRY_BOOTSTRAP)
179
+ .digest("hex");
173
180
  const LINUX_NODE_ENTRY_SNAPSHOT_SCOPE = "plugin-entry-source";
174
181
  const LINUX_NATIVE_ENTRY_SNAPSHOT_SCOPE = "plugin-entry-executable";
175
182
  const LINUX_NODE_PLUGIN_TREE_SNAPSHOT_SCOPE = "all-pinned-plugin-regular-files";
@@ -283,6 +290,14 @@ const windowsAdapterCacheEntries = new Set();
283
290
  const windowsTemporaryCleanupBacklog = new Set();
284
291
  let windowsTemporaryCleanupRetryTimer = null;
285
292
  const windowsAppContainerCleanupBacklog = new Set();
293
+ const issuedWindowsMcpCodeSnapshotPlans = new WeakMap();
294
+ // Only the unified production adapter can register a Windows MCP launch
295
+ // capability. Direct callers of the exported platform-specific helper (and
296
+ // callers that inject a test/runtime facade into applySandbox) may exercise
297
+ // plan construction, but cannot mint a Broker-admissible capability.
298
+ const WINDOWS_MCP_CODE_SNAPSHOT_ISSUER = Symbol(
299
+ "windows-mcp-code-snapshot-issuer",
300
+ );
286
301
  // Each AppContainer retry starts a synchronous, digest-attested PowerShell
287
302
  // helper. Bound automatic retries so a permanently unsupported Windows host
288
303
  // cannot repeatedly block a long-lived CLI; explicit cleanup/reset and process
@@ -453,6 +468,8 @@ export function generateMacSeatbeltProfile(opts = {}, runtimeOverrides = {}) {
453
468
  allowNetwork = false,
454
469
  allowExec = true,
455
470
  } = opts;
471
+ const seatbeltLiteral = (value) =>
472
+ String(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
456
473
 
457
474
  const lines = [
458
475
  "(version 1)",
@@ -485,12 +502,12 @@ export function generateMacSeatbeltProfile(opts = {}, runtimeOverrides = {}) {
485
502
 
486
503
  // Allow read/write to specific paths
487
504
  for (const p of allowRead) {
488
- const abs = runtime.resolvePath(p);
505
+ const abs = seatbeltLiteral(runtime.resolvePath(p));
489
506
  lines.push(`(allow file-read* (subpath "${abs}"))`);
490
507
  }
491
508
 
492
509
  for (const p of allowWrite) {
493
- const abs = runtime.resolvePath(p);
510
+ const abs = seatbeltLiteral(runtime.resolvePath(p));
494
511
  lines.push(`(allow file-read* file-write* (subpath "${abs}"))`);
495
512
  }
496
513
 
@@ -511,6 +528,144 @@ export function generateMacSeatbeltProfile(opts = {}, runtimeOverrides = {}) {
511
528
  return lines.join("\n");
512
529
  }
513
530
 
531
+ function validateMacMcpCapsuleContract(
532
+ command,
533
+ args,
534
+ spawnOpts,
535
+ contract,
536
+ runtime,
537
+ sync,
538
+ ) {
539
+ if (
540
+ contract?.kind !== MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND ||
541
+ contract.contractVersion !== 1 ||
542
+ (sync !== true && sync !== false) ||
543
+ spawnOpts?.shell !== false ||
544
+ !linuxStdioIsNarrow(spawnOpts?.stdio) ||
545
+ spawnOpts?.serialization !== undefined ||
546
+ spawnOpts?.argv0 !== undefined ||
547
+ spawnOpts?.uid !== undefined ||
548
+ spawnOpts?.gid !== undefined ||
549
+ !Array.isArray(args) ||
550
+ args.length < 1 ||
551
+ args.some((value) => typeof value !== "string" || value.includes("\0")) ||
552
+ command !== contract.runtimePath ||
553
+ command !== contract.runtimeIdentity?.realPath ||
554
+ args[0] !== contract.entryIdentity?.realPath ||
555
+ ![".js", ".cjs", ".mjs"].includes(
556
+ path.posix.extname(contract.entryIdentity?.realPath || "").toLowerCase(),
557
+ )
558
+ ) {
559
+ return { ok: false, reason: "launch_identity_mismatch" };
560
+ }
561
+ for (const value of [
562
+ contract.pluginRoot,
563
+ contract.workingDirectory,
564
+ contract.rootIdentity?.realPath,
565
+ contract.entryIdentity?.realPath,
566
+ contract.runtimeIdentity?.realPath,
567
+ ]) {
568
+ if (
569
+ typeof value !== "string" ||
570
+ !path.posix.isAbsolute(value) ||
571
+ value.includes("\0")
572
+ ) {
573
+ return { ok: false, reason: "noncanonical_contract_path" };
574
+ }
575
+ }
576
+ try {
577
+ if (
578
+ linuxRealpath(runtime, contract.pluginRoot) !== contract.pluginRoot ||
579
+ linuxRealpath(runtime, contract.workingDirectory) !==
580
+ contract.workingDirectory ||
581
+ linuxRealpath(runtime, spawnOpts.cwd) !== contract.pluginRoot ||
582
+ contract.workingDirectory !== contract.pluginRoot ||
583
+ contract.rootIdentity?.realPath !== contract.pluginRoot ||
584
+ !linuxPathWithin(contract.pluginRoot, contract.entryIdentity.realPath)
585
+ ) {
586
+ return { ok: false, reason: "noncanonical_contract_path" };
587
+ }
588
+ } catch {
589
+ return { ok: false, reason: "contract_path_unavailable" };
590
+ }
591
+ if (
592
+ !linuxDirectoryIdentityMatches(runtime, contract.rootIdentity) ||
593
+ !linuxIdentityMatches(runtime, contract.runtimeIdentity, {
594
+ executable: true,
595
+ }) ||
596
+ !linuxIdentityMatches(runtime, contract.entryIdentity)
597
+ ) {
598
+ return { ok: false, reason: "execution_identity_changed" };
599
+ }
600
+ return { ok: true };
601
+ }
602
+
603
+ function applyMacMcpCapsuleCodeSnapshot(
604
+ command,
605
+ args,
606
+ spawnOpts,
607
+ sandboxOpts,
608
+ runtime,
609
+ base,
610
+ ) {
611
+ const contract = sandboxOpts.executionContract;
612
+ const validation = validateMacMcpCapsuleContract(
613
+ command,
614
+ args,
615
+ spawnOpts,
616
+ contract,
617
+ runtime,
618
+ sandboxOpts.sync,
619
+ );
620
+ const unavailable = (reason, runtimeProbe = null) =>
621
+ createSandboxPlan({
622
+ ...base,
623
+ backend: null,
624
+ candidateBackend: MACOS_MCP_CAPSULE_BACKEND,
625
+ policyAttested: false,
626
+ runtimeProbe: runtimeProbe
627
+ ? {
628
+ kind: "darwin-mcp-capsule-code-snapshot-v1",
629
+ attempted: runtimeProbe.attempted !== false,
630
+ probeRuntime: "node",
631
+ targetRuntime: "node",
632
+ ...runtimeProbe,
633
+ }
634
+ : null,
635
+ reason,
636
+ guarantees: [],
637
+ });
638
+ if (!validation.ok) {
639
+ return unavailable("macos_mcp_capsule_execution_contract_invalid", {
640
+ attempted: false,
641
+ runnable: false,
642
+ reason: validation.reason,
643
+ contentSnapshot: false,
644
+ handleAtomic: false,
645
+ entrySnapshotAtomic: false,
646
+ runtimeLaunchAtomic: false,
647
+ sharedLibraryClosure: false,
648
+ });
649
+ }
650
+
651
+ // Darwin exposes only pathname-based exec/spawn APIs to an unprivileged
652
+ // process. An inherited descriptor can bind the entry source, but public
653
+ // APIs cannot bind the verified Node runtime descriptor to the image that
654
+ // executes. Private temporary paths and Seatbelt still leave a same-UID
655
+ // pathname-replacement window, so they cannot satisfy CODE_SNAPSHOT.
656
+ return unavailable("macos_atomic_runtime_exec_unavailable", {
657
+ attempted: true,
658
+ runnable: false,
659
+ reason: "public_api_has_no_descriptor_bound_exec",
660
+ contentSnapshot: false,
661
+ handleAtomic: false,
662
+ entrySnapshotAtomic: false,
663
+ runtimeLaunchAtomic: false,
664
+ runtimeLaunchMechanism: "darwin-public-api-pathname-exec-only-v1",
665
+ sharedLibraryClosure: false,
666
+ });
667
+ }
668
+
514
669
  /**
515
670
  * Apply macOS sandbox via SBWritableProfile or sandbox-exec wrapper.
516
671
  *
@@ -552,6 +707,20 @@ export function applyMacSandbox(
552
707
  });
553
708
  }
554
709
 
710
+ if (
711
+ Array.isArray(sandboxOpts.requiredBoundaries) &&
712
+ sandboxOpts.requiredBoundaries.includes(SANDBOX_BOUNDARIES.CODE_SNAPSHOT)
713
+ ) {
714
+ return applyMacMcpCapsuleCodeSnapshot(
715
+ command,
716
+ args,
717
+ spawnOpts,
718
+ sandboxOpts,
719
+ runtime,
720
+ base,
721
+ );
722
+ }
723
+
555
724
  // A deny-by-default Seatbelt profile cannot safely infer the filesystem,
556
725
  // IPC, and inherited-descriptor access required by an arbitrary command.
557
726
  // Keep the boundary truthful for the broker's implicit default profile:
@@ -731,6 +900,218 @@ function sha256(value) {
731
900
  return crypto.createHash("sha256").update(value).digest("hex");
732
901
  }
733
902
 
903
+ function sameStringArray(left, right) {
904
+ return (
905
+ Array.isArray(left) &&
906
+ Array.isArray(right) &&
907
+ left.length === right.length &&
908
+ left.every((value, index) => value === right[index])
909
+ );
910
+ }
911
+
912
+ function captureWindowsStdio(stdio) {
913
+ if (Array.isArray(stdio)) return Object.freeze([...stdio]);
914
+ return stdio ?? null;
915
+ }
916
+
917
+ function sameWindowsStdio(left, right) {
918
+ const normalizedRight = right ?? null;
919
+ if (Array.isArray(left) || Array.isArray(normalizedRight)) {
920
+ return (
921
+ Array.isArray(left) &&
922
+ Array.isArray(normalizedRight) &&
923
+ left.length === normalizedRight.length &&
924
+ left.every((entry, index) => Object.is(entry, normalizedRight[index]))
925
+ );
926
+ }
927
+ return Object.is(left, normalizedRight);
928
+ }
929
+
930
+ function windowsStdioDigestContract(stdio) {
931
+ const normalizeEntry = (entry) => {
932
+ if (entry === null || entry === undefined) return ["null"];
933
+ if (typeof entry === "string") return ["string", entry];
934
+ if (Number.isInteger(entry)) return ["fd", entry];
935
+ return [typeof entry];
936
+ };
937
+ return Array.isArray(stdio)
938
+ ? ["array", ...stdio.map(normalizeEntry)]
939
+ : ["scalar", ...normalizeEntry(stdio)];
940
+ }
941
+
942
+ function windowsEnvironmentDigest(env) {
943
+ const entries = Object.entries(env || {})
944
+ .map(([key, value]) => [key, String(value)])
945
+ .sort(([leftKey, leftValue], [rightKey, rightValue]) => {
946
+ if (leftKey !== rightKey) return leftKey < rightKey ? -1 : 1;
947
+ if (leftValue === rightValue) return 0;
948
+ return leftValue < rightValue ? -1 : 1;
949
+ });
950
+ return sha256(JSON.stringify(entries));
951
+ }
952
+
953
+ function windowsMcpBindingIdentity(identity) {
954
+ if (!identity) return null;
955
+ return {
956
+ contractVersion: identity.contractVersion ?? null,
957
+ realPath: identity.realPath ?? null,
958
+ sha256: identity.sha256 ?? null,
959
+ bytes: identity.bytes ?? null,
960
+ fileId: identity.fileId
961
+ ? {
962
+ dev: identity.fileId.dev ?? null,
963
+ ino: identity.fileId.ino ?? null,
964
+ }
965
+ : null,
966
+ mtimeMs: identity.mtimeMs ?? null,
967
+ attestation: identity.attestation ?? null,
968
+ };
969
+ }
970
+
971
+ function windowsMcpBindingContract(contract) {
972
+ return {
973
+ contractVersion: contract?.contractVersion ?? null,
974
+ kind: contract?.kind ?? null,
975
+ pluginRoot: contract?.pluginRoot ?? null,
976
+ workingDirectory: contract?.workingDirectory ?? null,
977
+ runtimePath: contract?.runtimePath ?? null,
978
+ rootIdentity: contract?.rootIdentity
979
+ ? {
980
+ realPath: contract.rootIdentity.realPath ?? null,
981
+ fileId: contract.rootIdentity.fileId
982
+ ? {
983
+ dev: contract.rootIdentity.fileId.dev ?? null,
984
+ ino: contract.rootIdentity.fileId.ino ?? null,
985
+ }
986
+ : null,
987
+ attestation: contract.rootIdentity.attestation ?? null,
988
+ }
989
+ : null,
990
+ entryIdentity: windowsMcpBindingIdentity(contract?.entryIdentity),
991
+ runtimeIdentity: windowsMcpBindingIdentity(contract?.runtimeIdentity),
992
+ };
993
+ }
994
+
995
+ function createWindowsMcpCodeSnapshotPlanBinding({
996
+ executionContract,
997
+ command,
998
+ args,
999
+ spawnOpts,
1000
+ profile,
1001
+ requiredBoundaries,
1002
+ sync,
1003
+ backend,
1004
+ policyAttested,
1005
+ policyDigest,
1006
+ adapterSource,
1007
+ helperInvocation,
1008
+ helperOptions,
1009
+ postSpawn,
1010
+ postSpawnWindows,
1011
+ }) {
1012
+ const helperEnvDigest = windowsEnvironmentDigest(helperOptions.env);
1013
+ const helperStdio = captureWindowsStdio(helperOptions.stdio);
1014
+ const originalArgs = Object.freeze([...(args || [])]);
1015
+ const helperArgs = Object.freeze([...(helperInvocation.args || [])]);
1016
+ const normalizedPostSpawn = Object.freeze({
1017
+ required: postSpawn?.required === true,
1018
+ mode: postSpawn?.mode || "none",
1019
+ });
1020
+ const digestPayload = {
1021
+ version: 1,
1022
+ kind: "windows-mcp-code-snapshot-plan-binding-v1",
1023
+ executionContract: windowsMcpBindingContract(executionContract),
1024
+ originalLaunch: {
1025
+ command,
1026
+ args: originalArgs,
1027
+ cwd: spawnOpts?.cwd ?? null,
1028
+ shell: spawnOpts?.shell ?? null,
1029
+ detached: spawnOpts?.detached ?? null,
1030
+ profile,
1031
+ requiredBoundaries: [...requiredBoundaries],
1032
+ sync,
1033
+ },
1034
+ policy: { backend, policyAttested, policyDigest },
1035
+ adapter: {
1036
+ loaderMode: adapterSource.loaderMode,
1037
+ sourceDigest: adapterSource.sourceDigest,
1038
+ sourceContractDigest: adapterSource.sourceContractDigest,
1039
+ },
1040
+ helperInvocation: {
1041
+ command: helperInvocation.command,
1042
+ args: helperArgs,
1043
+ cwd: helperOptions.cwd ?? null,
1044
+ shell: helperOptions.shell ?? null,
1045
+ detached: helperOptions.detached ?? null,
1046
+ envDigest: helperEnvDigest,
1047
+ stdio: windowsStdioDigestContract(helperStdio),
1048
+ },
1049
+ postSpawn: normalizedPostSpawn,
1050
+ };
1051
+ return Object.freeze({
1052
+ executionContract,
1053
+ originalCommand: command,
1054
+ originalArgs,
1055
+ originalCwd: spawnOpts?.cwd ?? null,
1056
+ originalShell: spawnOpts?.shell ?? null,
1057
+ originalDetached: spawnOpts?.detached ?? null,
1058
+ profile,
1059
+ requiredBoundaries: Object.freeze([...requiredBoundaries]),
1060
+ sync,
1061
+ backend,
1062
+ policyAttested,
1063
+ policyDigest,
1064
+ helperCommand: helperInvocation.command,
1065
+ helperArgs,
1066
+ helperCwd: helperOptions.cwd ?? null,
1067
+ helperShell: helperOptions.shell ?? null,
1068
+ helperDetached: helperOptions.detached ?? null,
1069
+ helperEnvDigest,
1070
+ helperStdio,
1071
+ postSpawn: normalizedPostSpawn,
1072
+ postSpawnWindows: postSpawnWindows || null,
1073
+ planBindingDigest: sha256(JSON.stringify(digestPayload)),
1074
+ });
1075
+ }
1076
+
1077
+ /**
1078
+ * Consume the one-launch capability attached to a real built-in Windows MCP
1079
+ * code-snapshot plan. The issuer stays module-private so an injected adapter
1080
+ * cannot make a structurally similar helper payload authoritative.
1081
+ */
1082
+ export function consumeWindowsMcpCodeSnapshotPlanBinding(plan, expected = {}) {
1083
+ const issued = issuedWindowsMcpCodeSnapshotPlans.get(plan);
1084
+ if (!issued) return false;
1085
+ issuedWindowsMcpCodeSnapshotPlans.delete(plan);
1086
+ return (
1087
+ issued.executionContract === expected.executionContract &&
1088
+ issued.originalCommand === expected.command &&
1089
+ sameStringArray(issued.originalArgs, expected.args) &&
1090
+ issued.originalCwd === (expected.cwd ?? null) &&
1091
+ issued.originalShell === (expected.shell ?? null) &&
1092
+ issued.originalDetached === (expected.detached ?? null) &&
1093
+ issued.profile === expected.profile &&
1094
+ sameStringArray(issued.requiredBoundaries, expected.requiredBoundaries) &&
1095
+ issued.sync === (expected.sync === true) &&
1096
+ plan.backend === issued.backend &&
1097
+ plan.policyAttested === issued.policyAttested &&
1098
+ plan.policyDigest === issued.policyDigest &&
1099
+ plan.command === issued.helperCommand &&
1100
+ sameStringArray(plan.args, issued.helperArgs) &&
1101
+ plan.options?.cwd === issued.helperCwd &&
1102
+ plan.options?.shell === issued.helperShell &&
1103
+ plan.options?.detached === issued.helperDetached &&
1104
+ windowsEnvironmentDigest(plan.options?.env) === issued.helperEnvDigest &&
1105
+ sameWindowsStdio(issued.helperStdio, plan.options?.stdio) &&
1106
+ plan.postSpawn?.required === issued.postSpawn.required &&
1107
+ plan.postSpawn?.mode === issued.postSpawn.mode &&
1108
+ (plan.postSpawnWindows || null) === issued.postSpawnWindows &&
1109
+ plan.runtimeProbe?.planBindingMechanism ===
1110
+ "windows-mcp-code-snapshot-plan-binding-v1" &&
1111
+ plan.runtimeProbe?.planBindingDigest === issued.planBindingDigest
1112
+ );
1113
+ }
1114
+
734
1115
  function windowsFileIdentity(stat) {
735
1116
  const timestamp = (nanosecondsKey, millisecondsKey) => {
736
1117
  if (stat[nanosecondsKey] !== undefined) {
@@ -2077,6 +2458,7 @@ export function applyWindowsSandbox(
2077
2458
  spawnOpts,
2078
2459
  sandboxOpts = {},
2079
2460
  runtimeOverrides = {},
2461
+ planBindingAuthority = null,
2080
2462
  ) {
2081
2463
  let runtime = resolveRuntime(runtimeOverrides);
2082
2464
  const requiredBoundaries = Array.isArray(sandboxOpts.requiredBoundaries)
@@ -2097,6 +2479,10 @@ export function applyWindowsSandbox(
2097
2479
  SANDBOX_BOUNDARIES.RESOURCE_LIMITS,
2098
2480
  SANDBOX_BOUNDARIES.PRIVILEGE_REDUCTION,
2099
2481
  ];
2482
+ const appContainerSupportedBoundaries = [
2483
+ ...appContainerGuarantees,
2484
+ SANDBOX_BOUNDARIES.CODE_SNAPSHOT,
2485
+ ];
2100
2486
  const base = {
2101
2487
  platform: runtime.platform,
2102
2488
  profile: sandboxOpts.profileName || "default",
@@ -2143,7 +2529,7 @@ export function applyWindowsSandbox(
2143
2529
  if (
2144
2530
  requiresAppContainer &&
2145
2531
  requiredBoundaries.some(
2146
- (boundary) => !appContainerGuarantees.includes(boundary),
2532
+ (boundary) => !appContainerSupportedBoundaries.includes(boundary),
2147
2533
  )
2148
2534
  ) {
2149
2535
  return unavailablePlan("windows_appcontainer_boundary_unsupported");
@@ -2503,10 +2889,14 @@ export function applyWindowsSandbox(
2503
2889
  detached: false,
2504
2890
  shell: false,
2505
2891
  cwd: helperWorkingDirectory,
2506
- env: hostEnvironment,
2892
+ env: Object.freeze({ ...hostEnvironment }),
2893
+ stdio: Array.isArray(invocation.options.stdio)
2894
+ ? Object.freeze([...invocation.options.stdio])
2895
+ : invocation.options.stdio,
2507
2896
  };
2508
2897
  let appContainerCleanupVerified = false;
2509
2898
  let appContainerCleanupRecord = null;
2899
+ let issuedWindowsMcpPlan = null;
2510
2900
  const cleanupAppContainer = () => {
2511
2901
  if (!appContainer || appContainerCleanupVerified) return true;
2512
2902
  if (appContainerCleanupRecord) {
@@ -2544,6 +2934,10 @@ export function applyWindowsSandbox(
2544
2934
  return false;
2545
2935
  };
2546
2936
  const cleanup = () => {
2937
+ if (issuedWindowsMcpPlan) {
2938
+ issuedWindowsMcpCodeSnapshotPlans.delete(issuedWindowsMcpPlan);
2939
+ issuedWindowsMcpPlan = null;
2940
+ }
2547
2941
  const failures = [];
2548
2942
  const attempt = (label, action) => {
2549
2943
  try {
@@ -2604,6 +2998,28 @@ export function applyWindowsSandbox(
2604
2998
  },
2605
2999
  }
2606
3000
  : {};
3001
+ const windowsMcpPlanBinding =
3002
+ entrySnapshot.locks &&
3003
+ sandboxOpts.executionContract?.kind ===
3004
+ MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND
3005
+ ? createWindowsMcpCodeSnapshotPlanBinding({
3006
+ executionContract: sandboxOpts.executionContract,
3007
+ command,
3008
+ args,
3009
+ spawnOpts,
3010
+ profile,
3011
+ requiredBoundaries,
3012
+ sync: sandboxOpts.sync === true,
3013
+ backend,
3014
+ policyAttested: requiresAppContainer ? true : null,
3015
+ policyDigest: appContainerPolicyDigest,
3016
+ adapterSource,
3017
+ helperInvocation,
3018
+ helperOptions: options,
3019
+ postSpawn: identityContract.postSpawn,
3020
+ postSpawnWindows: identityContract.postSpawnWindows,
3021
+ })
3022
+ : null;
2607
3023
  const entrySnapshotRuntimeProbe = entrySnapshot.locks
2608
3024
  ? {
2609
3025
  ...(appContainerRuntimeProbe || nodeSnapshotRuntimeProbe),
@@ -2636,11 +3052,13 @@ export function applyWindowsSandbox(
2636
3052
  runtimeLaunchMechanism:
2637
3053
  "filter-oplock-locked-createprocess-suspended-image-v1",
2638
3054
  sharedLibraryClosure: false,
3055
+ planBindingMechanism: "windows-mcp-code-snapshot-plan-binding-v1",
3056
+ planBindingDigest: windowsMcpPlanBinding.planBindingDigest,
2639
3057
  }
2640
3058
  : {}),
2641
3059
  }
2642
3060
  : appContainerRuntimeProbe;
2643
- return createSandboxPlan({
3061
+ const plan = createSandboxPlan({
2644
3062
  ...base,
2645
3063
  applied: true,
2646
3064
  enforcement: backend,
@@ -2667,6 +3085,14 @@ export function applyWindowsSandbox(
2667
3085
  ...identityContract,
2668
3086
  cleanup,
2669
3087
  });
3088
+ if (
3089
+ windowsMcpPlanBinding &&
3090
+ planBindingAuthority === WINDOWS_MCP_CODE_SNAPSHOT_ISSUER
3091
+ ) {
3092
+ issuedWindowsMcpPlan = plan;
3093
+ issuedWindowsMcpCodeSnapshotPlans.set(plan, windowsMcpPlanBinding);
3094
+ }
3095
+ return plan;
2670
3096
  }
2671
3097
 
2672
3098
  /**
@@ -3829,7 +4255,6 @@ function applyLinuxMcpCapsuleCodeSnapshot(
3829
4255
  ]);
3830
4256
  const descriptors = [runtimeSnapshot.finalMount, entrySnapshot.finalMount];
3831
4257
  const runtimeFd = 3;
3832
- const entryFd = 4;
3833
4258
  const snapshotIdentity = Object.freeze({
3834
4259
  runtimeSnapshotSha256: runtimeSnapshot.attestation.sha256,
3835
4260
  runtimeSnapshotBytes: runtimeSnapshot.attestation.bytes,
@@ -3846,6 +4271,8 @@ function applyLinuxMcpCapsuleCodeSnapshot(
3846
4271
  ].sort(),
3847
4272
  identity: snapshotIdentity,
3848
4273
  cwd: invocation.options.cwd,
4274
+ entrySnapshotBootstrapSha256: MCP_STDIO_FD_ENTRY_BOOTSTRAP_SHA256,
4275
+ runtimeLaunchMechanism: "inherited-executable-fd-v1",
3849
4276
  passthroughArgsDigest: sha256(JSON.stringify(invocation.args.slice(1))),
3850
4277
  }),
3851
4278
  );
@@ -3874,13 +4301,22 @@ function applyLinuxMcpCapsuleCodeSnapshot(
3874
4301
  contentSnapshotScope: "mcp-capsule-entry-and-node-runtime",
3875
4302
  contentSnapshotMechanism: LINUX_MCP_CAPSULE_SNAPSHOT_MECHANISM,
3876
4303
  handleAtomic: true,
4304
+ entrySnapshotAtomic: true,
4305
+ runtimeLaunchAtomic: true,
4306
+ runtimeLaunchMechanism: "inherited-executable-fd-v1",
4307
+ entrySnapshotBootstrapSha256: MCP_STDIO_FD_ENTRY_BOOTSTRAP_SHA256,
3877
4308
  sharedLibraryClosure: false,
3878
4309
  ...snapshotIdentity,
3879
4310
  },
3880
4311
  reason: null,
3881
4312
  guarantees: [SANDBOX_BOUNDARIES.CODE_SNAPSHOT],
3882
4313
  command: `/proc/self/fd/${runtimeFd}`,
3883
- args: [`/proc/self/fd/${entryFd}`, ...invocation.args.slice(1)],
4314
+ args: [
4315
+ "-e",
4316
+ MCP_STDIO_FD_ENTRY_BOOTSTRAP,
4317
+ "--",
4318
+ ...invocation.args.slice(1),
4319
+ ],
3884
4320
  options: {
3885
4321
  ...invocation.options,
3886
4322
  shell: false,
@@ -5707,7 +6143,10 @@ export function applyLinuxSandbox(
5707
6143
  boundary === SANDBOX_BOUNDARIES.PROCESS_TREE,
5708
6144
  );
5709
6145
 
5710
- if (requiredBoundaries.includes(SANDBOX_BOUNDARIES.CODE_SNAPSHOT)) {
6146
+ if (
6147
+ requiredBoundaries.includes(SANDBOX_BOUNDARIES.CODE_SNAPSHOT) &&
6148
+ !requiresStrongLinuxBoundary
6149
+ ) {
5711
6150
  return applyLinuxMcpCapsuleCodeSnapshot(
5712
6151
  command,
5713
6152
  args,
@@ -6369,17 +6808,36 @@ export function applyLinuxSandbox(
6369
6808
  const supervisorBinding = supervisorPin.attestation;
6370
6809
  closeLinuxPinnedMounts(runtime, [supervisorPin]);
6371
6810
  supervisorPin = null;
6811
+ const capsuleContract =
6812
+ validation.contract.kind === MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND;
6813
+ const baseRuntimeProbe = linuxBubblewrapProbe(
6814
+ true,
6815
+ true,
6816
+ null,
6817
+ validation.entryRuntime,
6818
+ entrySnapshot?.attestation,
6819
+ supervisorBinding,
6820
+ pluginTreeSnapshot,
6821
+ nativeDynamicClosure,
6822
+ );
6372
6823
  const runtimeProbe = Object.freeze(
6373
- linuxBubblewrapProbe(
6374
- true,
6375
- true,
6376
- null,
6377
- validation.entryRuntime,
6378
- entrySnapshot?.attestation,
6379
- supervisorBinding,
6380
- pluginTreeSnapshot,
6381
- nativeDynamicClosure,
6382
- ),
6824
+ capsuleContract
6825
+ ? {
6826
+ ...baseRuntimeProbe,
6827
+ mcpCapsuleCodeSnapshot: true,
6828
+ entrySnapshotAtomic: true,
6829
+ runtimeLaunchAtomic: true,
6830
+ runtimeLaunchMechanism:
6831
+ "bwrap-descriptor-mount-node-runtime-exec-v1",
6832
+ sharedLibraryClosure: false,
6833
+ runtimeSnapshotSha256: validation.contract.runtimeIdentity.sha256,
6834
+ runtimeSnapshotBytes: validation.contract.runtimeIdentity.bytes,
6835
+ entrySnapshotSha256: entrySnapshot.attestation.sha256,
6836
+ entrySnapshotBytes: entrySnapshot.attestation.bytes,
6837
+ runtimeLaunchPath: "/opt/chainless/runtime/node",
6838
+ entrySnapshotPath: sandboxEntry,
6839
+ }
6840
+ : baseRuntimeProbe,
6383
6841
  );
6384
6842
  const options = {
6385
6843
  ...spawnOpts,
@@ -6417,6 +6875,7 @@ export function applyLinuxSandbox(
6417
6875
  SANDBOX_BOUNDARIES.FILESYSTEM,
6418
6876
  SANDBOX_BOUNDARIES.NETWORK,
6419
6877
  SANDBOX_BOUNDARIES.PROCESS_TREE,
6878
+ ...(capsuleContract ? [SANDBOX_BOUNDARIES.CODE_SNAPSHOT] : []),
6420
6879
  ],
6421
6880
  command: finalLaunch.command,
6422
6881
  args: [...policyArgs, "--", ...targetArgs],
@@ -6492,9 +6951,10 @@ export function applySandbox(
6492
6951
  args,
6493
6952
  spawnOpts,
6494
6953
  profileOrRequest = "default",
6495
- runtimeOverrides = {},
6954
+ runtimeOverrides = undefined,
6496
6955
  explicitRequest = null,
6497
6956
  ) {
6957
+ const runtimeInjected = runtimeOverrides !== undefined;
6498
6958
  const runtime = resolveRuntime(runtimeOverrides);
6499
6959
  const sandboxRequest = normalizeSandboxRequest(
6500
6960
  profileOrRequest,
@@ -6558,6 +7018,7 @@ export function applySandbox(
6558
7018
  spawnOpts,
6559
7019
  profile,
6560
7020
  runtimeOverrides,
7021
+ runtimeInjected ? null : WINDOWS_MCP_CODE_SNAPSHOT_ISSUER,
6561
7022
  );
6562
7023
  }
6563
7024
  if (runtime.platform === "linux") {
@@ -3540,10 +3540,11 @@ namespace ChainlessChain.WindowsSandbox
3540
3540
  ThrowLastError("AssignProcessToJobObject");
3541
3541
  }
3542
3542
  ReattestLaunchPaths(launchPathLocks);
3543
- // The suspended process has already created its image section.
3544
- // Release all remaining runtime stream guards before resume so
3545
- // target code can never deadlock waiting for a break owned by
3546
- // the helper. This is not a pathname-atomic runtime launch.
3543
+ // The suspended process has already created its image section
3544
+ // while the attested pathname remained protected by its Filter
3545
+ // oplock. Reattestation above completes the pathname-to-image
3546
+ // atomic handoff; release the stream guards before resume so
3547
+ // target code cannot deadlock on a break owned by the helper.
3547
3548
  ReleaseLaunchPathLocks(launchPathLocks);
3548
3549
  if (ResumeThread(processInfo.hThread) == UInt32.MaxValue)
3549
3550
  {