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.
- package/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-Cn7quRgL.js → AIOps-DnGsmsqJ.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-YqMX3ueH.js → ActionButton-CrO6fcQ7.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bxmy1b7Y.js → Analytics-DsBdOaP2.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DBOw69jE.js → AppLayout-DmQslKUB.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-mq1nyzN1.js → Artifacts-BvyrT_QQ.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-mMiKtZ0D.js → Audit-prndoLiC.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-WBUjpYVh.js → BackgroundAgents-DOTFyA55.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-c25OoJgs.js → Backup-9zOnPp_8.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BbfWhZ4-.js → BaseInput-C4PC6sAG.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CVVzsTwU.js → Chat-BBAF-W9v.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CVCjZJ04.js → ChatBubbleRenderer-CWhvvloO.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C9o2HK-1.js → Checkbox-BI9iculd.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B7X5LfKc.js → Codegen-3DP9BCKb.js} +1 -1
- package/src/assets/web-panel/assets/{Col-jpPj2Pur.js → Col-df-2TnJX.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Dti6bHxN.js → Community-CHs8gG_A.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-S4ZsLt3W.js → Compact-CDfF6q7V.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Bge0sQ3O.js → Compliance-CthrDnO7.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-C4XyzVI7.js → Cowork-HjIqsWJw.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CPR0v2xy.js → Cron-BKc196fb.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DAX8lDaj.js → Crosschain-CJnjdc8W.js} +1 -1
- package/src/assets/web-panel/assets/{DID-fBHPa0QH.js → DID-BHUy-8Q2.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-vvaUTafU.js → Dashboard-QDB7sKeY.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DyaQM63v.js → Dropdown-DStcVK11.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CAF0wiU2.js → EmailListRenderer-BwSUskMJ.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-ia-WzDRs.js → FamilyGuardDashboard-DgF_kurT.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Cz3gHoT5.js → Federation-k8wvv-wN.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CJQDJr4Q.js → FormItemContext-C11qoq2r.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-B05BZlQp.js → GenericCardRenderer-BIIpr9kg.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DT0YcQnI.js → Git-BlA1exTe.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Bqbl6m5Q.js → Governance-CYa1ZYM4.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BdebLR0N.js → Inference-6_kKVIt6.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-M36b8YYV.js → KnowledgeGraph-CB4AwxYy.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-5LN_XL43.js → Logs-xf7nHFAe.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-Bf3DEqP6.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BkIin-QY.js → Marketplace-aPg8e4Jt.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Bkppx8Uj.js → McpTools-C-TNlVUf.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-Qk9wg_Ib.js → Memory-DMTPIpGa.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BsTDU3Aj.js → MobileBridge-BxyvveRq.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CrZW5I28.js → MobileProjects-DyPCrAyQ.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BMkmgtsA.js → Mtc-BdhqNXp6.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-6m4CC0Yn.js → MtcAudit-Cz-HFxzW.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-BZ8yB7QV.js → Multisig-CIUaFNsx.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CxitAMIO.js → NLProgramming-CWe6-J17.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Bv0msnHu.js → Notes-vYAKeviU.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-DeVMqM3P.js → NotificationSettings-DQL9-2d7.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CXBSWa3R.js → OrderTableRenderer-DnXj1jBn.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-b_G5Vs1Q.js → Organization-B3spU8AN.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DW7riOmA.js → Overflow-DgEwo7vm.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CtpQNYjL.js → P2P-hujMRH8X.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Ba63yT4l.js → PdhVaultBrowser-C_qhdg9h.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DnzyeB67.js → Permissions-vp7LMcSf.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DbPZ7HWw.js → PersonalDataHub-Dxr5Hgnq.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-gs_HOThJ.js → Pipeline-DEPZqqH4.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CZlQ1EjE.js → Privacy-DTpDiKPe.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DQp__Ccb.js → ProjectInit-jDJsRWmF.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-C7h2sOWZ.js → ProjectSettings-Dhor5RWH.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DdCpNRNt.js → Projects-08xUDZGt.js} +1 -1
- package/src/assets/web-panel/assets/Providers-BGs47s1a.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-B_8M1-FC.js → QrScannerModal-CjIw-wIb.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Bpycr8WD.js → QuickAsk-DX6jcqoi.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Z4TrcNzs.js → Recommend-DopXkhar.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BD6TsJlS.js → RemoteSession-BLvqJE9c.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-IKxDXHEu.js → Reputation-DhRj2Me7.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DbmR20tJ.js → Row-DQ53vuPq.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CLjA5PPf.js → RssFeed-BslvwiBD.js} +2 -2
- package/src/assets/web-panel/assets/{Search-Bm3owbIU.js → Search-DJKBDNKZ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CY4RyOuq.js → Security-COhpxHER.js} +3 -3
- package/src/assets/web-panel/assets/{Services-CYO9qrd_.js → Services-dbulD6cI.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-ClF51Go6.js → Skeleton-ciIVNfhC.js} +1 -1
- package/src/assets/web-panel/assets/Skills-AiRTkTCk.js +1 -0
- package/src/assets/web-panel/assets/{Sla-zqpDUxzP.js → Sla-DDMcWYBc.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DPSi8Qco.js → SpeechSettings-BPxWbpXO.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CqABopsQ.js → SyncSettings-BoEOXCyg.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-4dbAJng4.js → Tasks-CEYFJwmr.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Dzl6f0M2.js → Templates-UowY8Ixe.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-XeZkw40a.js → Tenant-DauSLQXN.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CYw2YzPm.js → Terminal-DBj7Jneq.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Bc2pko4i.js → TimelineRenderer-UMrPwoZC.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CfCenOHx.js → Tokens-4ea96-bn.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DTz-_YqV.js → Trigger--ISCqt4b.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CB3tt3Z6.js → Trust-D4GVimRJ.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-y1ykmMvU.js → UkeySign-Ci-nXRQc.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-UlZ_lX0e.js → VideoEditing-Cjk7mKPw.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DMBaHTha.js → Wallet-BgOLOO3Z.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Cksm-hBI.js → WebAuthn-CCX0K29i.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BhOa40sX.js → WorkflowEditor-Ch3zgIsE.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DNbeSTDO.js → chat-DKOU_2Vb.js} +1 -1
- package/src/assets/web-panel/assets/{colors-9zz8gBmW.js → colors-6OVo4u3C.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-D7aoVv-5.js → compact-item-BH78Hlsq.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DYg7B8nd.js → createContext-CFRpSbbC.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DEMblAIm.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BNbhkcoI.js → hasIn-DNQhgcVi.js} +1 -1
- package/src/assets/web-panel/assets/{index-gNKj00Fx.js → index--rq90rL9.js} +1 -1
- package/src/assets/web-panel/assets/{index-FlBuITVG.js → index-7TC3S8SN.js} +1 -1
- package/src/assets/web-panel/assets/{index-nnmo3ipi.js → index-AuBhLqOm.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dn-JFqEi.js → index-BDSR7ecX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUWmZ059.js → index-BHa4WyTZ.js} +1 -1
- package/src/assets/web-panel/assets/index-BTvq-36D.js +1 -0
- package/src/assets/web-panel/assets/{index--TvoQ6UC.js → index-BYrnm5Ob.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpEIwp4A.js → index-B_Z-YoxX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnTM8FWK.js → index-BaVE6E8y.js} +3 -3
- package/src/assets/web-panel/assets/{index-67GdrUx2.js → index-Bb6kDrUx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPojutcZ.js → index-BepBTpa8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CV06YdPO.js → index-BkN3iTTp.js} +1 -1
- package/src/assets/web-panel/assets/{index-CN6-OEgS.js → index-BnnXQot_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHskwmwI.js → index-BujsOZfc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9zUawcE.js → index-BxRy5LPR.js} +1 -1
- package/src/assets/web-panel/assets/{index-C8LC0nvw.js → index-CFPJ8yzF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMrqEsOS.js → index-CNuCHHQT.js} +1 -1
- package/src/assets/web-panel/assets/{index-Da0SysnX.js → index-CaYqY35Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cq3l0L7C.js → index-CkNEMANR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIljkSt9.js → index-CkqHgG-b.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYu-F-gp.js → index-CrcLHN2F.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtQzs0hH.js → index-Cu3L4r5l.js} +1 -1
- package/src/assets/web-panel/assets/{index-SmEIFaRm.js → index-D3RtTT4K.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZPDbEh-L.js → index-D84id2Y4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzDDeZBo.js → index-DKN2noIF.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bdxe0nrD.js → index-DaDgdJYj.js} +1 -1
- package/src/assets/web-panel/assets/{index-uc8Rz96X.js → index-Du0rnksC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cqy-hqD9.js → index-DvHGtNnF.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9TzVW7i.js → index-Eag8e_mA.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRd1zkLB.js → index-HNGGVF6o.js} +1 -1
- package/src/assets/web-panel/assets/{index-jS6NASar.js → index-Y9MJv28e.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIMVe3HJ.js → index-bKm3TUDp.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8irlIUK.js → index-caye7AOE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRKukX1W.js → index-cdf7fd7d.js} +1 -1
- package/src/assets/web-panel/assets/{index-DeD1wWA8.js → index-dDkoL4Pe.js} +1 -1
- package/src/assets/web-panel/assets/{index-CA72qB1n.js → index-hPY0fFrd.js} +1 -1
- package/src/assets/web-panel/assets/index-hUpvk6Jl.js +1 -0
- package/src/assets/web-panel/assets/{index-_-Vt1Wqk.js → index-nbfHl1oV.js} +1 -1
- package/src/assets/web-panel/assets/{index-m2pXS3W2.js → index-sm7W8AXy.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-D0mTMUGz.js → initDefaultProps-BZ9w6jPL.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DK16p4-o.js → motion-BnwUiOho.js} +1 -1
- package/src/assets/web-panel/assets/{move-DalC20HC.js → move-ByUKJnNm.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B5RusszF.js → mtc-parser-V7yK1KEl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-C9Mhitht.js → omit-BEXBBt4j.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-51xQLgwM.js → pickAttrs-qDm_46Gi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CJzIqp8u.js → placementArrow-BIbhEo_0.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-HQvC19u4.js → responsiveObserve-NbPbDgA_.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C6hhabOp.js → slide-BnUWglZ0.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Q1r48-oc.js → statusUtils-BX8_wZI5.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-UakVWrHs.js → styleChecker-BV4OycQX.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Dmv94cxx.js → useFlexGapSupport-Od_H5llY.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DrxOnt_V.js → useFs-BWI-PyiX.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BVf2M-Hg.js → usePersonalDataHub-BqMuhG3g.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BzzW9qKH.js → vnode-DNd23z6f.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-C1ZvMgAZ.js → zoom-Cjaxnm7l.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/mcp.js +29 -1
- package/src/data/changelog.json +15 -2
- package/src/harness/mcp-client.js +15 -2
- package/src/lib/cowork-mcp-tools.js +1 -0
- package/src/lib/cowork-task-templates.js +1 -0
- package/src/lib/mcp-stdio-executable-identity.js +75 -11
- package/src/lib/mcp-stdio-execution-authority.js +5 -0
- package/src/lib/process-execution-broker/index.js +316 -22
- package/src/lib/process-execution-broker/platform-sandbox.js +481 -20
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +5 -4
- package/src/lib/skill-mcp.js +10 -0
- package/src/runtime/mcp-config.js +3 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-BCb1Dm8l.js +0 -1
- package/src/assets/web-panel/assets/Providers-CyvtUkUf.js +0 -1
- package/src/assets/web-panel/assets/Skills-CCCEmSf5.js +0 -1
- package/src/assets/web-panel/assets/devWarning-uadaGF_y.js +0 -1
- package/src/assets/web-panel/assets/index-C7zhie9M.js +0 -1
- 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-
|
|
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) => !
|
|
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
|
-
|
|
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: [
|
|
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 (
|
|
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
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
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") {
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
-
//
|
|
3545
|
-
//
|
|
3546
|
-
//
|
|
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
|
{
|