chainlesschain 0.162.183 → 0.162.184
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/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BapS7lz4.js → AIOps-DzAl5fGx.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CXYdXEUI.js → ActionButton-DAHtMGeC.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CKR5Lexn.js → Analytics-BHQaexv5.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DATVUOXB.js → AppLayout-Phz_pD0n.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-vb_0ZlV1.js → Artifacts-DHt47kCA.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BI1l9GWt.js → Audit--Y_8FULl.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BFXbaUEf.js → BackgroundAgents-N1zchH7D.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DEYBJJ6H.js → Backup-B_BoyN30.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-COdzeO0M.js → BaseInput-Gl4uQHcT.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-oSN6sfM5.js → Chat-Cg-eIyAZ.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BzeUi3JH.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-BezEa4tm.js → Checkbox-D0MGR2wA.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CNEL0Ife.js → Codegen-BdObJEFn.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Bf2Y2Bn1.js → Col--ghxXT3z.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BfUlu4Hc.js → Community-BUFeXOqz.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BN4xWP9e.js → Compact-DhQO2_Mr.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Bt6BKmEP.js → Compliance-3HoTqKYd.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DKLp8YxO.js → Cowork-B3zmO4VW.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-o7Hhw6ky.js → Cron-CJDrZOcc.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DaNXWJIw.js → Crosschain-SMl15obd.js} +1 -1
- package/src/assets/web-panel/assets/{DID-B-Qa2mha.js → DID-CgTrTWrl.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CMX0Qnxw.js → Dashboard-dXFKaKol.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BLuLyRu_.js → Dropdown-qQHEhCvI.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CFBAeMij.js → EmailListRenderer-C_ej0MWH.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DWzXQ67V.js → FamilyGuardDashboard-D6ajoE7I.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DB1QSLgr.js → Federation-Cio2y49h.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C-OKCToP.js → FormItemContext-ClJz1cYp.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DMJFtFZf.js → GenericCardRenderer-Dr_8Maca.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DsGSujOV.js → Git-CevLwp5u.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-B0iS9NEW.js → Governance-CW9YyQUY.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CH004H7c.js → Inference-CQqeAyER.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Q9MTQ83c.js → KnowledgeGraph-cuGVxHrw.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-B_fyjZK9.js → Logs-DIuHri5d.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-C0o4FtpD.js → MarkdownRenderer-R91Qw5JA.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BIStF9d1.js → Marketplace-CY1VhFGx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-pGfal768.js → McpTools-BBAbi1vt.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-xbNqpIqB.js → Memory-BWYGHxJA.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-B5EQGrIK.js → MobileBridge-CPIFkW7A.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-DQyWxCho.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-a_rmfxJH.js → Mtc-Bo3GnQbx.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-BmKuofUr.js → MtcAudit-C8-c4rSW.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BQbJ-CAN.js → Multisig-ChqMTtoq.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-JtPJKX25.js → NLProgramming-C48TyhvI.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-ZFKznTSG.js → Notes-zogUFWxp.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-B6aHRBBR.js → NotificationSettings-v-K9XpSB.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-P94JGGNz.js +1 -0
- package/src/assets/web-panel/assets/{Organization-BFDTAUgS.js → Organization-Boi1dQfR.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-0FoTfbWH.js → Overflow-DM5YWwgA.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CWd90etw.js → P2P-C57LKpKK.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DtCGC-W-.js → PdhVaultBrowser-BFkPqu6Q.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CvQ7nr7T.js → Permissions-D6fB9YSp.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-rdNPcR-Z.js → PersonalDataHub-Bp7EefEo.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-CmrfiNOs.js → Pipeline-BVln3hZf.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D7ep1h_t.js → Privacy-Bf8P3nF6.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-C0xKINHS.js → ProjectInit-DM6wA2E2.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-AOmZFp-F.js → ProjectSettings-CGbc5Iho.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BWHSkXZP.js → Projects-D0p9EOxm.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Cb7JCTPL.js → Providers-B2kJcxS6.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BDMehcXC.js → QrScannerModal-Cxu7dXYy.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BF6_1nvx.js → QuickAsk-DTlrTPms.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BHfT-A28.js → Recommend-Cm3X-cCj.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-DNb2kjvt.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-CsWHLEcj.js → Reputation-CZUFFjc1.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D6srnWhm.js → Row-DAPgloxA.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Xhr-KyVd.js → RssFeed-dsx9S793.js} +3 -3
- package/src/assets/web-panel/assets/{Search-vIbIJvwL.js → Search-DnnC8kz-.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Bzi5Aiko.js → Security-VuZknRMK.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BHtVX52P.js → Services-B3XNX8Vx.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C0R8B2jf.js → Skeleton-Dl1nVtCj.js} +1 -1
- package/src/assets/web-panel/assets/Skills-CY09CZ_W.js +1 -0
- package/src/assets/web-panel/assets/{Sla-0B37mxVU.js → Sla-HzU56n1z.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-0V2jE1Bs.js → SpeechSettings-CRle7Jl2.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CYedRzaj.js → SyncSettings-DWadz7Sl.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-D-R1x8vm.js → Tasks-CNVTDGg8.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BKoHztGT.js → Templates-BBAgvrlM.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant--17nwVNZ.js → Tenant-BsbbvGN8.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-uscpZI4q.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-C5jx4AE3.js → TimelineRenderer-mTyjNE6r.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DYJKYa9t.js → Tokens-Bz97oBgs.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DChpWiQ9.js → Trigger-BTRKC140.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DfWG52EA.js → Trust-B4A_KuyX.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CMugYcyA.js → UkeySign-DES9TmLU.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BOSmrHAd.js → VideoEditing-ClXs7Qxp.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-D5g3k3Sa.js → Wallet-IzZqFz-7.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-D-7u4Mkc.js → WebAuthn-BtOP04g_.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-CFzZMSUJ.js → WorkflowEditor-_0cqnopY.js} +1 -1
- package/src/assets/web-panel/assets/{chat-VbR6l6mc.js → chat-ax7193uU.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BSZn8EDS.js → colors-Bu4WGJah.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-y74obMEq.js → compact-item-BX1dlTW0.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-C326bjex.js → createContext-CktA_Dj7.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-x877iKKS.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D_INJQT_.js → hasIn-D5wd817l.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsovTpx9.js → index-5PYYkr8S.js} +1 -1
- package/src/assets/web-panel/assets/{index-9PIVuXqo.js → index-A4uBPQCz.js} +1 -1
- package/src/assets/web-panel/assets/{index-BjcWKg1S.js → index-BAtBNfkr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMHqs3Jb.js → index-BLLsUNDc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7SrC-On.js → index-BQtoRyTO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUU2606o.js → index-BRfXoRuh.js} +1 -1
- package/src/assets/web-panel/assets/{index-Iw0FfqUz.js → index-Bad2CYeH.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dlxh9D8D.js → index-BcGdL3sG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuIkfnTF.js → index-C3HmzCLt.js} +1 -1
- package/src/assets/web-panel/assets/{index-E_v1ZCTP.js → index-C8DkWyNr.js} +1 -1
- package/src/assets/web-panel/assets/{index-4eyH-eC2.js → index-C8tLR2TG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnSfnSMP.js → index-CP8ELJBc.js} +1 -1
- package/src/assets/web-panel/assets/{index-DwHSZLXg.js → index-CUForzsG.js} +1 -1
- package/src/assets/web-panel/assets/{index-C2NyllnW.js → index-CYRE0NJA.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bnua8IX3.js → index-CeVZaJSC.js} +1 -1
- package/src/assets/web-panel/assets/{index-KF9Zmqln.js → index-CfzxR61U.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cr3uuz0C.js → index-Ci3y1ZAv.js} +3 -3
- package/src/assets/web-panel/assets/{index-DBkzrpiL.js → index-CjEJjl5C.js} +1 -1
- package/src/assets/web-panel/assets/{index-abmn_8Yz.js → index-Cv7bVWJ5.js} +1 -1
- package/src/assets/web-panel/assets/{index-qMA4GYdQ.js → index-D-o4Rwjk.js} +1 -1
- package/src/assets/web-panel/assets/index-D7pfPouB.js +1 -0
- package/src/assets/web-panel/assets/{index-jYaogFE8.js → index-D9op8poE.js} +1 -1
- package/src/assets/web-panel/assets/{index-GA80ir_u.js → index-DF1TysIF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzE53HiB.js → index-DYo9S5OT.js} +1 -1
- package/src/assets/web-panel/assets/{index-gINyI1rh.js → index-D_cycOET.js} +1 -1
- package/src/assets/web-panel/assets/{index-FQBsuExX.js → index-Db3CpWTr.js} +1 -1
- package/src/assets/web-panel/assets/{index-IZAWt0H8.js → index-DkD1K-fF.js} +1 -1
- package/src/assets/web-panel/assets/{index-C327pLbw.js → index-DmPJ6T6F.js} +1 -1
- package/src/assets/web-panel/assets/{index-DdyjrCAu.js → index-DmVUeWUk.js} +1 -1
- package/src/assets/web-panel/assets/{index-CfLJ42kv.js → index-Dzdr0zDf.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkH1JvEt.js → index-PBLzwYnu.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNMxIsDg.js → index-bFCaM7Eq.js} +1 -1
- package/src/assets/web-panel/assets/index-e4i-VLBd.js +1 -0
- package/src/assets/web-panel/assets/{index-C-ZCaUJc.js → index-h3KJZr95.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bfw2hf2s.js → index-iHcPtQ2e.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJi3UqBt.js → index-jzlzm4VK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BY8-nCgs.js → index-o14NNnxw.js} +1 -1
- package/src/assets/web-panel/assets/{index-nSn2-C4N.js → index-tYPSfGbd.js} +1 -1
- package/src/assets/web-panel/assets/{index-4PIeTM--.js → index-ytp2H5Zx.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DI0Zaf8-.js → initDefaultProps-D2Iut83B.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BZDKSy3Z.js → motion-BuaJVdK9.js} +1 -1
- package/src/assets/web-panel/assets/{move-DsIW01Vp.js → move-CaEuM92y.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CohkDhsf.js → mtc-parser-wuKNBwys.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DpiN5rzg.js → omit-7a3eklaq.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-qbuqni3y.js → pickAttrs-Dn4z7KvJ.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-mBky6714.js → placementArrow-DVn_qT4-.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Bas3eQ2K.js → responsiveObserve-Dodz1OMQ.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CBx_SKoK.js → slide-CxoGskbp.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BlYguJSV.js → statusUtils-DBh_epQH.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BCYQmRGv.js → styleChecker-RXQ4gG5P.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Dp5dybLM.js → useFlexGapSupport-1Wxm0HEG.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DHAMBgA2.js → useFs-CI_ySNxJ.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-W6jsSw76.js → usePersonalDataHub-C6973rZP.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BkI6aayc.js → vnode-CalynwKr.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-C_IMGueq.js → zoom-CM1cd-Q0.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +74 -1
- package/src/commands/background-session.js +11 -1
- package/src/commands/batch.js +160 -5
- package/src/commands/plugin.js +90 -27
- package/src/commands/session.js +31 -1
- package/src/commands/team.js +212 -6
- package/src/data/changelog.json +13 -0
- package/src/harness/jsonl-session-store.js +57 -6
- package/src/harness/mcp-client.js +65 -43
- package/src/lib/agent-batch.js +4 -1
- package/src/lib/agent-team/team-worktree.js +3 -0
- package/src/lib/async-hook-supervisor.cjs +82 -10
- package/src/lib/async-hook-supervisor.js +50 -4
- package/src/lib/collaboration-run-store.js +362 -0
- package/src/lib/hook-runner.cjs +98 -17
- package/src/lib/hook-runner.js +77 -6
- package/src/lib/hook-shell-command.cjs +148 -0
- package/src/lib/hooks-v2-runtime.js +188 -77
- package/src/lib/jsonl-session-store.js +2 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +18 -0
- package/src/lib/lsp/lsp-client.js +12 -1
- package/src/lib/plugin-monitor-supervisor.js +53 -16
- package/src/lib/plugin-runtime/bin.js +1 -1
- package/src/lib/plugin-runtime/install.js +249 -57
- package/src/lib/plugin-runtime/mcp.js +21 -2
- package/src/lib/plugin-runtime/monitors.js +19 -3
- package/src/lib/plugin-runtime/sandbox-policy.js +99 -0
- package/src/lib/process-execution-broker/index.js +453 -12
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +1347 -0
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +1260 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +580 -56
- package/src/lib/session-usage.js +202 -2
- package/src/lib/stream-retry.js +29 -0
- package/src/repl/agent-repl.js +32 -3
- package/src/runtime/agent-core.js +32 -4
- package/src/runtime/headless-runner.js +37 -0
- package/src/runtime/headless-stream.js +34 -2
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CI_jT0ru.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-VTc3gT1y.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-DdcsOqEz.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-B6EEf8hh.js +0 -5
- package/src/assets/web-panel/assets/Skills-DtT6rWOX.js +0 -1
- package/src/assets/web-panel/assets/Terminal-Dnkos7vW.js +0 -3
- package/src/assets/web-panel/assets/devWarning-D3Bho_6u.js +0 -1
- package/src/assets/web-panel/assets/index-5iAFwYx1.js +0 -1
- package/src/assets/web-panel/assets/index-BfnB7LPx.js +0 -1
|
@@ -38,7 +38,13 @@ import {
|
|
|
38
38
|
postSpawnSandbox as _postSpawnSandbox,
|
|
39
39
|
SANDBOX_BOUNDARIES,
|
|
40
40
|
} from "./platform-sandbox.js";
|
|
41
|
+
import {
|
|
42
|
+
admitLinuxGenericSandboxExecutionContract,
|
|
43
|
+
issueLinuxGenericSandboxExecutionContract,
|
|
44
|
+
LINUX_GENERIC_CONTRACT_KIND,
|
|
45
|
+
} from "./linux-generic-bwrap.js";
|
|
41
46
|
import { consumeIssuedPluginSandboxExecutionContract } from "../plugin-runtime/bin.js";
|
|
47
|
+
import runtimeProvenanceLedger from "../runtime-provenance-ledger.js";
|
|
42
48
|
import { credentialAgent } from "./credential-agent.js";
|
|
43
49
|
|
|
44
50
|
const SUPPORTED_SANDBOX_BOUNDARIES = new Set(Object.values(SANDBOX_BOUNDARIES));
|
|
@@ -50,7 +56,6 @@ const SUPPORTED_SANDBOX_PROFILES = new Set([
|
|
|
50
56
|
|
|
51
57
|
// 延迟导入避免循环依赖
|
|
52
58
|
let _traceCtx = null;
|
|
53
|
-
let _rpl = null;
|
|
54
59
|
let _hooksV2 = null;
|
|
55
60
|
const _ipcBus = null;
|
|
56
61
|
|
|
@@ -66,14 +71,7 @@ function getTraceCtx() {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
function getRpl() {
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
_rpl = require("../runtime-provenance-ledger.js");
|
|
72
|
-
} catch {
|
|
73
|
-
_rpl = null;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return _rpl;
|
|
74
|
+
return runtimeProvenanceLedger;
|
|
77
75
|
}
|
|
78
76
|
|
|
79
77
|
function getHooksV2() {
|
|
@@ -271,6 +269,24 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
271
269
|
},
|
|
272
270
|
);
|
|
273
271
|
};
|
|
272
|
+
if (raw?.kind === LINUX_GENERIC_CONTRACT_KIND) {
|
|
273
|
+
const admitted = admitLinuxGenericSandboxExecutionContract(raw, {
|
|
274
|
+
origin: options.origin || "unknown",
|
|
275
|
+
command: launch?.command,
|
|
276
|
+
args: launch?.args,
|
|
277
|
+
cwd: options.cwd || process.cwd(),
|
|
278
|
+
shell: options.shell,
|
|
279
|
+
sync: launch?.sync === true,
|
|
280
|
+
stdio: options.stdio,
|
|
281
|
+
requiredBoundaries,
|
|
282
|
+
});
|
|
283
|
+
if (!admitted) {
|
|
284
|
+
return invalid(
|
|
285
|
+
"sandboxExecutionContract was not issued for this workspace launch provenance",
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
return admitted;
|
|
289
|
+
}
|
|
274
290
|
if (
|
|
275
291
|
!consumeIssuedPluginSandboxExecutionContract(raw, {
|
|
276
292
|
origin: options.origin,
|
|
@@ -315,6 +331,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
315
331
|
![
|
|
316
332
|
"strict-plugin-node-bin",
|
|
317
333
|
"strict-plugin-native-static-elf-bin",
|
|
334
|
+
"strict-plugin-native-elf-bin",
|
|
318
335
|
].includes(raw.kind)
|
|
319
336
|
) {
|
|
320
337
|
return invalid("unsupported sandboxExecutionContract kind or version");
|
|
@@ -407,6 +424,57 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
407
424
|
});
|
|
408
425
|
}
|
|
409
426
|
|
|
427
|
+
/**
|
|
428
|
+
* Issue a private one-launch Linux workspace authority for trusted host
|
|
429
|
+
* call-sites. The writable root is a positional host value, never read from
|
|
430
|
+
* a manifest/spawn option. Unsupported platforms and mixed boundary sets
|
|
431
|
+
* return null so the normal fail-closed adapter path remains authoritative.
|
|
432
|
+
*/
|
|
433
|
+
issueLinuxWorkspaceSandboxExecutionContract(
|
|
434
|
+
command,
|
|
435
|
+
args = [],
|
|
436
|
+
options = {},
|
|
437
|
+
trustedWorkspaceRoot = process.cwd(),
|
|
438
|
+
{ sync = false } = {},
|
|
439
|
+
) {
|
|
440
|
+
const requiredBoundaries = [
|
|
441
|
+
...new Set([
|
|
442
|
+
...(options.requiredBoundaries || []),
|
|
443
|
+
...(options.sandboxPolicy?.requiredBoundaries || []),
|
|
444
|
+
]),
|
|
445
|
+
];
|
|
446
|
+
if (
|
|
447
|
+
process.platform !== "linux" ||
|
|
448
|
+
requiredBoundaries.length === 0 ||
|
|
449
|
+
(options.shell !== undefined &&
|
|
450
|
+
options.shell !== null &&
|
|
451
|
+
options.shell !== false) ||
|
|
452
|
+
requiredBoundaries.some(
|
|
453
|
+
(boundary) =>
|
|
454
|
+
boundary !== SANDBOX_BOUNDARIES.FILESYSTEM &&
|
|
455
|
+
boundary !== SANDBOX_BOUNDARIES.NETWORK,
|
|
456
|
+
)
|
|
457
|
+
) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
return issueLinuxGenericSandboxExecutionContract({
|
|
461
|
+
origin: options.origin || "unknown",
|
|
462
|
+
command,
|
|
463
|
+
args,
|
|
464
|
+
cwd: options.cwd || trustedWorkspaceRoot,
|
|
465
|
+
workspaceRoot: trustedWorkspaceRoot,
|
|
466
|
+
shell: options.shell,
|
|
467
|
+
sync,
|
|
468
|
+
stdio: options.stdio,
|
|
469
|
+
requiredBoundaries,
|
|
470
|
+
detached: options.detached,
|
|
471
|
+
uid: options.uid,
|
|
472
|
+
gid: options.gid,
|
|
473
|
+
argv0: options.argv0,
|
|
474
|
+
serialization: options.serialization,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
|
|
410
478
|
_stripPluginControlOptions(options) {
|
|
411
479
|
delete options.pluginId;
|
|
412
480
|
delete options.pluginVersion;
|
|
@@ -636,6 +704,9 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
636
704
|
);
|
|
637
705
|
}
|
|
638
706
|
let runtimeProbe = null;
|
|
707
|
+
let genericWorkspaceProbe = false;
|
|
708
|
+
let sanitizedFilesystemPolicy = null;
|
|
709
|
+
let sanitizedNetworkPolicy = null;
|
|
639
710
|
if (plan.runtimeProbe !== null && plan.runtimeProbe !== undefined) {
|
|
640
711
|
if (
|
|
641
712
|
typeof plan.runtimeProbe !== "object" ||
|
|
@@ -659,6 +730,9 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
659
730
|
"pluginTreeContentSnapshotScope",
|
|
660
731
|
"pluginTreeContentSnapshotMechanism",
|
|
661
732
|
"pluginTreeSnapshotConsistency",
|
|
733
|
+
"initialDynamicLoadClosureScope",
|
|
734
|
+
"initialDynamicLoadClosureMechanism",
|
|
735
|
+
"initialDynamicInterpreter",
|
|
662
736
|
]) {
|
|
663
737
|
if (
|
|
664
738
|
plan.runtimeProbe[field] !== undefined &&
|
|
@@ -677,6 +751,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
677
751
|
"pluginTreeContentSnapshot",
|
|
678
752
|
"pluginTreeSnapshotContractBound",
|
|
679
753
|
"pluginTreeSnapshotAtomic",
|
|
754
|
+
"initialDynamicLoadClosureDescriptorBound",
|
|
680
755
|
]) {
|
|
681
756
|
if (
|
|
682
757
|
plan.runtimeProbe[field] !== undefined &&
|
|
@@ -691,6 +766,8 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
691
766
|
for (const field of [
|
|
692
767
|
"pluginTreeContentSnapshotFiles",
|
|
693
768
|
"pluginTreeContentSnapshotBytes",
|
|
769
|
+
"initialDynamicDependencyCount",
|
|
770
|
+
"initialDynamicRuntimeFileCount",
|
|
694
771
|
]) {
|
|
695
772
|
if (
|
|
696
773
|
plan.runtimeProbe[field] !== undefined &&
|
|
@@ -716,6 +793,19 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
716
793
|
"Sandbox runtime probe pluginTreeContentSnapshotDigest must be a lowercase SHA-256 value",
|
|
717
794
|
);
|
|
718
795
|
}
|
|
796
|
+
if (
|
|
797
|
+
plan.runtimeProbe.initialDynamicLoadClosureDigest !== undefined &&
|
|
798
|
+
(typeof plan.runtimeProbe.initialDynamicLoadClosureDigest !==
|
|
799
|
+
"string" ||
|
|
800
|
+
!/^[a-f0-9]{64}$/.test(
|
|
801
|
+
plan.runtimeProbe.initialDynamicLoadClosureDigest,
|
|
802
|
+
))
|
|
803
|
+
) {
|
|
804
|
+
throw this._sandboxError(
|
|
805
|
+
"invalid_sandbox_plan",
|
|
806
|
+
"Sandbox runtime probe initialDynamicLoadClosureDigest must be a lowercase SHA-256 value",
|
|
807
|
+
);
|
|
808
|
+
}
|
|
719
809
|
const pluginTreeSnapshot =
|
|
720
810
|
plan.runtimeProbe.pluginTreeContentSnapshot === true;
|
|
721
811
|
const pluginTreeEvidenceFields = [
|
|
@@ -899,6 +989,277 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
899
989
|
);
|
|
900
990
|
}
|
|
901
991
|
}
|
|
992
|
+
const initialDynamicLoadClosureBound =
|
|
993
|
+
plan.runtimeProbe.initialDynamicLoadClosureDescriptorBound === true;
|
|
994
|
+
const initialDynamicEvidenceFields = [
|
|
995
|
+
"initialDynamicLoadClosureScope",
|
|
996
|
+
"initialDynamicLoadClosureMechanism",
|
|
997
|
+
"initialDynamicInterpreter",
|
|
998
|
+
"initialDynamicDependencyCount",
|
|
999
|
+
"initialDynamicRuntimeFileCount",
|
|
1000
|
+
"initialDynamicLoadClosureDigest",
|
|
1001
|
+
];
|
|
1002
|
+
const initialDynamicInterpreter =
|
|
1003
|
+
plan.runtimeProbe.initialDynamicInterpreter;
|
|
1004
|
+
const initialDynamicDependencyCount =
|
|
1005
|
+
plan.runtimeProbe.initialDynamicDependencyCount;
|
|
1006
|
+
const initialDynamicRuntimeFileCount =
|
|
1007
|
+
plan.runtimeProbe.initialDynamicRuntimeFileCount;
|
|
1008
|
+
const successfulDynamicProbe =
|
|
1009
|
+
plan.applied === true &&
|
|
1010
|
+
plan.runtimeProbe.kind ===
|
|
1011
|
+
"linux-bwrap-plugin-native-dynamic-elf-policy-v1" &&
|
|
1012
|
+
plan.runtimeProbe.runnable === true;
|
|
1013
|
+
if (
|
|
1014
|
+
initialDynamicLoadClosureBound &&
|
|
1015
|
+
(plan.applied !== true ||
|
|
1016
|
+
plan.platform !== "linux" ||
|
|
1017
|
+
plan.enforcement !== "linux-bwrap" ||
|
|
1018
|
+
backend !== "linux-bwrap" ||
|
|
1019
|
+
candidateBackend !== null ||
|
|
1020
|
+
policyAttested !== true ||
|
|
1021
|
+
policyDigest === null ||
|
|
1022
|
+
!guarantees.includes(SANDBOX_BOUNDARIES.FILESYSTEM) ||
|
|
1023
|
+
!guarantees.includes(SANDBOX_BOUNDARIES.NETWORK) ||
|
|
1024
|
+
plan.runtimeProbe.attempted !== true ||
|
|
1025
|
+
plan.runtimeProbe.runnable !== true ||
|
|
1026
|
+
plan.runtimeProbe.reason !== null ||
|
|
1027
|
+
plan.runtimeProbe.kind !==
|
|
1028
|
+
"linux-bwrap-plugin-native-dynamic-elf-policy-v1" ||
|
|
1029
|
+
plan.runtimeProbe.probeRuntime !== "node" ||
|
|
1030
|
+
plan.runtimeProbe.targetRuntime !== "native-dynamic-elf" ||
|
|
1031
|
+
plan.runtimeProbe.contentSnapshot !== true ||
|
|
1032
|
+
plan.runtimeProbe.contentSnapshotScope !==
|
|
1033
|
+
"plugin-entry-executable" ||
|
|
1034
|
+
plan.runtimeProbe.contentSnapshotMechanism !==
|
|
1035
|
+
"verified-o_tmpfile-copy-bwrap-ro-bind-data-v1" ||
|
|
1036
|
+
plan.runtimeProbe.handleAtomic !== false ||
|
|
1037
|
+
!supervisorBound ||
|
|
1038
|
+
plan.runtimeProbe.initialDynamicLoadClosureScope !==
|
|
1039
|
+
"initial-pt_interp-and-direct-dt_needed-attested-system-set" ||
|
|
1040
|
+
plan.runtimeProbe.initialDynamicLoadClosureMechanism !==
|
|
1041
|
+
"parsed-elf-direct-system-set-to-attested-node-runtime-fds-v1" ||
|
|
1042
|
+
typeof initialDynamicInterpreter !== "string" ||
|
|
1043
|
+
!path.posix.isAbsolute(initialDynamicInterpreter) ||
|
|
1044
|
+
path.posix.normalize(initialDynamicInterpreter) !==
|
|
1045
|
+
initialDynamicInterpreter ||
|
|
1046
|
+
!["/lib/", "/lib64/", "/usr/lib/", "/usr/lib64/"].some((prefix) =>
|
|
1047
|
+
initialDynamicInterpreter.startsWith(prefix),
|
|
1048
|
+
) ||
|
|
1049
|
+
!Number.isSafeInteger(initialDynamicDependencyCount) ||
|
|
1050
|
+
initialDynamicDependencyCount < 0 ||
|
|
1051
|
+
initialDynamicDependencyCount > 128 ||
|
|
1052
|
+
!Number.isSafeInteger(initialDynamicRuntimeFileCount) ||
|
|
1053
|
+
initialDynamicRuntimeFileCount < 1 ||
|
|
1054
|
+
initialDynamicRuntimeFileCount > 129 ||
|
|
1055
|
+
initialDynamicRuntimeFileCount <
|
|
1056
|
+
Math.max(1, initialDynamicDependencyCount) ||
|
|
1057
|
+
initialDynamicRuntimeFileCount > initialDynamicDependencyCount + 1 ||
|
|
1058
|
+
!/^[a-f0-9]{64}$/.test(
|
|
1059
|
+
plan.runtimeProbe.initialDynamicLoadClosureDigest || "",
|
|
1060
|
+
))
|
|
1061
|
+
) {
|
|
1062
|
+
throw this._sandboxError(
|
|
1063
|
+
"invalid_sandbox_plan",
|
|
1064
|
+
"Sandbox runtime probe initial dynamic direct system set evidence must use the typed descriptor-bound contract",
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
if (
|
|
1068
|
+
!initialDynamicLoadClosureBound &&
|
|
1069
|
+
initialDynamicEvidenceFields.some(
|
|
1070
|
+
(field) => plan.runtimeProbe[field] !== undefined,
|
|
1071
|
+
)
|
|
1072
|
+
) {
|
|
1073
|
+
throw this._sandboxError(
|
|
1074
|
+
"invalid_sandbox_plan",
|
|
1075
|
+
"Sandbox runtime probe initial dynamic direct system set evidence requires initialDynamicLoadClosureDescriptorBound",
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
if (successfulDynamicProbe && !initialDynamicLoadClosureBound) {
|
|
1079
|
+
throw this._sandboxError(
|
|
1080
|
+
"invalid_sandbox_plan",
|
|
1081
|
+
"Sandbox runtime probe successful dynamic ELF evidence requires a descriptor-bound initial direct system set",
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
const genericWorkspaceEvidenceFields = [
|
|
1085
|
+
"contractDigest",
|
|
1086
|
+
"policyDigest",
|
|
1087
|
+
"mountTopologyDigest",
|
|
1088
|
+
"emptyRoot",
|
|
1089
|
+
"undeclaredRootReadOnly",
|
|
1090
|
+
"workspaceReadWrite",
|
|
1091
|
+
"workspaceMountTopologyAttested",
|
|
1092
|
+
"workspaceRootAliasAttested",
|
|
1093
|
+
"anonymousDevWritable",
|
|
1094
|
+
"systemReadOnly",
|
|
1095
|
+
"hostHomeHidden",
|
|
1096
|
+
"outsideMarkerHidden",
|
|
1097
|
+
"networkNamespace",
|
|
1098
|
+
"networkNamespaceChanged",
|
|
1099
|
+
"socketCreationDenied",
|
|
1100
|
+
"descriptorMounts",
|
|
1101
|
+
"mountTopologyAtomic",
|
|
1102
|
+
];
|
|
1103
|
+
for (const field of [
|
|
1104
|
+
"contractDigest",
|
|
1105
|
+
"policyDigest",
|
|
1106
|
+
"mountTopologyDigest",
|
|
1107
|
+
]) {
|
|
1108
|
+
if (
|
|
1109
|
+
plan.runtimeProbe[field] !== undefined &&
|
|
1110
|
+
(typeof plan.runtimeProbe[field] !== "string" ||
|
|
1111
|
+
!/^[a-f0-9]{64}$/.test(plan.runtimeProbe[field]))
|
|
1112
|
+
) {
|
|
1113
|
+
throw this._sandboxError(
|
|
1114
|
+
"invalid_sandbox_plan",
|
|
1115
|
+
`Sandbox runtime probe ${field} must be a lowercase SHA-256 value`,
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
for (const field of genericWorkspaceEvidenceFields.slice(3)) {
|
|
1120
|
+
if (
|
|
1121
|
+
plan.runtimeProbe[field] !== undefined &&
|
|
1122
|
+
typeof plan.runtimeProbe[field] !== "boolean"
|
|
1123
|
+
) {
|
|
1124
|
+
throw this._sandboxError(
|
|
1125
|
+
"invalid_sandbox_plan",
|
|
1126
|
+
`Sandbox runtime probe ${field} must be boolean`,
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
const genericWorkspaceKind =
|
|
1131
|
+
plan.runtimeProbe.kind === "linux-bwrap-generic-workspace-policy-v1";
|
|
1132
|
+
if (
|
|
1133
|
+
!genericWorkspaceKind &&
|
|
1134
|
+
genericWorkspaceEvidenceFields.some(
|
|
1135
|
+
(field) => plan.runtimeProbe[field] !== undefined,
|
|
1136
|
+
)
|
|
1137
|
+
) {
|
|
1138
|
+
throw this._sandboxError(
|
|
1139
|
+
"invalid_sandbox_plan",
|
|
1140
|
+
"Linux generic workspace evidence requires its typed runtime probe kind",
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
if (genericWorkspaceKind) {
|
|
1144
|
+
const filesystemPolicy = plan.filesystemPolicy;
|
|
1145
|
+
const networkPolicy = plan.networkPolicy;
|
|
1146
|
+
const workspaceRoot = filesystemPolicy?.workspaceRoot;
|
|
1147
|
+
const workingDirectory = filesystemPolicy?.workingDirectory;
|
|
1148
|
+
const workspaceRelative =
|
|
1149
|
+
typeof workspaceRoot === "string" &&
|
|
1150
|
+
typeof workingDirectory === "string"
|
|
1151
|
+
? path.posix.relative(workspaceRoot, workingDirectory)
|
|
1152
|
+
: "..";
|
|
1153
|
+
genericWorkspaceProbe =
|
|
1154
|
+
plan.applied === true &&
|
|
1155
|
+
plan.platform === "linux" &&
|
|
1156
|
+
plan.enforcement === "linux-bwrap-workspace" &&
|
|
1157
|
+
backend === "linux-bwrap-workspace" &&
|
|
1158
|
+
candidateBackend === null &&
|
|
1159
|
+
policyAttested === true &&
|
|
1160
|
+
policyDigest !== null &&
|
|
1161
|
+
plan.runtimeProbe.policyDigest === policyDigest &&
|
|
1162
|
+
/^[a-f0-9]{64}$/.test(plan.runtimeProbe.contractDigest || "") &&
|
|
1163
|
+
guarantees.includes(SANDBOX_BOUNDARIES.FILESYSTEM) &&
|
|
1164
|
+
guarantees.includes(SANDBOX_BOUNDARIES.NETWORK) &&
|
|
1165
|
+
plan.runtimeProbe.attempted === true &&
|
|
1166
|
+
plan.runtimeProbe.runnable === true &&
|
|
1167
|
+
plan.runtimeProbe.reason === null &&
|
|
1168
|
+
plan.runtimeProbe.probeRuntime === "posix-sh" &&
|
|
1169
|
+
plan.runtimeProbe.targetRuntime === "generic-command" &&
|
|
1170
|
+
plan.runtimeProbe.contentSnapshot === false &&
|
|
1171
|
+
plan.runtimeProbe.handleAtomic === false &&
|
|
1172
|
+
plan.runtimeProbe.mountTopologyAtomic === false &&
|
|
1173
|
+
plan.runtimeProbe.mountTopologyDigest ===
|
|
1174
|
+
filesystemPolicy?.mountTopologyDigest &&
|
|
1175
|
+
[
|
|
1176
|
+
"emptyRoot",
|
|
1177
|
+
"undeclaredRootReadOnly",
|
|
1178
|
+
"workspaceReadWrite",
|
|
1179
|
+
"workspaceMountTopologyAttested",
|
|
1180
|
+
"workspaceRootAliasAttested",
|
|
1181
|
+
"anonymousDevWritable",
|
|
1182
|
+
"systemReadOnly",
|
|
1183
|
+
"hostHomeHidden",
|
|
1184
|
+
"outsideMarkerHidden",
|
|
1185
|
+
"networkNamespace",
|
|
1186
|
+
"networkNamespaceChanged",
|
|
1187
|
+
"socketCreationDenied",
|
|
1188
|
+
"descriptorMounts",
|
|
1189
|
+
].every((field) => plan.runtimeProbe[field] === true) &&
|
|
1190
|
+
typeof workspaceRoot === "string" &&
|
|
1191
|
+
path.posix.isAbsolute(workspaceRoot) &&
|
|
1192
|
+
workspaceRoot !== "/" &&
|
|
1193
|
+
typeof workingDirectory === "string" &&
|
|
1194
|
+
path.posix.isAbsolute(workingDirectory) &&
|
|
1195
|
+
workspaceRelative !== ".." &&
|
|
1196
|
+
!workspaceRelative.startsWith("../") &&
|
|
1197
|
+
!path.posix.isAbsolute(workspaceRelative) &&
|
|
1198
|
+
filesystemPolicy.workspaceAccess === "read-write" &&
|
|
1199
|
+
filesystemPolicy.systemAccess === "read-only" &&
|
|
1200
|
+
filesystemPolicy.undeclaredRootAccess === "read-only" &&
|
|
1201
|
+
filesystemPolicy.hostRootMapped === false &&
|
|
1202
|
+
filesystemPolicy.hostHomeMapped === false &&
|
|
1203
|
+
filesystemPolicy.workspaceDescriptorBound === true &&
|
|
1204
|
+
filesystemPolicy.systemDescriptorBound === true &&
|
|
1205
|
+
filesystemPolicy.exactEtcFileDescriptors === true &&
|
|
1206
|
+
filesystemPolicy.workspaceRecursiveBind === true &&
|
|
1207
|
+
filesystemPolicy.workspaceMountTopology ===
|
|
1208
|
+
"no-strict-descendants-or-forbidden-root-aliases-at-attestation" &&
|
|
1209
|
+
filesystemPolicy.mountTopologySource === "proc-self-mountinfo" &&
|
|
1210
|
+
/^[a-f0-9]{64}$/.test(filesystemPolicy.mountTopologyDigest || "") &&
|
|
1211
|
+
filesystemPolicy.mountTopologyAtomic === false &&
|
|
1212
|
+
Array.isArray(filesystemPolicy.anonymousWritablePaths) &&
|
|
1213
|
+
filesystemPolicy.anonymousWritablePaths.length === 5 &&
|
|
1214
|
+
["/home/sandbox", "/dev", "/run", "/tmp", "/var/tmp"].every(
|
|
1215
|
+
(value, index) =>
|
|
1216
|
+
filesystemPolicy.anonymousWritablePaths[index] === value,
|
|
1217
|
+
) &&
|
|
1218
|
+
networkPolicy?.namespace === "new" &&
|
|
1219
|
+
networkPolicy?.namespaceIdentityChanged === true &&
|
|
1220
|
+
networkPolicy?.seccomp === "deny-network-creation" &&
|
|
1221
|
+
plan.command.startsWith("/proc/self/fd/") &&
|
|
1222
|
+
plan.options?.cwd === "/" &&
|
|
1223
|
+
plan.options?.shell === false &&
|
|
1224
|
+
Array.isArray(plan.options?.stdio) &&
|
|
1225
|
+
plan.args.includes("--bind-fd") &&
|
|
1226
|
+
plan.args.includes("--ro-bind-fd") &&
|
|
1227
|
+
plan.args.includes("--remount-ro") &&
|
|
1228
|
+
plan.args.includes("--unshare-net") &&
|
|
1229
|
+
plan.args.includes("--seccomp") &&
|
|
1230
|
+
!plan.args.includes("--ro-bind");
|
|
1231
|
+
if (!genericWorkspaceProbe) {
|
|
1232
|
+
throw this._sandboxError(
|
|
1233
|
+
"invalid_sandbox_plan",
|
|
1234
|
+
"Linux generic workspace evidence must use the typed descriptor-bound empty-root contract",
|
|
1235
|
+
);
|
|
1236
|
+
}
|
|
1237
|
+
sanitizedFilesystemPolicy = Object.freeze({
|
|
1238
|
+
workspaceRoot,
|
|
1239
|
+
workingDirectory,
|
|
1240
|
+
workspaceAccess: filesystemPolicy.workspaceAccess,
|
|
1241
|
+
systemAccess: filesystemPolicy.systemAccess,
|
|
1242
|
+
undeclaredRootAccess: filesystemPolicy.undeclaredRootAccess,
|
|
1243
|
+
anonymousWritablePaths: Object.freeze([
|
|
1244
|
+
...filesystemPolicy.anonymousWritablePaths,
|
|
1245
|
+
]),
|
|
1246
|
+
hostRootMapped: filesystemPolicy.hostRootMapped,
|
|
1247
|
+
hostHomeMapped: filesystemPolicy.hostHomeMapped,
|
|
1248
|
+
workspaceDescriptorBound: filesystemPolicy.workspaceDescriptorBound,
|
|
1249
|
+
systemDescriptorBound: filesystemPolicy.systemDescriptorBound,
|
|
1250
|
+
exactEtcFileDescriptors: filesystemPolicy.exactEtcFileDescriptors,
|
|
1251
|
+
workspaceRecursiveBind: filesystemPolicy.workspaceRecursiveBind,
|
|
1252
|
+
workspaceMountTopology: filesystemPolicy.workspaceMountTopology,
|
|
1253
|
+
mountTopologySource: filesystemPolicy.mountTopologySource,
|
|
1254
|
+
mountTopologyDigest: filesystemPolicy.mountTopologyDigest,
|
|
1255
|
+
mountTopologyAtomic: filesystemPolicy.mountTopologyAtomic,
|
|
1256
|
+
});
|
|
1257
|
+
sanitizedNetworkPolicy = Object.freeze({
|
|
1258
|
+
namespace: networkPolicy.namespace,
|
|
1259
|
+
namespaceIdentityChanged: networkPolicy.namespaceIdentityChanged,
|
|
1260
|
+
seccomp: networkPolicy.seccomp,
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
902
1263
|
runtimeProbe = {
|
|
903
1264
|
kind: plan.runtimeProbe.kind,
|
|
904
1265
|
attempted: plan.runtimeProbe.attempted,
|
|
@@ -944,6 +1305,19 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
944
1305
|
runtimeProbe[field] = plan.runtimeProbe[field];
|
|
945
1306
|
}
|
|
946
1307
|
}
|
|
1308
|
+
for (const field of [
|
|
1309
|
+
"initialDynamicLoadClosureDescriptorBound",
|
|
1310
|
+
...initialDynamicEvidenceFields,
|
|
1311
|
+
]) {
|
|
1312
|
+
if (plan.runtimeProbe[field] !== undefined) {
|
|
1313
|
+
runtimeProbe[field] = plan.runtimeProbe[field];
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
for (const field of genericWorkspaceEvidenceFields) {
|
|
1317
|
+
if (plan.runtimeProbe[field] !== undefined) {
|
|
1318
|
+
runtimeProbe[field] = plan.runtimeProbe[field];
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
947
1321
|
if (supervisorIdentity !== undefined) {
|
|
948
1322
|
runtimeProbe.supervisorExecutableIdentity = {
|
|
949
1323
|
path: supervisorIdentity.path,
|
|
@@ -960,6 +1334,12 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
960
1334
|
};
|
|
961
1335
|
}
|
|
962
1336
|
}
|
|
1337
|
+
if (backend === "linux-bwrap-workspace" && !genericWorkspaceProbe) {
|
|
1338
|
+
throw this._sandboxError(
|
|
1339
|
+
"invalid_sandbox_plan",
|
|
1340
|
+
"Applied Linux generic workspace plans require typed runtime evidence",
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
963
1343
|
const postSpawn = plan.postSpawn || { required: false, mode: "none" };
|
|
964
1344
|
if (
|
|
965
1345
|
postSpawn.required &&
|
|
@@ -981,6 +1361,12 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
981
1361
|
policyAttested,
|
|
982
1362
|
policyDigest,
|
|
983
1363
|
runtimeProbe,
|
|
1364
|
+
...(sanitizedFilesystemPolicy
|
|
1365
|
+
? {
|
|
1366
|
+
filesystemPolicy: sanitizedFilesystemPolicy,
|
|
1367
|
+
networkPolicy: sanitizedNetworkPolicy,
|
|
1368
|
+
}
|
|
1369
|
+
: {}),
|
|
984
1370
|
postSpawn: { ...postSpawn },
|
|
985
1371
|
};
|
|
986
1372
|
}
|
|
@@ -1135,6 +1521,39 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1135
1521
|
auditEntry.sandboxPolicyAttested =
|
|
1136
1522
|
typeof plan?.policyAttested === "boolean" ? plan.policyAttested : null;
|
|
1137
1523
|
auditEntry.sandboxPolicyDigest = plan?.policyDigest || null;
|
|
1524
|
+
const genericPolicy =
|
|
1525
|
+
applied === true && plan?.backend === "linux-bwrap-workspace";
|
|
1526
|
+
auditEntry.sandboxFilesystemPolicy = genericPolicy
|
|
1527
|
+
? {
|
|
1528
|
+
workspaceRoot: plan.filesystemPolicy.workspaceRoot,
|
|
1529
|
+
workingDirectory: plan.filesystemPolicy.workingDirectory,
|
|
1530
|
+
workspaceAccess: plan.filesystemPolicy.workspaceAccess,
|
|
1531
|
+
systemAccess: plan.filesystemPolicy.systemAccess,
|
|
1532
|
+
undeclaredRootAccess: plan.filesystemPolicy.undeclaredRootAccess,
|
|
1533
|
+
anonymousWritablePaths: [
|
|
1534
|
+
...plan.filesystemPolicy.anonymousWritablePaths,
|
|
1535
|
+
],
|
|
1536
|
+
hostRootMapped: plan.filesystemPolicy.hostRootMapped,
|
|
1537
|
+
hostHomeMapped: plan.filesystemPolicy.hostHomeMapped,
|
|
1538
|
+
workspaceDescriptorBound:
|
|
1539
|
+
plan.filesystemPolicy.workspaceDescriptorBound,
|
|
1540
|
+
systemDescriptorBound: plan.filesystemPolicy.systemDescriptorBound,
|
|
1541
|
+
exactEtcFileDescriptors:
|
|
1542
|
+
plan.filesystemPolicy.exactEtcFileDescriptors,
|
|
1543
|
+
workspaceRecursiveBind: plan.filesystemPolicy.workspaceRecursiveBind,
|
|
1544
|
+
workspaceMountTopology: plan.filesystemPolicy.workspaceMountTopology,
|
|
1545
|
+
mountTopologySource: plan.filesystemPolicy.mountTopologySource,
|
|
1546
|
+
mountTopologyDigest: plan.filesystemPolicy.mountTopologyDigest,
|
|
1547
|
+
mountTopologyAtomic: plan.filesystemPolicy.mountTopologyAtomic,
|
|
1548
|
+
}
|
|
1549
|
+
: null;
|
|
1550
|
+
auditEntry.sandboxNetworkPolicy = genericPolicy
|
|
1551
|
+
? {
|
|
1552
|
+
namespace: plan.networkPolicy.namespace,
|
|
1553
|
+
namespaceIdentityChanged: plan.networkPolicy.namespaceIdentityChanged,
|
|
1554
|
+
seccomp: plan.networkPolicy.seccomp,
|
|
1555
|
+
}
|
|
1556
|
+
: null;
|
|
1138
1557
|
auditEntry.sandboxCandidateReason = plan?.candidateBackend
|
|
1139
1558
|
? plan?.reason || null
|
|
1140
1559
|
: null;
|
|
@@ -1396,12 +1815,13 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1396
1815
|
|
|
1397
1816
|
_writeRplEntry(auditEntry, status = "started", error = null) {
|
|
1398
1817
|
const rpl = getRpl();
|
|
1399
|
-
if (!rpl
|
|
1818
|
+
if (!rpl) return;
|
|
1400
1819
|
try {
|
|
1401
1820
|
const traceCtx = this._getTraceContext();
|
|
1402
|
-
rpl.
|
|
1821
|
+
if (typeof rpl.record !== "function") return;
|
|
1822
|
+
rpl.record(
|
|
1823
|
+
"process.execution",
|
|
1403
1824
|
{
|
|
1404
|
-
kind: "process.execution",
|
|
1405
1825
|
component: auditEntry.origin,
|
|
1406
1826
|
action: "spawn",
|
|
1407
1827
|
artifactId: auditEntry.executionId,
|
|
@@ -1422,6 +1842,15 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1422
1842
|
policy: auditEntry.policy,
|
|
1423
1843
|
scope: auditEntry.scope,
|
|
1424
1844
|
},
|
|
1845
|
+
sandbox: {
|
|
1846
|
+
applied: auditEntry.sandboxed === true,
|
|
1847
|
+
backend: auditEntry.sandboxBackend || null,
|
|
1848
|
+
guarantees: [...(auditEntry.sandboxGuarantees || [])],
|
|
1849
|
+
policyAttested: auditEntry.sandboxPolicyAttested === true,
|
|
1850
|
+
policyDigest: auditEntry.sandboxPolicyDigest || null,
|
|
1851
|
+
filesystemPolicy: auditEntry.sandboxFilesystemPolicy || null,
|
|
1852
|
+
networkPolicy: auditEntry.sandboxNetworkPolicy || null,
|
|
1853
|
+
},
|
|
1425
1854
|
traceId:
|
|
1426
1855
|
traceCtx?.traceId || auditEntry.traceId || `trace-${Date.now()}`,
|
|
1427
1856
|
parentSpanId: traceCtx?.spanId || null,
|
|
@@ -1607,6 +2036,18 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
1607
2036
|
proc,
|
|
1608
2037
|
sandboxPlan.cleanup,
|
|
1609
2038
|
);
|
|
2039
|
+
if (
|
|
2040
|
+
sandboxPlan.applied === true &&
|
|
2041
|
+
sandboxPlan.backend === "linux-bwrap-workspace" &&
|
|
2042
|
+
sandboxPlan.postSpawn.required === false
|
|
2043
|
+
) {
|
|
2044
|
+
// child_process.spawn() has synchronously duplicated every stdio entry
|
|
2045
|
+
// into the launched bwrap process before returning. Generic workspace
|
|
2046
|
+
// plans do not need a parent-side post-spawn handle, so retaining their
|
|
2047
|
+
// pinned mount/seccomp descriptors until a long-lived MCP/LSP/monitor
|
|
2048
|
+
// exits would turn each child into an avoidable FD leak.
|
|
2049
|
+
cleanupSandbox();
|
|
2050
|
+
}
|
|
1610
2051
|
try {
|
|
1611
2052
|
this._runPostSpawnSandbox(proc, sandboxPlan, auditEntry);
|
|
1612
2053
|
auditEntry.pid = proc.pid;
|