chainlesschain 0.163.1 → 0.163.3
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-DIY6KxV-.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-YqMX3ueH.js → ActionButton-BXH0muPt.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bxmy1b7Y.js → Analytics-D39w8vmg.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-DBOw69jE.js → AppLayout-CUU1zvLs.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-mq1nyzN1.js → Artifacts-D8azHO3T.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-mMiKtZ0D.js → Audit-D0tAwXTg.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-WBUjpYVh.js → BackgroundAgents-C29mhJll.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-c25OoJgs.js → Backup-D6Aa1Gro.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BbfWhZ4-.js → BaseInput-B1uoHbPQ.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CVVzsTwU.js → Chat-Bs4DLOR5.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CVCjZJ04.js → ChatBubbleRenderer-DUYIBSle.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C9o2HK-1.js → Checkbox-CNcBPEa4.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B7X5LfKc.js → Codegen-CIY89763.js} +1 -1
- package/src/assets/web-panel/assets/{Col-jpPj2Pur.js → Col-CsPYFmgo.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Dti6bHxN.js → Community-BBocEge4.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-S4ZsLt3W.js → Compact-TQ8Ux0Lf.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Bge0sQ3O.js → Compliance-DfBsZTft.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-C4XyzVI7.js → Cowork-Cg-I6FVH.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-CPR0v2xy.js → Cron-DTQzfRTp.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DAX8lDaj.js → Crosschain-DGxEKGpR.js} +1 -1
- package/src/assets/web-panel/assets/{DID-fBHPa0QH.js → DID-DLZ1RDSr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-vvaUTafU.js → Dashboard-XneICKNI.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DyaQM63v.js → Dropdown-BRU00J1-.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CAF0wiU2.js → EmailListRenderer-BzCbJuAy.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-ia-WzDRs.js → FamilyGuardDashboard-D7BRyNBG.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Cz3gHoT5.js → Federation-D9DeFIhW.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CJQDJr4Q.js → FormItemContext-6rAtA9Ko.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-B05BZlQp.js → GenericCardRenderer-8Hqy80pU.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DT0YcQnI.js → Git-Cmvkj1rt.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Bqbl6m5Q.js → Governance-BRiQUjjw.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BdebLR0N.js → Inference-CKN_EzVf.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-M36b8YYV.js → KnowledgeGraph-BCDHwpwQ.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-5LN_XL43.js → Logs-DK9ovhaB.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BCb1Dm8l.js → MarkdownRenderer-D53pHiHy.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BkIin-QY.js → Marketplace-BILPGakp.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Bkppx8Uj.js → McpTools-DTVCOr9-.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-Qk9wg_Ib.js → Memory-Hzc1iow4.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BsTDU3Aj.js → MobileBridge-GXfgnGYV.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CrZW5I28.js → MobileProjects-B-3TJWsS.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BMkmgtsA.js → Mtc-DwSJMWtK.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-6m4CC0Yn.js → MtcAudit-D2uxf-DA.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BZ8yB7QV.js → Multisig-DG6kbKK0.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CxitAMIO.js → NLProgramming-f5p49EDU.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Bv0msnHu.js → Notes-FUgHyzSD.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-DeVMqM3P.js → NotificationSettings-DCHGee7e.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CXBSWa3R.js → OrderTableRenderer-Dm6LlIoa.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-b_G5Vs1Q.js → Organization-BawA7qAg.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DW7riOmA.js → Overflow-D6a5wZU1.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CtpQNYjL.js → P2P-K8WavwnA.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Ba63yT4l.js → PdhVaultBrowser-4JAJYaqx.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DnzyeB67.js → Permissions-BDWvi8PD.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DbPZ7HWw.js → PersonalDataHub-DF_K4E9i.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-gs_HOThJ.js → Pipeline-BYeZlesI.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CZlQ1EjE.js → Privacy-BIHlgnIc.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DQp__Ccb.js → ProjectInit-Cvf-6B5P.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-C7h2sOWZ.js → ProjectSettings-CnwfJrRz.js} +2 -2
- package/src/assets/web-panel/assets/Projects-b-jPXzF4.js +1 -0
- package/src/assets/web-panel/assets/Providers-CxC7JuYv.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-B_8M1-FC.js → QrScannerModal-VLf3gAfL.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Bpycr8WD.js → QuickAsk-B5vGjRiF.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Z4TrcNzs.js → Recommend--UW4iYs-.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BD6TsJlS.js → RemoteSession-DMSPcfKR.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-IKxDXHEu.js → Reputation-kQXlEHmj.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DbmR20tJ.js → Row-CxGu3pit.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CLjA5PPf.js → RssFeed-Bi5lo8MZ.js} +2 -2
- package/src/assets/web-panel/assets/{Search-Bm3owbIU.js → Search-Cq_H5RTh.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CY4RyOuq.js → Security-YFbmkaQS.js} +2 -2
- package/src/assets/web-panel/assets/{Services-CYO9qrd_.js → Services-DLOGdaLm.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-ClF51Go6.js → Skeleton-CteIxb3D.js} +1 -1
- package/src/assets/web-panel/assets/Skills-CccopaIZ.js +1 -0
- package/src/assets/web-panel/assets/{Sla-zqpDUxzP.js → Sla-AzfEQKX1.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DPSi8Qco.js → SpeechSettings-ekGo5l77.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CqABopsQ.js → SyncSettings-BmZmAgYH.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-D7q3Z4uL.js +1 -0
- package/src/assets/web-panel/assets/{Templates-Dzl6f0M2.js → Templates-CX1Tgeka.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-XeZkw40a.js → Tenant-Zc59jF4i.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CYw2YzPm.js → Terminal-CXOD7y83.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Bc2pko4i.js → TimelineRenderer-B1aBHPBo.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CfCenOHx.js → Tokens-zALlOq_U.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DTz-_YqV.js → Trigger-CQfJMXaq.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CB3tt3Z6.js → Trust-BU0RcM-w.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-y1ykmMvU.js → UkeySign-IFZ3HsbH.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-UlZ_lX0e.js → VideoEditing-BzslgW0v.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DMBaHTha.js → Wallet-BZAcQNS6.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Cksm-hBI.js → WebAuthn-CBK1DMi0.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BhOa40sX.js → WorkflowEditor-BlMTPzO-.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DNbeSTDO.js → chat-B51-8QVn.js} +1 -1
- package/src/assets/web-panel/assets/{colors-9zz8gBmW.js → colors-504RTByU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-D7aoVv-5.js → compact-item-C-GP6IQM.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DYg7B8nd.js → createContext-DOkIj7ID.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-kB0nCNwN.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BNbhkcoI.js → hasIn-DN7V-_FW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DeD1wWA8.js → index--n-ZciV3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Da0SysnX.js → index-7jIqHbzw.js} +1 -1
- package/src/assets/web-panel/assets/{index--TvoQ6UC.js → index-B2-x9bS8.js} +1 -1
- package/src/assets/web-panel/assets/{index-m2pXS3W2.js → index-BFIFJ5Dr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzDDeZBo.js → index-B_vGU-Js.js} +1 -1
- package/src/assets/web-panel/assets/{index-gNKj00Fx.js → index-Bkxhaeta.js} +1 -1
- package/src/assets/web-panel/assets/{index-C8LC0nvw.js → index-By6u5IV1.js} +1 -1
- package/src/assets/web-panel/assets/index-Bya64sZE.js +1 -0
- package/src/assets/web-panel/assets/{index-B8irlIUK.js → index-C0k_Nqg9.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9zUawcE.js → index-C3TSohzc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPojutcZ.js → index-C4DV_5uA.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZPDbEh-L.js → index-C8UltbXK.js} +1 -1
- package/src/assets/web-panel/assets/{index-jS6NASar.js → index-C9_48OzU.js} +1 -1
- package/src/assets/web-panel/assets/{index-67GdrUx2.js → index-CKTfZyfU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYu-F-gp.js → index-CP2A226L.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cq3l0L7C.js → index-CUhQpiYv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtQzs0hH.js → index-CX78k-qf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bdxe0nrD.js → index-CYopNjcJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-uc8Rz96X.js → index-Cao5DZy7.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnTM8FWK.js → index-CfiEM64n.js} +3 -3
- package/src/assets/web-panel/assets/{index-DHskwmwI.js → index-ConjaJro.js} +1 -1
- package/src/assets/web-panel/assets/{index-CA72qB1n.js → index-CqcLo5WV.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dn-JFqEi.js → index-CySTJKeq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUWmZ059.js → index-D1phyca8.js} +1 -1
- package/src/assets/web-panel/assets/{index-_-Vt1Wqk.js → index-D9LyiN-L.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIljkSt9.js → index-DA2f1UV3.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9TzVW7i.js → index-DAOpQvl_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRKukX1W.js → index-DE-hmI2l.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIMVe3HJ.js → index-DEMPUVa3.js} +1 -1
- package/src/assets/web-panel/assets/index-D_FWpDZM.js +1 -0
- package/src/assets/web-panel/assets/{index-FlBuITVG.js → index-DaA__-q1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cqy-hqD9.js → index-FcV8J_Qz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpEIwp4A.js → index-P2mfY27Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-nnmo3ipi.js → index-et5JIPHO.js} +1 -1
- package/src/assets/web-panel/assets/{index-SmEIFaRm.js → index-f4Bo4KXm.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMrqEsOS.js → index-kAqQXfP6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CV06YdPO.js → index-kt_5rfcZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CN6-OEgS.js → index-so8eIIxF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRd1zkLB.js → index-yYTQZypF.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-D0mTMUGz.js → initDefaultProps-CPYEIdpV.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DK16p4-o.js → motion-Cjim9pxs.js} +1 -1
- package/src/assets/web-panel/assets/{move-DalC20HC.js → move-DuU-cgz3.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B5RusszF.js → mtc-parser-DJHNAkta.js} +1 -1
- package/src/assets/web-panel/assets/{omit-C9Mhitht.js → omit-DSQBgdBj.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-51xQLgwM.js → pickAttrs-CTmT_j5m.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CJzIqp8u.js → placementArrow-Lfm6v-r4.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-HQvC19u4.js → responsiveObserve-CgrcPcDi.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C6hhabOp.js → slide-CuE3110i.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Q1r48-oc.js → statusUtils-DiK5nbpf.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-UakVWrHs.js → styleChecker-DPEJdQaZ.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Dmv94cxx.js → useFlexGapSupport-CnnodGmp.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DrxOnt_V.js → useFs-DWF84Yav.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BVf2M-Hg.js → usePersonalDataHub-a5b5Dw2f.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BzzW9qKH.js → vnode-DAluzXOq.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-C1ZvMgAZ.js → zoom-Dokg7uAZ.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/agenda.js +6 -5
- package/src/commands/agent.js +237 -75
- package/src/commands/agents.js +6 -0
- package/src/commands/background-session.js +11 -1
- package/src/commands/mcp.js +245 -30
- package/src/data/changelog.json +28 -2
- package/src/harness/mcp-client.js +256 -43
- package/src/harness/worktree-isolator.js +26 -3
- package/src/lib/agent-worktree.js +41 -2
- package/src/lib/background-agent-supervisor.js +790 -186
- package/src/lib/background-command-argv.js +318 -0
- package/src/lib/background-launch-profile.js +1 -0
- package/src/lib/background-phase-reporter.js +22 -2
- package/src/lib/background-worktree-policy.js +109 -0
- package/src/lib/cowork-mcp-tools.js +52 -6
- package/src/lib/cowork-task-runner.js +1 -0
- package/src/lib/cowork-task-templates.js +1 -0
- package/src/lib/mcp-headers-helper.js +76 -8
- package/src/lib/mcp-sandbox-policy.js +155 -0
- package/src/lib/mcp-stdio-executable-identity.js +75 -11
- package/src/lib/mcp-stdio-execution-authority.js +168 -0
- package/src/lib/mcp-stdio-workspace-authority.js +252 -0
- package/src/lib/plugin-runtime/sandbox-policy.js +42 -2
- package/src/lib/process-execution-broker/index.js +495 -126
- package/src/lib/process-execution-broker/platform-sandbox.js +1424 -189
- 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/process-tree-termination.js +17 -1
- package/src/lib/skill-mcp.js +74 -3
- package/src/lib/web-fetch.js +4 -4
- package/src/runtime/agent-runtime.js +61 -8
- package/src/runtime/mcp-config.js +238 -28
- package/src/workers/background-agent-worker.js +492 -71
- package/src/assets/web-panel/assets/Projects-DdCpNRNt.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/Tasks-4dbAJng4.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
|
@@ -36,7 +36,9 @@ const require = createRequire(import.meta.url);
|
|
|
36
36
|
// platform-sandbox.js exports: applySandbox, postSpawnSandbox
|
|
37
37
|
import {
|
|
38
38
|
applySandbox as _applySandbox,
|
|
39
|
+
consumeWindowsMcpCodeSnapshotPlanBinding,
|
|
39
40
|
postSpawnSandbox as _postSpawnSandbox,
|
|
41
|
+
MCP_STDIO_FD_ENTRY_BOOTSTRAP_SHA256,
|
|
40
42
|
SANDBOX_BOUNDARIES,
|
|
41
43
|
} from "./platform-sandbox.js";
|
|
42
44
|
import {
|
|
@@ -60,6 +62,9 @@ const SUPPORTED_SANDBOX_PROFILES = new Set([
|
|
|
60
62
|
"strict",
|
|
61
63
|
"network-only",
|
|
62
64
|
]);
|
|
65
|
+
// Broker-private admission state. Public runtime-probe fields are audit
|
|
66
|
+
// evidence, not authority to invoke a privileged post-spawn closure.
|
|
67
|
+
const admittedWindowsMcpCodeSnapshotPlans = new WeakSet();
|
|
63
68
|
|
|
64
69
|
// 延迟导入避免循环依赖
|
|
65
70
|
let _traceCtx = null;
|
|
@@ -1065,7 +1070,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1065
1070
|
return error;
|
|
1066
1071
|
}
|
|
1067
1072
|
|
|
1068
|
-
_validateSandboxPlan(plan) {
|
|
1073
|
+
_validateSandboxPlan(plan, launchContext = {}) {
|
|
1069
1074
|
if (!plan || typeof plan !== "object") {
|
|
1070
1075
|
throw this._sandboxError(
|
|
1071
1076
|
"invalid_sandbox_plan",
|
|
@@ -1159,6 +1164,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1159
1164
|
let sanitizedNetworkPolicy = null;
|
|
1160
1165
|
let sanitizedProcessTreePolicy = null;
|
|
1161
1166
|
let sanitizedPtyPolicy = null;
|
|
1167
|
+
let windowsPlanBindingConsumed = false;
|
|
1162
1168
|
if (plan.runtimeProbe !== null && plan.runtimeProbe !== undefined) {
|
|
1163
1169
|
if (
|
|
1164
1170
|
typeof plan.runtimeProbe !== "object" ||
|
|
@@ -1180,6 +1186,9 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1180
1186
|
"contentSnapshotScope",
|
|
1181
1187
|
"contentSnapshotMechanism",
|
|
1182
1188
|
"runtimeLaunchMechanism",
|
|
1189
|
+
"planBindingMechanism",
|
|
1190
|
+
"runtimeLaunchPath",
|
|
1191
|
+
"entrySnapshotPath",
|
|
1183
1192
|
"pluginTreeContentSnapshotScope",
|
|
1184
1193
|
"pluginTreeContentSnapshotMechanism",
|
|
1185
1194
|
"pluginTreeSnapshotConsistency",
|
|
@@ -1208,6 +1217,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1208
1217
|
"sharedLibraryClosure",
|
|
1209
1218
|
"entrySnapshotAtomic",
|
|
1210
1219
|
"runtimeLaunchAtomic",
|
|
1220
|
+
"mcpCapsuleCodeSnapshot",
|
|
1211
1221
|
]) {
|
|
1212
1222
|
if (
|
|
1213
1223
|
plan.runtimeProbe[field] !== undefined &&
|
|
@@ -1243,6 +1253,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1243
1253
|
"runtimeSnapshotSha256",
|
|
1244
1254
|
"runtimeAttestedSha256",
|
|
1245
1255
|
"entrySnapshotSha256",
|
|
1256
|
+
"planBindingDigest",
|
|
1246
1257
|
]) {
|
|
1247
1258
|
if (
|
|
1248
1259
|
plan.runtimeProbe[field] !== undefined &&
|
|
@@ -1255,6 +1266,22 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1255
1266
|
);
|
|
1256
1267
|
}
|
|
1257
1268
|
}
|
|
1269
|
+
const planBindingDeclared =
|
|
1270
|
+
plan.runtimeProbe.planBindingMechanism !== undefined ||
|
|
1271
|
+
plan.runtimeProbe.planBindingDigest !== undefined;
|
|
1272
|
+
if (
|
|
1273
|
+
planBindingDeclared &&
|
|
1274
|
+
(plan.platform !== "win32" ||
|
|
1275
|
+
!guarantees.includes(SANDBOX_BOUNDARIES.CODE_SNAPSHOT) ||
|
|
1276
|
+
plan.runtimeProbe.planBindingMechanism !==
|
|
1277
|
+
"windows-mcp-code-snapshot-plan-binding-v1" ||
|
|
1278
|
+
!/^[a-f0-9]{64}$/.test(plan.runtimeProbe.planBindingDigest || ""))
|
|
1279
|
+
) {
|
|
1280
|
+
throw this._sandboxError(
|
|
1281
|
+
"invalid_sandbox_plan",
|
|
1282
|
+
"Sandbox runtime probe plan binding must use the typed Windows MCP code-snapshot contract",
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1258
1285
|
if (
|
|
1259
1286
|
plan.runtimeProbe.pluginTreeContentSnapshotDigest !== undefined &&
|
|
1260
1287
|
(typeof plan.runtimeProbe.pluginTreeContentSnapshotDigest !==
|
|
@@ -1293,6 +1320,20 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1293
1320
|
"pluginTreeSnapshotContractBound",
|
|
1294
1321
|
"pluginTreeSnapshotAtomic",
|
|
1295
1322
|
];
|
|
1323
|
+
const nodePluginTreeSnapshotEvidence =
|
|
1324
|
+
plan.runtimeProbe.kind === "linux-bwrap-plugin-node-policy-v1" &&
|
|
1325
|
+
plan.runtimeProbe.targetRuntime === "node" &&
|
|
1326
|
+
plan.runtimeProbe.contentSnapshotScope === "plugin-entry-source";
|
|
1327
|
+
const nativePluginRuntimeEvidence =
|
|
1328
|
+
(plan.runtimeProbe.kind ===
|
|
1329
|
+
"linux-bwrap-plugin-native-static-elf-policy-v1" &&
|
|
1330
|
+
plan.runtimeProbe.targetRuntime === "native-static-elf") ||
|
|
1331
|
+
(plan.runtimeProbe.kind ===
|
|
1332
|
+
"linux-bwrap-plugin-native-dynamic-elf-policy-v1" &&
|
|
1333
|
+
plan.runtimeProbe.targetRuntime === "native-dynamic-elf");
|
|
1334
|
+
const nativePluginTreeSnapshotEvidence =
|
|
1335
|
+
nativePluginRuntimeEvidence &&
|
|
1336
|
+
plan.runtimeProbe.contentSnapshotScope === "plugin-entry-executable";
|
|
1296
1337
|
if (
|
|
1297
1338
|
pluginTreeSnapshot &&
|
|
1298
1339
|
(plan.applied !== true ||
|
|
@@ -1307,11 +1348,10 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1307
1348
|
plan.runtimeProbe.attempted !== true ||
|
|
1308
1349
|
plan.runtimeProbe.runnable !== true ||
|
|
1309
1350
|
plan.runtimeProbe.reason !== null ||
|
|
1310
|
-
|
|
1351
|
+
(!nodePluginTreeSnapshotEvidence &&
|
|
1352
|
+
!nativePluginTreeSnapshotEvidence) ||
|
|
1311
1353
|
plan.runtimeProbe.probeRuntime !== "node" ||
|
|
1312
|
-
plan.runtimeProbe.targetRuntime !== "node" ||
|
|
1313
1354
|
plan.runtimeProbe.contentSnapshot !== true ||
|
|
1314
|
-
plan.runtimeProbe.contentSnapshotScope !== "plugin-entry-source" ||
|
|
1315
1355
|
plan.runtimeProbe.contentSnapshotMechanism !==
|
|
1316
1356
|
"verified-o_tmpfile-copy-bwrap-ro-bind-data-v1" ||
|
|
1317
1357
|
plan.runtimeProbe.handleAtomic !== false ||
|
|
@@ -1355,6 +1395,18 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1355
1395
|
"Sandbox runtime probe plugin tree snapshot evidence requires pluginTreeContentSnapshot",
|
|
1356
1396
|
);
|
|
1357
1397
|
}
|
|
1398
|
+
const successfulNativeProbe =
|
|
1399
|
+
plan.applied === true &&
|
|
1400
|
+
plan.runtimeProbe.attempted === true &&
|
|
1401
|
+
plan.runtimeProbe.runnable === true &&
|
|
1402
|
+
plan.runtimeProbe.reason === null &&
|
|
1403
|
+
nativePluginRuntimeEvidence;
|
|
1404
|
+
if (successfulNativeProbe && !pluginTreeSnapshot) {
|
|
1405
|
+
throw this._sandboxError(
|
|
1406
|
+
"invalid_sandbox_plan",
|
|
1407
|
+
"Successful Linux native plugin evidence requires a complete plugin tree snapshot",
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1358
1410
|
const supervisorStringFields = [
|
|
1359
1411
|
"supervisorBindingScope",
|
|
1360
1412
|
"supervisorDescriptorBindingMechanism",
|
|
@@ -1560,15 +1612,97 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1560
1612
|
SANDBOX_BOUNDARIES.CODE_SNAPSHOT,
|
|
1561
1613
|
);
|
|
1562
1614
|
if (codeSnapshotGuaranteed) {
|
|
1615
|
+
const executionContract = launchContext.executionContract;
|
|
1616
|
+
const launchArgs = Array.isArray(launchContext.args)
|
|
1617
|
+
? launchContext.args
|
|
1618
|
+
: [];
|
|
1619
|
+
const windowsPlanBindingDeclared =
|
|
1620
|
+
plan.platform === "win32" &&
|
|
1621
|
+
(plan.runtimeProbe.planBindingMechanism !== undefined ||
|
|
1622
|
+
plan.runtimeProbe.planBindingDigest !== undefined);
|
|
1623
|
+
// Consume before evaluating any other Windows evidence. A genuine
|
|
1624
|
+
// one-launch plan is therefore burned by its first admission attempt,
|
|
1625
|
+
// including an attempt with a mismatched command or contract.
|
|
1626
|
+
windowsPlanBindingConsumed = windowsPlanBindingDeclared
|
|
1627
|
+
? consumeWindowsMcpCodeSnapshotPlanBinding(plan, {
|
|
1628
|
+
command: launchContext.command,
|
|
1629
|
+
args: launchArgs,
|
|
1630
|
+
cwd: launchContext.cwd,
|
|
1631
|
+
shell: launchContext.shell,
|
|
1632
|
+
detached: launchContext.detached,
|
|
1633
|
+
executionContract,
|
|
1634
|
+
profile: launchContext.profile,
|
|
1635
|
+
requiredBoundaries: launchContext.requiredBoundaries,
|
|
1636
|
+
sync: launchContext.sync,
|
|
1637
|
+
})
|
|
1638
|
+
: false;
|
|
1639
|
+
const passthroughArgsMatch = (candidateArgs) =>
|
|
1640
|
+
candidateArgs.length === Math.max(0, launchArgs.length - 1) &&
|
|
1641
|
+
candidateArgs.every(
|
|
1642
|
+
(candidateArg, index) => candidateArg === launchArgs[index + 1],
|
|
1643
|
+
);
|
|
1644
|
+
const contractBoundSnapshotEvidence =
|
|
1645
|
+
executionContract?.contractVersion === 1 &&
|
|
1646
|
+
executionContract.kind === MCP_STDIO_CAPSULE_SANDBOX_CONTRACT_KIND &&
|
|
1647
|
+
typeof launchContext.command === "string" &&
|
|
1648
|
+
launchContext.command === executionContract.runtimePath &&
|
|
1649
|
+
launchContext.command ===
|
|
1650
|
+
executionContract.runtimeIdentity?.realPath &&
|
|
1651
|
+
launchArgs.length >= 1 &&
|
|
1652
|
+
launchArgs[0] === executionContract.entryIdentity?.realPath &&
|
|
1653
|
+
/^[a-f0-9]{64}$/.test(
|
|
1654
|
+
executionContract.runtimeIdentity?.sha256 || "",
|
|
1655
|
+
) &&
|
|
1656
|
+
Number.isSafeInteger(executionContract.runtimeIdentity?.bytes) &&
|
|
1657
|
+
executionContract.runtimeIdentity.bytes > 0 &&
|
|
1658
|
+
/^[a-f0-9]{64}$/.test(
|
|
1659
|
+
executionContract.entryIdentity?.sha256 || "",
|
|
1660
|
+
) &&
|
|
1661
|
+
Number.isSafeInteger(executionContract.entryIdentity?.bytes) &&
|
|
1662
|
+
executionContract.entryIdentity.bytes >= 0 &&
|
|
1663
|
+
plan.runtimeProbe.entrySnapshotSha256 ===
|
|
1664
|
+
executionContract.entryIdentity.sha256 &&
|
|
1665
|
+
plan.runtimeProbe.entrySnapshotBytes ===
|
|
1666
|
+
executionContract.entryIdentity.bytes;
|
|
1667
|
+
const linuxRuntimeSnapshotContractBound =
|
|
1668
|
+
plan.runtimeProbe.runtimeSnapshotSha256 ===
|
|
1669
|
+
executionContract?.runtimeIdentity?.sha256 &&
|
|
1670
|
+
plan.runtimeProbe.runtimeSnapshotBytes ===
|
|
1671
|
+
executionContract?.runtimeIdentity?.bytes &&
|
|
1672
|
+
plan.runtimeProbe.runtimeAttestedSha256 === undefined &&
|
|
1673
|
+
plan.runtimeProbe.runtimeAttestedBytes === undefined;
|
|
1674
|
+
const windowsRuntimeAttestationContractBound =
|
|
1675
|
+
plan.runtimeProbe.runtimeAttestedSha256 ===
|
|
1676
|
+
executionContract?.runtimeIdentity?.sha256 &&
|
|
1677
|
+
plan.runtimeProbe.runtimeAttestedBytes ===
|
|
1678
|
+
executionContract?.runtimeIdentity?.bytes &&
|
|
1679
|
+
plan.runtimeProbe.runtimeSnapshotSha256 === undefined &&
|
|
1680
|
+
plan.runtimeProbe.runtimeSnapshotBytes === undefined;
|
|
1681
|
+
const contractEntryRelative = executionContract
|
|
1682
|
+
? path.posix.relative(
|
|
1683
|
+
executionContract.pluginRoot,
|
|
1684
|
+
executionContract.entryIdentity.realPath,
|
|
1685
|
+
)
|
|
1686
|
+
: null;
|
|
1687
|
+
const expectedLinuxBubblewrapEntry =
|
|
1688
|
+
contractEntryRelative &&
|
|
1689
|
+
contractEntryRelative !== ".." &&
|
|
1690
|
+
!contractEntryRelative.startsWith("../") &&
|
|
1691
|
+
!path.posix.isAbsolute(contractEntryRelative)
|
|
1692
|
+
? path.posix.join("/opt/chainless/plugin", contractEntryRelative)
|
|
1693
|
+
: null;
|
|
1563
1694
|
const exactSnapshotEvidence =
|
|
1564
1695
|
plan.applied === true &&
|
|
1565
1696
|
candidateBackend === null &&
|
|
1697
|
+
contractBoundSnapshotEvidence &&
|
|
1566
1698
|
plan.runtimeProbe.attempted === true &&
|
|
1567
1699
|
plan.runtimeProbe.runnable === true &&
|
|
1568
1700
|
plan.runtimeProbe.reason === null &&
|
|
1569
1701
|
plan.runtimeProbe.probeRuntime === "node" &&
|
|
1570
1702
|
plan.runtimeProbe.targetRuntime === "node" &&
|
|
1571
1703
|
plan.runtimeProbe.contentSnapshot === true &&
|
|
1704
|
+
plan.runtimeProbe.entrySnapshotAtomic === true &&
|
|
1705
|
+
plan.runtimeProbe.runtimeLaunchAtomic === true &&
|
|
1572
1706
|
plan.runtimeProbe.sharedLibraryClosure === false &&
|
|
1573
1707
|
/^[a-f0-9]{64}$/.test(plan.runtimeProbe.entrySnapshotSha256 || "") &&
|
|
1574
1708
|
Number.isSafeInteger(plan.runtimeProbe.entrySnapshotBytes) &&
|
|
@@ -1584,8 +1718,54 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1584
1718
|
plan.runtimeProbe.contentSnapshotScope ===
|
|
1585
1719
|
"mcp-capsule-entry-and-node-runtime" &&
|
|
1586
1720
|
plan.runtimeProbe.contentSnapshotMechanism ===
|
|
1587
|
-
"verified-o_tmpfile-copy-inherited-fd-
|
|
1721
|
+
"verified-o_tmpfile-copy-inherited-fd-module-compile-v1" &&
|
|
1588
1722
|
plan.runtimeProbe.handleAtomic === true &&
|
|
1723
|
+
plan.runtimeProbe.entrySnapshotAtomic === true &&
|
|
1724
|
+
plan.runtimeProbe.runtimeLaunchAtomic === true &&
|
|
1725
|
+
plan.runtimeProbe.runtimeLaunchMechanism ===
|
|
1726
|
+
"inherited-executable-fd-v1" &&
|
|
1727
|
+
plan.runtimeProbe.entrySnapshotBootstrapSha256 ===
|
|
1728
|
+
MCP_STDIO_FD_ENTRY_BOOTSTRAP_SHA256 &&
|
|
1729
|
+
linuxRuntimeSnapshotContractBound &&
|
|
1730
|
+
/^[a-f0-9]{64}$/.test(
|
|
1731
|
+
plan.runtimeProbe.runtimeSnapshotSha256 || "",
|
|
1732
|
+
) &&
|
|
1733
|
+
Number.isSafeInteger(plan.runtimeProbe.runtimeSnapshotBytes) &&
|
|
1734
|
+
plan.runtimeProbe.runtimeSnapshotBytes > 0 &&
|
|
1735
|
+
plan.runtimeProbe.runtimeSnapshotBytes <= 256 * 1024 * 1024 &&
|
|
1736
|
+
/^\/proc\/self\/fd\/\d+$/.test(plan.command) &&
|
|
1737
|
+
plan.args[0] === "-e" &&
|
|
1738
|
+
crypto
|
|
1739
|
+
.createHash("sha256")
|
|
1740
|
+
.update(plan.args[1] || "")
|
|
1741
|
+
.digest("hex") === MCP_STDIO_FD_ENTRY_BOOTSTRAP_SHA256 &&
|
|
1742
|
+
plan.args[2] === "--" &&
|
|
1743
|
+
passthroughArgsMatch(plan.args.slice(3));
|
|
1744
|
+
const linuxBubblewrapTargetSeparator = plan.args.indexOf("--");
|
|
1745
|
+
const linuxBubblewrapSnapshotEvidence =
|
|
1746
|
+
plan.platform === "linux" &&
|
|
1747
|
+
backend === "linux-bwrap" &&
|
|
1748
|
+
plan.enforcement === "linux-bwrap" &&
|
|
1749
|
+
policyAttested === true &&
|
|
1750
|
+
policyDigest !== null &&
|
|
1751
|
+
plan.runtimeProbe.kind === "linux-bwrap-plugin-node-policy-v1" &&
|
|
1752
|
+
plan.runtimeProbe.mcpCapsuleCodeSnapshot === true &&
|
|
1753
|
+
plan.runtimeProbe.contentSnapshotScope === "plugin-entry-source" &&
|
|
1754
|
+
plan.runtimeProbe.contentSnapshotMechanism ===
|
|
1755
|
+
"verified-o_tmpfile-copy-bwrap-ro-bind-data-v1" &&
|
|
1756
|
+
plan.runtimeProbe.handleAtomic === false &&
|
|
1757
|
+
plan.runtimeProbe.entrySnapshotAtomic === true &&
|
|
1758
|
+
plan.runtimeProbe.runtimeLaunchAtomic === true &&
|
|
1759
|
+
plan.runtimeProbe.runtimeLaunchMechanism ===
|
|
1760
|
+
"bwrap-descriptor-mount-node-runtime-exec-v1" &&
|
|
1761
|
+
plan.runtimeProbe.supervisorDescriptorBound === true &&
|
|
1762
|
+
plan.runtimeProbe.pluginTreeContentSnapshot === true &&
|
|
1763
|
+
plan.runtimeProbe.runtimeLaunchPath ===
|
|
1764
|
+
"/opt/chainless/runtime/node" &&
|
|
1765
|
+
expectedLinuxBubblewrapEntry !== null &&
|
|
1766
|
+
plan.runtimeProbe.entrySnapshotPath ===
|
|
1767
|
+
expectedLinuxBubblewrapEntry &&
|
|
1768
|
+
linuxRuntimeSnapshotContractBound &&
|
|
1589
1769
|
/^[a-f0-9]{64}$/.test(
|
|
1590
1770
|
plan.runtimeProbe.runtimeSnapshotSha256 || "",
|
|
1591
1771
|
) &&
|
|
@@ -1593,7 +1773,14 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1593
1773
|
plan.runtimeProbe.runtimeSnapshotBytes > 0 &&
|
|
1594
1774
|
plan.runtimeProbe.runtimeSnapshotBytes <= 256 * 1024 * 1024 &&
|
|
1595
1775
|
/^\/proc\/self\/fd\/\d+$/.test(plan.command) &&
|
|
1596
|
-
|
|
1776
|
+
linuxBubblewrapTargetSeparator >= 0 &&
|
|
1777
|
+
plan.args[linuxBubblewrapTargetSeparator + 1] ===
|
|
1778
|
+
plan.runtimeProbe.runtimeLaunchPath &&
|
|
1779
|
+
plan.args[linuxBubblewrapTargetSeparator + 2] ===
|
|
1780
|
+
plan.runtimeProbe.entrySnapshotPath &&
|
|
1781
|
+
passthroughArgsMatch(
|
|
1782
|
+
plan.args.slice(linuxBubblewrapTargetSeparator + 3),
|
|
1783
|
+
);
|
|
1597
1784
|
const windowsSnapshotEvidence =
|
|
1598
1785
|
plan.platform === "win32" &&
|
|
1599
1786
|
[
|
|
@@ -1601,10 +1788,14 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1601
1788
|
"windows-appcontainer-job-restricted-token",
|
|
1602
1789
|
].includes(backend) &&
|
|
1603
1790
|
plan.enforcement === backend &&
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1791
|
+
((backend === "windows-job-restricted-token" &&
|
|
1792
|
+
plan.runtimeProbe.kind ===
|
|
1793
|
+
"windows-plugin-node-entry-snapshot-v1") ||
|
|
1794
|
+
(backend === "windows-appcontainer-job-restricted-token" &&
|
|
1795
|
+
plan.runtimeProbe.kind ===
|
|
1796
|
+
"windows-appcontainer-launch-attestation-v1" &&
|
|
1797
|
+
policyAttested === true &&
|
|
1798
|
+
policyDigest !== null)) &&
|
|
1608
1799
|
plan.runtimeProbe.contentSnapshotScope ===
|
|
1609
1800
|
"mcp-capsule-entry-source" &&
|
|
1610
1801
|
plan.runtimeProbe.contentSnapshotMechanism ===
|
|
@@ -1614,15 +1805,23 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1614
1805
|
plan.runtimeProbe.runtimeLaunchAtomic === true &&
|
|
1615
1806
|
plan.runtimeProbe.runtimeLaunchMechanism ===
|
|
1616
1807
|
"filter-oplock-locked-createprocess-suspended-image-v1" &&
|
|
1808
|
+
plan.runtimeProbe.planBindingMechanism ===
|
|
1809
|
+
"windows-mcp-code-snapshot-plan-binding-v1" &&
|
|
1810
|
+
/^[a-f0-9]{64}$/.test(plan.runtimeProbe.planBindingDigest || "") &&
|
|
1811
|
+
windowsRuntimeAttestationContractBound &&
|
|
1617
1812
|
/^[a-f0-9]{64}$/.test(
|
|
1618
1813
|
plan.runtimeProbe.runtimeAttestedSha256 || "",
|
|
1619
1814
|
) &&
|
|
1620
1815
|
Number.isSafeInteger(plan.runtimeProbe.runtimeAttestedBytes) &&
|
|
1621
1816
|
plan.runtimeProbe.runtimeAttestedBytes > 0 &&
|
|
1622
|
-
plan.runtimeProbe.runtimeAttestedBytes <= 256 * 1024 * 1024
|
|
1817
|
+
plan.runtimeProbe.runtimeAttestedBytes <= 256 * 1024 * 1024 &&
|
|
1818
|
+
launchContext.builtInSandboxAdapter === true &&
|
|
1819
|
+
windowsPlanBindingConsumed;
|
|
1623
1820
|
if (
|
|
1624
1821
|
!exactSnapshotEvidence ||
|
|
1625
|
-
(!linuxSnapshotEvidence &&
|
|
1822
|
+
(!linuxSnapshotEvidence &&
|
|
1823
|
+
!linuxBubblewrapSnapshotEvidence &&
|
|
1824
|
+
!windowsSnapshotEvidence)
|
|
1626
1825
|
) {
|
|
1627
1826
|
throw this._sandboxError(
|
|
1628
1827
|
"invalid_sandbox_plan",
|
|
@@ -1910,6 +2109,22 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1910
2109
|
...(plan.runtimeProbe.handleAtomic !== undefined
|
|
1911
2110
|
? { handleAtomic: plan.runtimeProbe.handleAtomic }
|
|
1912
2111
|
: {}),
|
|
2112
|
+
...(plan.runtimeProbe.entrySnapshotAtomic !== undefined
|
|
2113
|
+
? { entrySnapshotAtomic: plan.runtimeProbe.entrySnapshotAtomic }
|
|
2114
|
+
: {}),
|
|
2115
|
+
...(plan.runtimeProbe.runtimeLaunchAtomic !== undefined
|
|
2116
|
+
? { runtimeLaunchAtomic: plan.runtimeProbe.runtimeLaunchAtomic }
|
|
2117
|
+
: {}),
|
|
2118
|
+
...(plan.runtimeProbe.runtimeLaunchMechanism !== undefined
|
|
2119
|
+
? {
|
|
2120
|
+
runtimeLaunchMechanism: plan.runtimeProbe.runtimeLaunchMechanism,
|
|
2121
|
+
}
|
|
2122
|
+
: {}),
|
|
2123
|
+
...(plan.runtimeProbe.sharedLibraryClosure !== undefined
|
|
2124
|
+
? {
|
|
2125
|
+
sharedLibraryClosure: plan.runtimeProbe.sharedLibraryClosure,
|
|
2126
|
+
}
|
|
2127
|
+
: {}),
|
|
1913
2128
|
...(plan.runtimeProbe.contentSnapshotScope !== undefined
|
|
1914
2129
|
? {
|
|
1915
2130
|
contentSnapshotScope: plan.runtimeProbe.contentSnapshotScope,
|
|
@@ -1921,12 +2136,35 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1921
2136
|
plan.runtimeProbe.contentSnapshotMechanism,
|
|
1922
2137
|
}
|
|
1923
2138
|
: {}),
|
|
2139
|
+
...(plan.runtimeProbe.planBindingMechanism !== undefined
|
|
2140
|
+
? {
|
|
2141
|
+
planBindingMechanism: plan.runtimeProbe.planBindingMechanism,
|
|
2142
|
+
planBindingDigest: plan.runtimeProbe.planBindingDigest,
|
|
2143
|
+
}
|
|
2144
|
+
: {}),
|
|
1924
2145
|
...(plan.runtimeProbe.runtimeSnapshotSha256 !== undefined
|
|
1925
2146
|
? {
|
|
1926
2147
|
runtimeSnapshotSha256: plan.runtimeProbe.runtimeSnapshotSha256,
|
|
1927
2148
|
runtimeSnapshotBytes: plan.runtimeProbe.runtimeSnapshotBytes,
|
|
1928
2149
|
entrySnapshotSha256: plan.runtimeProbe.entrySnapshotSha256,
|
|
1929
2150
|
entrySnapshotBytes: plan.runtimeProbe.entrySnapshotBytes,
|
|
2151
|
+
entrySnapshotAtomic: plan.runtimeProbe.entrySnapshotAtomic,
|
|
2152
|
+
runtimeLaunchAtomic: plan.runtimeProbe.runtimeLaunchAtomic,
|
|
2153
|
+
runtimeLaunchMechanism: plan.runtimeProbe.runtimeLaunchMechanism,
|
|
2154
|
+
...(plan.runtimeProbe.runtimeLaunchPath !== undefined
|
|
2155
|
+
? { runtimeLaunchPath: plan.runtimeProbe.runtimeLaunchPath }
|
|
2156
|
+
: {}),
|
|
2157
|
+
...(plan.runtimeProbe.entrySnapshotPath !== undefined
|
|
2158
|
+
? { entrySnapshotPath: plan.runtimeProbe.entrySnapshotPath }
|
|
2159
|
+
: {}),
|
|
2160
|
+
...(plan.runtimeProbe.mcpCapsuleCodeSnapshot !== undefined
|
|
2161
|
+
? {
|
|
2162
|
+
mcpCapsuleCodeSnapshot:
|
|
2163
|
+
plan.runtimeProbe.mcpCapsuleCodeSnapshot,
|
|
2164
|
+
}
|
|
2165
|
+
: {}),
|
|
2166
|
+
entrySnapshotBootstrapSha256:
|
|
2167
|
+
plan.runtimeProbe.entrySnapshotBootstrapSha256,
|
|
1930
2168
|
sharedLibraryClosure: plan.runtimeProbe.sharedLibraryClosure,
|
|
1931
2169
|
}
|
|
1932
2170
|
: {}),
|
|
@@ -1988,6 +2226,15 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1988
2226
|
};
|
|
1989
2227
|
}
|
|
1990
2228
|
}
|
|
2229
|
+
if (
|
|
2230
|
+
guarantees.includes(SANDBOX_BOUNDARIES.CODE_SNAPSHOT) &&
|
|
2231
|
+
runtimeProbe === null
|
|
2232
|
+
) {
|
|
2233
|
+
throw this._sandboxError(
|
|
2234
|
+
"invalid_sandbox_plan",
|
|
2235
|
+
"Code snapshot guarantee requires typed atomic MCP capsule evidence",
|
|
2236
|
+
);
|
|
2237
|
+
}
|
|
1991
2238
|
if (backend === "linux-bwrap-workspace" && !genericWorkspaceProbe) {
|
|
1992
2239
|
throw this._sandboxError(
|
|
1993
2240
|
"invalid_sandbox_plan",
|
|
@@ -2005,7 +2252,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2005
2252
|
"Required post-spawn enforcement must declare sync or async mode",
|
|
2006
2253
|
);
|
|
2007
2254
|
}
|
|
2008
|
-
|
|
2255
|
+
const validatedPlan = {
|
|
2009
2256
|
...plan,
|
|
2010
2257
|
args: [...plan.args],
|
|
2011
2258
|
options: { ...plan.options },
|
|
@@ -2025,6 +2272,15 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2025
2272
|
: {}),
|
|
2026
2273
|
postSpawn: { ...postSpawn },
|
|
2027
2274
|
};
|
|
2275
|
+
if (windowsPlanBindingConsumed) {
|
|
2276
|
+
const upstreamCleanup = validatedPlan.cleanup;
|
|
2277
|
+
validatedPlan.cleanup = (...args) => {
|
|
2278
|
+
admittedWindowsMcpCodeSnapshotPlans.delete(validatedPlan);
|
|
2279
|
+
return upstreamCleanup?.(...args);
|
|
2280
|
+
};
|
|
2281
|
+
admittedWindowsMcpCodeSnapshotPlans.add(validatedPlan);
|
|
2282
|
+
}
|
|
2283
|
+
return validatedPlan;
|
|
2028
2284
|
}
|
|
2029
2285
|
|
|
2030
2286
|
_assertRequiredSandboxBoundaries(plan, requiredBoundaries) {
|
|
@@ -2059,10 +2315,20 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2059
2315
|
},
|
|
2060
2316
|
);
|
|
2061
2317
|
}
|
|
2062
|
-
|
|
2318
|
+
const assertedPlan = {
|
|
2063
2319
|
...plan,
|
|
2064
2320
|
requiredBoundaries: [...requiredBoundaries],
|
|
2065
2321
|
};
|
|
2322
|
+
if (admittedWindowsMcpCodeSnapshotPlans.has(plan)) {
|
|
2323
|
+
admittedWindowsMcpCodeSnapshotPlans.delete(plan);
|
|
2324
|
+
const upstreamCleanup = assertedPlan.cleanup;
|
|
2325
|
+
assertedPlan.cleanup = (...args) => {
|
|
2326
|
+
admittedWindowsMcpCodeSnapshotPlans.delete(assertedPlan);
|
|
2327
|
+
return upstreamCleanup?.(...args);
|
|
2328
|
+
};
|
|
2329
|
+
admittedWindowsMcpCodeSnapshotPlans.add(assertedPlan);
|
|
2330
|
+
}
|
|
2331
|
+
return assertedPlan;
|
|
2066
2332
|
}
|
|
2067
2333
|
|
|
2068
2334
|
_prepareSandboxPlan(
|
|
@@ -2116,17 +2382,44 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2116
2382
|
// Keep the legacy string profile in argument four. The built-in adapter
|
|
2117
2383
|
// reserves argument five for runtime injection, so the typed request is
|
|
2118
2384
|
// additive in argument six and legacy injected adapters can ignore it.
|
|
2119
|
-
const
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2385
|
+
const sandboxAdapter = this._sandboxAdapter;
|
|
2386
|
+
const applySandboxAdapter = sandboxAdapter.applySandbox;
|
|
2387
|
+
const builtInSandboxAdapter = applySandboxAdapter === _applySandbox;
|
|
2388
|
+
// Never dispatch the built-in through a mutable Function property or a
|
|
2389
|
+
// global reflective helper after consulting an injected adapter getter.
|
|
2390
|
+
// The lexical import is the identity we checked and the implementation we
|
|
2391
|
+
// invoke. Legacy adapters retain their historical `this` receiver.
|
|
2392
|
+
const rawPlan = builtInSandboxAdapter
|
|
2393
|
+
? _applySandbox(
|
|
2394
|
+
command,
|
|
2395
|
+
args || [],
|
|
2396
|
+
options,
|
|
2397
|
+
profile,
|
|
2398
|
+
undefined,
|
|
2399
|
+
adapterRequest,
|
|
2400
|
+
)
|
|
2401
|
+
: Reflect.apply(applySandboxAdapter, sandboxAdapter, [
|
|
2402
|
+
command,
|
|
2403
|
+
args || [],
|
|
2404
|
+
options,
|
|
2405
|
+
profile,
|
|
2406
|
+
undefined,
|
|
2407
|
+
adapterRequest,
|
|
2408
|
+
]);
|
|
2127
2409
|
let plan;
|
|
2128
2410
|
try {
|
|
2129
|
-
plan = this._validateSandboxPlan(rawPlan
|
|
2411
|
+
plan = this._validateSandboxPlan(rawPlan, {
|
|
2412
|
+
command,
|
|
2413
|
+
args: Object.freeze([...(args || [])]),
|
|
2414
|
+
cwd: options.cwd,
|
|
2415
|
+
shell: options.shell,
|
|
2416
|
+
detached: options.detached,
|
|
2417
|
+
executionContract: sandboxPolicy.executionContract || null,
|
|
2418
|
+
profile,
|
|
2419
|
+
requiredBoundaries: Object.freeze([...requiredBoundaries]),
|
|
2420
|
+
sync,
|
|
2421
|
+
builtInSandboxAdapter,
|
|
2422
|
+
});
|
|
2130
2423
|
plan = this._assertRequiredSandboxBoundaries(plan, requiredBoundaries);
|
|
2131
2424
|
|
|
2132
2425
|
if (!plan.applied && strict) {
|
|
@@ -2139,7 +2432,12 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2139
2432
|
}
|
|
2140
2433
|
|
|
2141
2434
|
if (plan.applied && plan.postSpawn.required) {
|
|
2142
|
-
|
|
2435
|
+
const builtInWindowsMcpPostSpawn =
|
|
2436
|
+
admittedWindowsMcpCodeSnapshotPlans.has(plan);
|
|
2437
|
+
if (
|
|
2438
|
+
!builtInWindowsMcpPostSpawn &&
|
|
2439
|
+
typeof this._sandboxAdapter.postSpawnSandbox !== "function"
|
|
2440
|
+
) {
|
|
2143
2441
|
throw this._sandboxError(
|
|
2144
2442
|
"post_spawn_adapter_unavailable",
|
|
2145
2443
|
"Required post-spawn sandbox adapter is unavailable",
|
|
@@ -2312,12 +2610,6 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2312
2610
|
}
|
|
2313
2611
|
|
|
2314
2612
|
_createWorkspaceProcessCloseFence(auditEntry, proc) {
|
|
2315
|
-
if (
|
|
2316
|
-
!Array.isArray(auditEntry.workspaceTransactionIds) ||
|
|
2317
|
-
auditEntry.workspaceTransactionIds.length === 0
|
|
2318
|
-
) {
|
|
2319
|
-
return null;
|
|
2320
|
-
}
|
|
2321
2613
|
return new Promise((resolve) => {
|
|
2322
2614
|
if (typeof proc?.once === "function") {
|
|
2323
2615
|
proc.once("close", (exitCode, signal) => {
|
|
@@ -2339,6 +2631,54 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2339
2631
|
});
|
|
2340
2632
|
}
|
|
2341
2633
|
|
|
2634
|
+
_postSpawnOwnershipError(
|
|
2635
|
+
error,
|
|
2636
|
+
{ proc, auditEntry, workspaceProcessClosed, cleanup },
|
|
2637
|
+
) {
|
|
2638
|
+
let failure =
|
|
2639
|
+
error instanceof Error
|
|
2640
|
+
? error
|
|
2641
|
+
: new Error(String(error || "spawn failed"));
|
|
2642
|
+
if (
|
|
2643
|
+
failure.processTerminationRequested !== true &&
|
|
2644
|
+
failure.workspaceTerminationRequested !== true
|
|
2645
|
+
) {
|
|
2646
|
+
try {
|
|
2647
|
+
if (typeof proc?.once === "function") proc.once("error", () => {});
|
|
2648
|
+
} catch {
|
|
2649
|
+
// Listener installation failure is itself post-spawn evidence.
|
|
2650
|
+
}
|
|
2651
|
+
try {
|
|
2652
|
+
proc?.kill?.("SIGKILL");
|
|
2653
|
+
} catch {
|
|
2654
|
+
// The close fence remains the only settlement authority.
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
try {
|
|
2658
|
+
cleanup?.();
|
|
2659
|
+
} catch {
|
|
2660
|
+
// Ownership evidence must survive cleanup reporting failures.
|
|
2661
|
+
}
|
|
2662
|
+
const attach = (target) => {
|
|
2663
|
+
target.auditEntry = auditEntry;
|
|
2664
|
+
target.spawnedProcess = proc;
|
|
2665
|
+
target.workspaceProcessClosed = workspaceProcessClosed;
|
|
2666
|
+
target.workspaceTerminationRequested = true;
|
|
2667
|
+
return target;
|
|
2668
|
+
};
|
|
2669
|
+
try {
|
|
2670
|
+
return attach(failure);
|
|
2671
|
+
} catch {
|
|
2672
|
+
const wrapped = new Error(failure.message || "post-spawn failure", {
|
|
2673
|
+
cause: failure,
|
|
2674
|
+
});
|
|
2675
|
+
wrapped.name = failure.name || wrapped.name;
|
|
2676
|
+
if (failure.code !== undefined) wrapped.code = failure.code;
|
|
2677
|
+
failure = wrapped;
|
|
2678
|
+
return attach(failure);
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2342
2682
|
_runPostSpawnSandbox(proc, plan, auditEntry) {
|
|
2343
2683
|
if (!plan.applied || !plan.postSpawn.required) {
|
|
2344
2684
|
this._applySandboxAudit(auditEntry, plan, plan.applied);
|
|
@@ -2354,7 +2694,28 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
2354
2694
|
|
|
2355
2695
|
let postSpawnResult;
|
|
2356
2696
|
try {
|
|
2357
|
-
|
|
2697
|
+
const windowsMcpPlanBindingDeclared =
|
|
2698
|
+
plan.platform === "win32" &&
|
|
2699
|
+
plan.runtimeProbe?.planBindingMechanism ===
|
|
2700
|
+
"windows-mcp-code-snapshot-plan-binding-v1";
|
|
2701
|
+
const builtInWindowsMcpPlan =
|
|
2702
|
+
admittedWindowsMcpCodeSnapshotPlans.has(plan);
|
|
2703
|
+
if (windowsMcpPlanBindingDeclared && !builtInWindowsMcpPlan) {
|
|
2704
|
+
throw this._sandboxError(
|
|
2705
|
+
"windows_mcp_plan_binding_consumed",
|
|
2706
|
+
"Windows MCP sandbox plan binding is unavailable or already consumed",
|
|
2707
|
+
);
|
|
2708
|
+
}
|
|
2709
|
+
if (builtInWindowsMcpPlan) {
|
|
2710
|
+
// Burn the one-launch post-spawn authority before invoking untrusted
|
|
2711
|
+
// process-facing code. Success, failure, cleanup, and reentry all
|
|
2712
|
+
// observe the capability as consumed.
|
|
2713
|
+
admittedWindowsMcpCodeSnapshotPlans.delete(plan);
|
|
2714
|
+
}
|
|
2715
|
+
const postSpawnAdapter = builtInWindowsMcpPlan
|
|
2716
|
+
? (child, boundPlan) => boundPlan.postSpawnWindows(child)
|
|
2717
|
+
: this._sandboxAdapter.postSpawnSandbox;
|
|
2718
|
+
postSpawnResult = postSpawnAdapter(proc, plan);
|
|
2358
2719
|
} catch (error) {
|
|
2359
2720
|
this._applySandboxAudit(auditEntry, plan, false);
|
|
2360
2721
|
auditEntry.sandboxState = "failed";
|
|
@@ -3034,6 +3395,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
3034
3395
|
// Use native spawn from _native (set by patch-child-process.js)
|
|
3035
3396
|
const nativeSpawnFn = this._native?.spawn || nativeSpawn;
|
|
3036
3397
|
let proc;
|
|
3398
|
+
let workspaceProcessClosed = null;
|
|
3037
3399
|
try {
|
|
3038
3400
|
if (mcpStdioExecutableIdentityAuthority !== undefined) {
|
|
3039
3401
|
const admitted = consumeMcpStdioExecutableIdentityAuthority(
|
|
@@ -3047,16 +3409,20 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
3047
3409
|
auditEntry.mcpStdioExecutableIdentityDigest = admitted.identityDigest;
|
|
3048
3410
|
}
|
|
3049
3411
|
proc = nativeSpawnFn(command, args, optsForSpawn);
|
|
3412
|
+
workspaceProcessClosed = this._createWorkspaceProcessCloseFence(
|
|
3413
|
+
auditEntry,
|
|
3414
|
+
proc,
|
|
3415
|
+
);
|
|
3050
3416
|
this._bindWorkspaceTransactionProcess(auditEntry, proc);
|
|
3051
3417
|
} catch (spawnError) {
|
|
3052
|
-
if (proc
|
|
3053
|
-
|
|
3054
|
-
proc
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3418
|
+
if (proc) {
|
|
3419
|
+
throw this._postSpawnOwnershipError(spawnError, {
|
|
3420
|
+
proc,
|
|
3421
|
+
auditEntry,
|
|
3422
|
+
workspaceProcessClosed,
|
|
3423
|
+
cleanup: sandboxPlan.cleanup,
|
|
3424
|
+
});
|
|
3425
|
+
} else {
|
|
3060
3426
|
try {
|
|
3061
3427
|
this._settleWorkspaceTransactionSpawn(auditEntry, {
|
|
3062
3428
|
error: spawnError.message,
|
|
@@ -3069,102 +3435,105 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
3069
3435
|
throw spawnError;
|
|
3070
3436
|
}
|
|
3071
3437
|
auditEntry.pid = proc.pid;
|
|
3072
|
-
|
|
3073
|
-
auditEntry,
|
|
3074
|
-
proc,
|
|
3075
|
-
);
|
|
3076
|
-
const cleanupSandbox = this._scheduleSandboxCleanup(
|
|
3077
|
-
proc,
|
|
3078
|
-
sandboxPlan.cleanup,
|
|
3079
|
-
);
|
|
3080
|
-
if (
|
|
3081
|
-
sandboxPlan.applied === true &&
|
|
3082
|
-
(sandboxPlan.backend === "linux-bwrap-workspace" ||
|
|
3083
|
-
sandboxPlan.backend === "linux-bwrap" ||
|
|
3084
|
-
sandboxPlan.backend === "linux-fd-code-snapshot") &&
|
|
3085
|
-
sandboxPlan.postSpawn.required === false
|
|
3086
|
-
) {
|
|
3087
|
-
// child_process.spawn() has synchronously duplicated every stdio entry
|
|
3088
|
-
// into the launched process before returning. The generic/direct bwrap
|
|
3089
|
-
// backends and the MCP anonymous-code snapshot backend are complete
|
|
3090
|
-
// pre-spawn plans with no parent-side enforcement handle. Retaining
|
|
3091
|
-
// their pinned descriptors until a long-lived process exits would turn
|
|
3092
|
-
// each child into an avoidable FD leak.
|
|
3093
|
-
cleanupSandbox();
|
|
3094
|
-
}
|
|
3438
|
+
let cleanupSandbox = sandboxPlan.cleanup;
|
|
3095
3439
|
try {
|
|
3096
|
-
this.
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3440
|
+
cleanupSandbox = this._scheduleSandboxCleanup(proc, sandboxPlan.cleanup);
|
|
3441
|
+
if (
|
|
3442
|
+
sandboxPlan.applied === true &&
|
|
3443
|
+
(sandboxPlan.backend === "linux-bwrap-workspace" ||
|
|
3444
|
+
sandboxPlan.backend === "linux-bwrap" ||
|
|
3445
|
+
sandboxPlan.backend === "linux-fd-code-snapshot") &&
|
|
3446
|
+
sandboxPlan.postSpawn.required === false
|
|
3447
|
+
) {
|
|
3448
|
+
// child_process.spawn() has synchronously duplicated every stdio entry
|
|
3449
|
+
// into the launched process before returning. The generic/direct bwrap
|
|
3450
|
+
// backends and the MCP anonymous-code snapshot backend are complete
|
|
3451
|
+
// pre-spawn plans with no parent-side enforcement handle. Retaining
|
|
3452
|
+
// their pinned descriptors until a long-lived process exits would turn
|
|
3453
|
+
// each child into an avoidable FD leak.
|
|
3454
|
+
cleanupSandbox();
|
|
3104
3455
|
}
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3456
|
+
try {
|
|
3457
|
+
this._runPostSpawnSandbox(proc, sandboxPlan, auditEntry);
|
|
3458
|
+
this._updateWorkspaceTransactionProcessGuarantees(auditEntry);
|
|
3459
|
+
auditEntry.pid = proc.pid;
|
|
3460
|
+
if (Number.isSafeInteger(proc.sandboxWrapperPid)) {
|
|
3461
|
+
auditEntry.sandboxWrapperPid = proc.sandboxWrapperPid;
|
|
3462
|
+
}
|
|
3463
|
+
if (Number.isSafeInteger(proc.sandboxTargetPid)) {
|
|
3464
|
+
auditEntry.sandboxTargetPid = proc.sandboxTargetPid;
|
|
3465
|
+
}
|
|
3466
|
+
} catch (postSpawnError) {
|
|
3467
|
+
if (postSpawnError.processTerminationRequested !== true) {
|
|
3468
|
+
try {
|
|
3469
|
+
proc.kill?.("SIGKILL");
|
|
3470
|
+
} catch {
|
|
3471
|
+
// The close fence remains pending and recovery stays fail-closed.
|
|
3472
|
+
}
|
|
3111
3473
|
}
|
|
3474
|
+
cleanupSandbox();
|
|
3475
|
+
this._recordSandboxDenial(auditEntry, postSpawnError, startTime);
|
|
3476
|
+
postSpawnError.auditEntry = auditEntry;
|
|
3477
|
+
postSpawnError.spawnedProcess = proc;
|
|
3478
|
+
postSpawnError.workspaceProcessClosed = workspaceProcessClosed;
|
|
3479
|
+
postSpawnError.workspaceTerminationRequested = true;
|
|
3480
|
+
throw postSpawnError;
|
|
3112
3481
|
}
|
|
3113
|
-
cleanupSandbox();
|
|
3114
|
-
this._recordSandboxDenial(auditEntry, postSpawnError, startTime);
|
|
3115
|
-
postSpawnError.auditEntry = auditEntry;
|
|
3116
|
-
postSpawnError.spawnedProcess = proc;
|
|
3117
|
-
postSpawnError.workspaceProcessClosed = workspaceProcessClosed;
|
|
3118
|
-
postSpawnError.workspaceTerminationRequested = true;
|
|
3119
|
-
throw postSpawnError;
|
|
3120
|
-
}
|
|
3121
3482
|
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
executionId,
|
|
3126
|
-
toolName: origin,
|
|
3127
|
-
command,
|
|
3128
|
-
args: [...auditEntry.args],
|
|
3129
|
-
cwd,
|
|
3130
|
-
pid: proc.pid,
|
|
3131
|
-
component: origin,
|
|
3132
|
-
});
|
|
3133
|
-
|
|
3134
|
-
proc.on("exit", (code, signal) => {
|
|
3135
|
-
const endTime = Date.now();
|
|
3136
|
-
auditEntry.exitCode = code;
|
|
3137
|
-
auditEntry.signal = signal;
|
|
3138
|
-
auditEntry.endTime = endTime;
|
|
3139
|
-
auditEntry.durationMs = endTime - startTime;
|
|
3140
|
-
this._writeRplEntry(auditEntry, "completed");
|
|
3141
|
-
this._emitHooksEvent("tool:end", {
|
|
3483
|
+
this._recordAudit(auditEntry);
|
|
3484
|
+
this._writeRplEntry(auditEntry, "started");
|
|
3485
|
+
this._emitHooksEvent("tool:start", {
|
|
3142
3486
|
executionId,
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3487
|
+
toolName: origin,
|
|
3488
|
+
command,
|
|
3489
|
+
args: [...auditEntry.args],
|
|
3490
|
+
cwd,
|
|
3491
|
+
pid: proc.pid,
|
|
3147
3492
|
component: origin,
|
|
3148
3493
|
});
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3494
|
+
|
|
3495
|
+
proc.on("exit", (code, signal) => {
|
|
3496
|
+
const endTime = Date.now();
|
|
3497
|
+
auditEntry.exitCode = code;
|
|
3498
|
+
auditEntry.signal = signal;
|
|
3499
|
+
auditEntry.endTime = endTime;
|
|
3500
|
+
auditEntry.durationMs = endTime - startTime;
|
|
3501
|
+
this._writeRplEntry(auditEntry, "completed");
|
|
3502
|
+
this._emitHooksEvent("tool:end", {
|
|
3503
|
+
executionId,
|
|
3504
|
+
success: code === 0,
|
|
3505
|
+
exitCode: code,
|
|
3506
|
+
signal,
|
|
3507
|
+
durationMs: auditEntry.durationMs,
|
|
3508
|
+
component: origin,
|
|
3509
|
+
});
|
|
3510
|
+
this.emit("exit", auditEntry);
|
|
3161
3511
|
});
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3512
|
+
proc.on("error", (err) => {
|
|
3513
|
+
auditEntry.error = err.message;
|
|
3514
|
+
auditEntry.endTime = Date.now();
|
|
3515
|
+
auditEntry.durationMs = auditEntry.endTime - startTime;
|
|
3516
|
+
this._writeRplEntry(auditEntry, "error", err);
|
|
3517
|
+
this._emitHooksEvent("tool:end", {
|
|
3518
|
+
executionId,
|
|
3519
|
+
success: false,
|
|
3520
|
+
error: err.message,
|
|
3521
|
+
component: origin,
|
|
3522
|
+
});
|
|
3523
|
+
// EventEmitter treats an unhandled `error` event as an exception. A
|
|
3524
|
+
// process ENOENT must reach the child-process listener/callback instead
|
|
3525
|
+
// of crashing callers that did not subscribe to broker diagnostics.
|
|
3526
|
+
if (this.listenerCount("error") > 0) this.emit("error", auditEntry);
|
|
3527
|
+
});
|
|
3528
|
+
return proc;
|
|
3529
|
+
} catch (postNativeError) {
|
|
3530
|
+
throw this._postSpawnOwnershipError(postNativeError, {
|
|
3531
|
+
proc,
|
|
3532
|
+
auditEntry,
|
|
3533
|
+
workspaceProcessClosed,
|
|
3534
|
+
cleanup: cleanupSandbox,
|
|
3535
|
+
});
|
|
3536
|
+
}
|
|
3168
3537
|
}
|
|
3169
3538
|
|
|
3170
3539
|
spawnSync(command, args, options = {}) {
|