chainlesschain 0.163.8 → 0.165.1
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 +7 -4
- package/scripts/macos-mcp-launcher-build.mjs +317 -0
- package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
- package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-CavM7W3k.js → AIOps-CYxFDrcm.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-CPBtdiU2.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Dayq7Dp7.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-6U7bPb2s.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-D2Iqg_3D.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-CdoOB7WV.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-DrnAVB8w.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-CesMi5cy.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-DaX9ptax.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-OrwOPxDS.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-CvPZFRxM.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-DiHbcysC.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-CbgCkaBJ.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-Du5hgrh4.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-DsPOBW-p.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-BwHIFkNC.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-BvrDQSgd.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-gwAE6arx.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DW-0l4uF.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-j-NsLesB.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-CibVEBOI.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-W4z9vSfe.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-DAcrkKxG.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-6GXah-89.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-TKDCq8Ku.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BXBLlcNm.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-BoJJBkG3.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-okjsl46v.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-Rvs7i6nn.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-CHSUxXXS.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-V3BlfxsB.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-C_NlD4aR.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-Nn4LNxhA.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-SVAgNnkt.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-DEmjFcg-.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-DlopXipI.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-BG3ynX60.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.js → MobileBridge-DeRzWOfT.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DlPwcCbq.js → MobileProjects-Tyd3o2A0.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-6hDTRPe1.js → Mtc-BoPbOv1C.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-un-rTHp7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Ds0oveEB.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-D09JI-yY.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-DTRhiKJn.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-BAnnNCim.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Yr-1fSYi.js +1 -0
- package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-S9EAolpj.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-CqcLKqJ8.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-Dw0F9EcU.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BDRwUevN.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-D3_c3nKB.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-CxdMV98x.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-CgjNQFLI.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-BHghIIht.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-De6pqaKM.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.js → ProjectSettings-Bg4ZkNYQ.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CP8vPvzs.js +1 -0
- package/src/assets/web-panel/assets/{Providers-C_jx4TWX.js → Providers-CUnHbNf-.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-DA2f3Wts.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-C1FeHDqp.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-B5guaUMN.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-PDADSds3.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-eTlRhgvK.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-D7AqSGY0.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-JiuLm4Ja.js} +3 -3
- package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-CwruahW3.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-CdhqaR0b.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-CU0ZIlcT.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-CtduPfAb.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CROXm6AY.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-DiZiABFD.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-B5pLcXUw.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-DBX6J1Oe.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-BLyRJd3-.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-BKa5qzmk.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-DnD3a4M6.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-DEitQeTb.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-CjHggTDq.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-CsGT7sfl.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-yr4rFDrW.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-CLvu1Sjp.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-B0m7yUP8.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-C0VvP4lc.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-kllBAG1M.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-C54UQNLx.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B7y8qSvU.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-DRzTh8CJ.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-BSMwSnCx.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-BTg602H5.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BjxlBRZv.js → createContext-B6EGsdvp.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Dol8jLEP.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-RDaWX_4i.js → hasIn-DDKqJ8RD.js} +1 -1
- package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-323Hhxxt.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-BICn3Qh1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-BMuGd2--.js} +1 -1
- package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-BRqt4fO-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-BVTAl5N2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-BsR7Y2NG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-Bx044qDj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-C1GFfuqN.js} +1 -1
- package/src/assets/web-panel/assets/index-C3QX5tOl.js +1 -0
- package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-C66NpWy5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlT2VAEK.js → index-CDTvsX8t.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dsij_KsN.js → index-CGNklbP6.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-CHfLYwcW.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-CNxg61YP.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0yx-jtQ.js → index-CQlHFN_g.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-CUEU48o1.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-CWGax2QW.js} +1 -1
- package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-C_JzIXUq.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-Cf23wVMs.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-CmAInUkX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-CmAubjDi.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-Co7oM1qr.js} +1 -1
- package/src/assets/web-panel/assets/{index-Drlnwr8F.js → index-CwPUZbMI.js} +1 -1
- package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-D1naNj4U.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-D5CsBShd.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DBT3YeQ9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-DLdrHhML.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-Dc77VR3H.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Dfv2lKu3.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index-DiW0sDkz.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-DpTHIRfZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-DqFXGzzC.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-XFe-1twF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-p2HYn89m.js} +3 -3
- package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-pqfux8vZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-pPL66J85.js → index-rjzk9z1Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-th2ihDc0.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-u2YVld9W.js} +1 -1
- package/src/assets/web-panel/assets/index-xYybvEic.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-C3Djh9fa.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-BzqFmbSe.js} +1 -1
- package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-DJo_FFaW.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-_tlTiBvk.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-CB2ZyxUg.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DZwIFD4u.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-DxZY0dgk.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-CzzGt7GL.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-BaIK52yz.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-3-FHu9_M.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-BkRT68fK.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-DHYwKS-s.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-DVVUhV8p.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-CkrFKAzQ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-BuBLFz0c.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-kpm6LtXU.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/cowork.js +418 -41
- package/src/commands/permissions.js +240 -16
- package/src/commands/plugin.js +1293 -56
- package/src/commands/session-location.js +276 -0
- package/src/commands/session.js +2 -0
- package/src/data/changelog.json +28 -2
- package/src/gateways/ws/action-protocol.js +316 -17
- package/src/gateways/ws/message-dispatcher.js +30 -0
- package/src/gateways/ws/remote-session-protocol.js +565 -35
- package/src/gateways/ws/ws-agent-handler.js +12 -0
- package/src/gateways/ws/ws-approval-gate.js +5 -0
- package/src/gateways/ws/ws-server.js +510 -50
- package/src/harness/jsonl-session-store.js +341 -24
- package/src/harness/mcp-client.js +8 -1
- package/src/harness/remote-session-audit.js +2 -0
- package/src/harness/remote-session-crypto.js +929 -21
- package/src/harness/remote-session-registry.js +945 -24
- package/src/harness/session-list-index.js +233 -14
- package/src/lib/agent-authority.js +6 -0
- package/src/lib/auto-mode-config.js +98 -3
- package/src/lib/background-agent-keeper-client.js +248 -0
- package/src/lib/background-agent-keeper-protocol.js +291 -0
- package/src/lib/background-agent-supervisor.js +1357 -85
- package/src/lib/background-interaction-resolver.js +12 -0
- package/src/lib/background-session-transport.js +23 -6
- package/src/lib/background-turn-bootstrap-protocol.js +190 -0
- package/src/lib/cowork-workflow.js +1188 -76
- package/src/lib/delivery-production-adapter.js +38 -2
- package/src/lib/dynamic-workflow-facade.js +1736 -0
- package/src/lib/execution-location-contract.js +551 -0
- package/src/lib/execution-location-runtime.js +130 -0
- package/src/lib/ide-context.js +94 -6
- package/src/lib/mcp-stdio-package-materialization.js +166 -14
- package/src/lib/packer/pkg-config-generator.js +2 -0
- package/src/lib/permission-authority.js +77 -0
- package/src/lib/permission-side-effect-center.js +495 -0
- package/src/lib/plugin-runtime/install.js +514 -13
- package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
- package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
- package/src/lib/plugin-security.js +60 -3
- package/src/lib/process-execution-broker/index.js +1095 -57
- package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
- package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
- package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
- 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 +50 -4
- package/src/lib/public-ide-capability-manifest.js +3 -0
- package/src/lib/remote-approval-bridge.js +777 -34
- package/src/lib/remote-control.js +2 -0
- package/src/lib/remote-membership-authority.js +632 -0
- package/src/lib/remote-membership-coordinator.js +2973 -0
- package/src/lib/remote-membership-host-store.js +1799 -0
- package/src/lib/runtime-provenance-ledger.js +171 -46
- package/src/lib/scoped-permission-store.js +369 -0
- package/src/lib/session-anti-rollback-anchor.js +262 -5
- package/src/lib/shell-approval.js +169 -6
- package/src/lib/sub-agent-context.js +4 -0
- package/src/lib/with-file-lock.js +73 -38
- package/src/lib/workflow-definition-contract.js +149 -0
- package/src/repl/agent-repl.js +111 -36
- package/src/repl/chat-repl.js +2 -0
- package/src/repl/clipboard-image.js +735 -16
- package/src/repl/ide-status.js +1 -1
- package/src/repl/prompt-interactions.js +59 -6
- package/src/repl/remote-approval.js +29 -7
- package/src/runtime/agent-core.js +1182 -155
- package/src/runtime/headless-runner.js +52 -30
- package/src/runtime/headless-stream.js +51 -28
- package/src/workers/background-agent-keeper.js +689 -0
- package/src/workers/background-agent-worker.js +365 -13
- package/src/workers/background-turn-bootstrap.js +170 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Bb1O3Ofr.js +0 -1
- package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-Biyn2-Ro.js +0 -5
- package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
- package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
- package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Descriptor-bound pre-exec launcher shared by the Linux bubblewrap backends.
|
|
3
|
+
*
|
|
4
|
+
* Node maps every declared stdio entry onto a contiguous child descriptor.
|
|
5
|
+
* The pinned Bash executable is appended after that declared range. Bash then
|
|
6
|
+
* closes its own descriptor and every unknown inherited descriptor above the
|
|
7
|
+
* range before executing the already-pinned target executable by descriptor.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import crypto from "node:crypto";
|
|
11
|
+
|
|
12
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PATH = "/usr/bin/bash";
|
|
13
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_KIND =
|
|
14
|
+
"linux-bwrap-inherited-fd-scrubber-v1";
|
|
15
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_MECHANISM =
|
|
16
|
+
"pinned-root-owned-bash-appended-fd-three-pass-proc-self-fd-sweep-v1";
|
|
17
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_ARGV0 =
|
|
18
|
+
"chainless-bwrap-fd-scrubber-v1";
|
|
19
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PASSES = 3;
|
|
20
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS = 125;
|
|
21
|
+
|
|
22
|
+
// This script is fixed application code. Values derived from a launch plan are
|
|
23
|
+
// passed only as positional arguments and are validated as decimal integers;
|
|
24
|
+
// untrusted target arguments are forwarded exclusively through quoted "$@".
|
|
25
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_SCRIPT = [
|
|
26
|
+
"set -u",
|
|
27
|
+
"shopt -s execfail",
|
|
28
|
+
'chainless_preserved_max_fd="$1"',
|
|
29
|
+
'chainless_executable_fd="$2"',
|
|
30
|
+
"shift 2",
|
|
31
|
+
'case "$chainless_preserved_max_fd" in',
|
|
32
|
+
` ""|*[!0-9]*) exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS} ;;`,
|
|
33
|
+
"esac",
|
|
34
|
+
'case "$chainless_executable_fd" in',
|
|
35
|
+
` ""|*[!0-9]*) exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS} ;;`,
|
|
36
|
+
"esac",
|
|
37
|
+
"if [[ ! $chainless_preserved_max_fd =~ ^[1-9][0-9]*$ ||",
|
|
38
|
+
" ! $chainless_executable_fd =~ ^[1-9][0-9]*$ ||",
|
|
39
|
+
" ${#chainless_preserved_max_fd} -gt 10 ||",
|
|
40
|
+
" ${#chainless_executable_fd} -gt 10 ]]; then",
|
|
41
|
+
` exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
42
|
+
"fi",
|
|
43
|
+
"if (( chainless_preserved_max_fd < 3 ||",
|
|
44
|
+
" chainless_preserved_max_fd > 2147483647 ||",
|
|
45
|
+
" chainless_executable_fd < 3 ||",
|
|
46
|
+
" chainless_executable_fd > 2147483647 ||",
|
|
47
|
+
" chainless_executable_fd > chainless_preserved_max_fd )); then",
|
|
48
|
+
` exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
49
|
+
"fi",
|
|
50
|
+
"chainless_sweep_fds() {",
|
|
51
|
+
" local chainless_fd_path chainless_fd",
|
|
52
|
+
" chainless_sweep_found=0",
|
|
53
|
+
" chainless_sweep_seen_executable=0",
|
|
54
|
+
" for chainless_fd_path in /proc/self/fd/*; do",
|
|
55
|
+
// Bash's glob enumeration can briefly contribute its own now-stale procfs
|
|
56
|
+
// entry. -L is a Bash builtin and distinguishes that closed entry without
|
|
57
|
+
// opening another descriptor or following the descriptor's target.
|
|
58
|
+
' [[ -L "$chainless_fd_path" ]] || continue',
|
|
59
|
+
' chainless_fd="${chainless_fd_path##*/}"',
|
|
60
|
+
' case "$chainless_fd" in',
|
|
61
|
+
` ""|*[!0-9]*) exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS} ;;`,
|
|
62
|
+
" esac",
|
|
63
|
+
" if (( chainless_fd == chainless_executable_fd )); then",
|
|
64
|
+
" chainless_sweep_seen_executable=1",
|
|
65
|
+
" fi",
|
|
66
|
+
" if (( chainless_fd > chainless_preserved_max_fd )); then",
|
|
67
|
+
" chainless_sweep_found=1",
|
|
68
|
+
// Bash's variable-fd close form handles descriptors above 9 without eval.
|
|
69
|
+
` exec {chainless_fd}>&- || exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
70
|
+
" fi",
|
|
71
|
+
" done",
|
|
72
|
+
" if (( chainless_sweep_seen_executable != 1 )); then",
|
|
73
|
+
` return ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
74
|
+
" fi",
|
|
75
|
+
"}",
|
|
76
|
+
`chainless_sweep_fds || exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
77
|
+
`chainless_sweep_fds || exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
78
|
+
'chainless_second_sweep_found="$chainless_sweep_found"',
|
|
79
|
+
`chainless_sweep_fds || exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
80
|
+
'chainless_third_sweep_found="$chainless_sweep_found"',
|
|
81
|
+
"if (( chainless_second_sweep_found != 0 ||",
|
|
82
|
+
" chainless_third_sweep_found != 0 )); then",
|
|
83
|
+
` exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
84
|
+
"fi",
|
|
85
|
+
'exec /proc/self/fd/"$chainless_executable_fd" "$@"',
|
|
86
|
+
`exit ${LINUX_BWRAP_DESCRIPTOR_SCRUBBER_FAILURE_STATUS}`,
|
|
87
|
+
].join("\n");
|
|
88
|
+
|
|
89
|
+
export const LINUX_BWRAP_DESCRIPTOR_SCRUBBER_SCRIPT_SHA256 = crypto
|
|
90
|
+
.createHash("sha256")
|
|
91
|
+
.update(LINUX_BWRAP_DESCRIPTOR_SCRUBBER_SCRIPT)
|
|
92
|
+
.digest("hex");
|
|
93
|
+
|
|
94
|
+
const FIXED_PREFIX = Object.freeze([
|
|
95
|
+
"--noprofile",
|
|
96
|
+
"--norc",
|
|
97
|
+
"-c",
|
|
98
|
+
LINUX_BWRAP_DESCRIPTOR_SCRUBBER_SCRIPT,
|
|
99
|
+
LINUX_BWRAP_DESCRIPTOR_SCRUBBER_ARGV0,
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
function childFd(value) {
|
|
103
|
+
return Number.isSafeInteger(value) && value >= 3 ? value : null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function denseDataArraySnapshot(value) {
|
|
107
|
+
if (
|
|
108
|
+
!Array.isArray(value) ||
|
|
109
|
+
Object.getPrototypeOf(value) !== Array.prototype
|
|
110
|
+
) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
114
|
+
const lengthDescriptor = descriptors.length;
|
|
115
|
+
if (
|
|
116
|
+
!lengthDescriptor ||
|
|
117
|
+
!("value" in lengthDescriptor) ||
|
|
118
|
+
!Number.isSafeInteger(lengthDescriptor.value) ||
|
|
119
|
+
lengthDescriptor.value < 0 ||
|
|
120
|
+
Reflect.ownKeys(descriptors).length !== lengthDescriptor.value + 1
|
|
121
|
+
) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const snapshot = [];
|
|
125
|
+
for (let index = 0; index < lengthDescriptor.value; index += 1) {
|
|
126
|
+
const descriptor = descriptors[String(index)];
|
|
127
|
+
if (!descriptor || !("value" in descriptor)) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
snapshot.push(descriptor.value);
|
|
131
|
+
}
|
|
132
|
+
return Object.freeze(snapshot);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function ownDataDescriptorSnapshot(value) {
|
|
136
|
+
if (
|
|
137
|
+
!value ||
|
|
138
|
+
typeof value !== "object" ||
|
|
139
|
+
Array.isArray(value) ||
|
|
140
|
+
Object.getPrototypeOf(value) !== Object.prototype
|
|
141
|
+
) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
145
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
146
|
+
if (typeof key !== "string" || !("value" in descriptors[key])) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return descriptors;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function fixedEnvironmentSnapshot(value) {
|
|
154
|
+
const descriptors = ownDataDescriptorSnapshot(value);
|
|
155
|
+
if (
|
|
156
|
+
!descriptors ||
|
|
157
|
+
Reflect.ownKeys(descriptors).length !== 3 ||
|
|
158
|
+
descriptors.PATH?.value !== "/usr/bin:/bin" ||
|
|
159
|
+
descriptors.LANG?.value !== "C" ||
|
|
160
|
+
descriptors.LC_ALL?.value !== "C"
|
|
161
|
+
) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
return Object.freeze({
|
|
165
|
+
PATH: descriptors.PATH.value,
|
|
166
|
+
LANG: descriptors.LANG.value,
|
|
167
|
+
LC_ALL: descriptors.LC_ALL.value,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Build the exact Bash argv wrapper around a descriptor-backed executable. */
|
|
172
|
+
export function buildLinuxBwrapDescriptorScrubbedLaunch({
|
|
173
|
+
scrubberChildFd,
|
|
174
|
+
preservedMaxFd,
|
|
175
|
+
executableChildFd,
|
|
176
|
+
executableArgs,
|
|
177
|
+
}) {
|
|
178
|
+
const executableArgsSnapshot = denseDataArraySnapshot(executableArgs);
|
|
179
|
+
if (
|
|
180
|
+
childFd(scrubberChildFd) === null ||
|
|
181
|
+
childFd(preservedMaxFd) === null ||
|
|
182
|
+
childFd(executableChildFd) === null ||
|
|
183
|
+
scrubberChildFd !== preservedMaxFd + 1 ||
|
|
184
|
+
executableChildFd > preservedMaxFd ||
|
|
185
|
+
!executableArgsSnapshot ||
|
|
186
|
+
!executableArgsSnapshot.every((value) => typeof value === "string")
|
|
187
|
+
) {
|
|
188
|
+
throw new Error("linux_bwrap_descriptor_scrubber_layout_invalid");
|
|
189
|
+
}
|
|
190
|
+
return Object.freeze({
|
|
191
|
+
command: `/proc/self/fd/${scrubberChildFd}`,
|
|
192
|
+
args: Object.freeze([
|
|
193
|
+
...FIXED_PREFIX,
|
|
194
|
+
String(preservedMaxFd),
|
|
195
|
+
String(executableChildFd),
|
|
196
|
+
...executableArgsSnapshot,
|
|
197
|
+
]),
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Parse only the current exact wrapper grammar. Direct legacy fd launches,
|
|
203
|
+
* altered scripts/options, sparse layouts, and non-numeric fd arguments fail.
|
|
204
|
+
*/
|
|
205
|
+
export function parseLinuxBwrapDescriptorScrubbedLaunch(
|
|
206
|
+
command,
|
|
207
|
+
args,
|
|
208
|
+
options,
|
|
209
|
+
{ activeStdioThrough = 2 } = {},
|
|
210
|
+
) {
|
|
211
|
+
const argsSnapshot = denseDataArraySnapshot(args);
|
|
212
|
+
const optionDescriptors = ownDataDescriptorSnapshot(options);
|
|
213
|
+
const stdio = denseDataArraySnapshot(optionDescriptors?.stdio?.value);
|
|
214
|
+
const callerEnvironment = fixedEnvironmentSnapshot(
|
|
215
|
+
optionDescriptors?.env?.value,
|
|
216
|
+
);
|
|
217
|
+
if (
|
|
218
|
+
!argsSnapshot ||
|
|
219
|
+
!optionDescriptors ||
|
|
220
|
+
optionDescriptors.shell?.value !== false ||
|
|
221
|
+
(optionDescriptors.serialization &&
|
|
222
|
+
optionDescriptors.serialization.value !== undefined) ||
|
|
223
|
+
!stdio ||
|
|
224
|
+
stdio.length < 5 ||
|
|
225
|
+
!callerEnvironment
|
|
226
|
+
) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
const optionsSnapshot = {};
|
|
230
|
+
for (const key of Reflect.ownKeys(optionDescriptors)) {
|
|
231
|
+
if (key === "stdio" || key === "env" || key === "shell") continue;
|
|
232
|
+
Object.defineProperty(optionsSnapshot, key, {
|
|
233
|
+
value: optionDescriptors[key].value,
|
|
234
|
+
enumerable: true,
|
|
235
|
+
configurable: true,
|
|
236
|
+
writable: true,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
Object.defineProperties(optionsSnapshot, {
|
|
240
|
+
shell: {
|
|
241
|
+
value: false,
|
|
242
|
+
enumerable: true,
|
|
243
|
+
configurable: true,
|
|
244
|
+
writable: true,
|
|
245
|
+
},
|
|
246
|
+
stdio: {
|
|
247
|
+
value: stdio,
|
|
248
|
+
enumerable: true,
|
|
249
|
+
configurable: true,
|
|
250
|
+
writable: true,
|
|
251
|
+
},
|
|
252
|
+
env: {
|
|
253
|
+
value: callerEnvironment,
|
|
254
|
+
enumerable: true,
|
|
255
|
+
configurable: true,
|
|
256
|
+
writable: true,
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
const scrubberChildFd = stdio.length - 1;
|
|
260
|
+
const preservedMaxFd = scrubberChildFd - 1;
|
|
261
|
+
if (
|
|
262
|
+
!Number.isSafeInteger(activeStdioThrough) ||
|
|
263
|
+
activeStdioThrough < 2 ||
|
|
264
|
+
activeStdioThrough > preservedMaxFd
|
|
265
|
+
) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
if (
|
|
269
|
+
command !== `/proc/self/fd/${scrubberChildFd}` ||
|
|
270
|
+
!Number.isInteger(stdio[scrubberChildFd]) ||
|
|
271
|
+
argsSnapshot.length < FIXED_PREFIX.length + 2 ||
|
|
272
|
+
!FIXED_PREFIX.every((value, index) => argsSnapshot[index] === value) ||
|
|
273
|
+
argsSnapshot[FIXED_PREFIX.length] !== String(preservedMaxFd) ||
|
|
274
|
+
!/^[1-9]\d*$/.test(argsSnapshot[FIXED_PREFIX.length + 1] || "")
|
|
275
|
+
) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
const parentFds = new Set();
|
|
279
|
+
let nodeIpcChildFd = null;
|
|
280
|
+
for (let index = 3; index <= scrubberChildFd; index += 1) {
|
|
281
|
+
if (!Object.hasOwn(stdio, index)) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
const value = stdio[index];
|
|
285
|
+
if (index <= activeStdioThrough) {
|
|
286
|
+
if (value !== "pipe" && value !== "ipc") {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
if (value === "ipc") {
|
|
290
|
+
if (nodeIpcChildFd !== null) return null;
|
|
291
|
+
nodeIpcChildFd = index;
|
|
292
|
+
}
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (!Number.isSafeInteger(value) || value < 0 || parentFds.has(value)) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
parentFds.add(value);
|
|
299
|
+
}
|
|
300
|
+
const executableChildFd = Number(argsSnapshot[FIXED_PREFIX.length + 1]);
|
|
301
|
+
if (
|
|
302
|
+
!Number.isSafeInteger(executableChildFd) ||
|
|
303
|
+
String(executableChildFd) !== argsSnapshot[FIXED_PREFIX.length + 1] ||
|
|
304
|
+
executableChildFd < 3 ||
|
|
305
|
+
executableChildFd > preservedMaxFd ||
|
|
306
|
+
!Number.isInteger(stdio[executableChildFd])
|
|
307
|
+
) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
const executableArgs = Object.freeze([
|
|
311
|
+
...argsSnapshot.slice(FIXED_PREFIX.length + 2),
|
|
312
|
+
]);
|
|
313
|
+
if (!executableArgs.every((value) => typeof value === "string")) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
return Object.freeze({
|
|
317
|
+
scrubberChildFd,
|
|
318
|
+
preservedMaxFd,
|
|
319
|
+
activeStdioThrough,
|
|
320
|
+
nodeIpcChildFd,
|
|
321
|
+
executableChildFd,
|
|
322
|
+
executableArgs,
|
|
323
|
+
launchArgs: argsSnapshot,
|
|
324
|
+
options: Object.freeze(optionsSnapshot),
|
|
325
|
+
stdio,
|
|
326
|
+
callerEnvironment,
|
|
327
|
+
shell: false,
|
|
328
|
+
serialization: undefined,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function linuxBwrapDescriptorScrubberPolicyBinding(
|
|
333
|
+
executableIdentity,
|
|
334
|
+
layout,
|
|
335
|
+
) {
|
|
336
|
+
const identitySnapshot = Object.freeze({
|
|
337
|
+
path: executableIdentity?.path,
|
|
338
|
+
fileId: Object.freeze({
|
|
339
|
+
dev: String(executableIdentity?.fileId?.dev),
|
|
340
|
+
ino: String(executableIdentity?.fileId?.ino),
|
|
341
|
+
}),
|
|
342
|
+
sha256: executableIdentity?.sha256,
|
|
343
|
+
bytes: executableIdentity?.bytes,
|
|
344
|
+
mtimeMs: executableIdentity?.mtimeMs,
|
|
345
|
+
mode: executableIdentity?.mode,
|
|
346
|
+
uid: executableIdentity?.uid,
|
|
347
|
+
gid: executableIdentity?.gid,
|
|
348
|
+
});
|
|
349
|
+
return Object.freeze({
|
|
350
|
+
kind: LINUX_BWRAP_DESCRIPTOR_SCRUBBER_KIND,
|
|
351
|
+
mechanism: LINUX_BWRAP_DESCRIPTOR_SCRUBBER_MECHANISM,
|
|
352
|
+
scriptSha256: LINUX_BWRAP_DESCRIPTOR_SCRUBBER_SCRIPT_SHA256,
|
|
353
|
+
executableIdentity: identitySnapshot,
|
|
354
|
+
executablePinned: true,
|
|
355
|
+
argvFixed: true,
|
|
356
|
+
callerEnvironmentFixed: true,
|
|
357
|
+
nodeRuntimeEnvironmentInjection:
|
|
358
|
+
layout.nodeIpcChildFd === null || layout.nodeIpcChildFd === undefined
|
|
359
|
+
? "none"
|
|
360
|
+
: "node-child-process-exact-ipc-v1",
|
|
361
|
+
nodeIpcChildFd: layout.nodeIpcChildFd ?? null,
|
|
362
|
+
nodeIpcSerializationMode:
|
|
363
|
+
layout.nodeIpcChildFd === null || layout.nodeIpcChildFd === undefined
|
|
364
|
+
? null
|
|
365
|
+
: "json",
|
|
366
|
+
procSelfFdPasses: LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PASSES,
|
|
367
|
+
closesUnknownInheritedDescriptors: true,
|
|
368
|
+
verificationPassesFailClosed: true,
|
|
369
|
+
policyBound: true,
|
|
370
|
+
scrubberChildFd: layout.scrubberChildFd,
|
|
371
|
+
preservedMaxFd: layout.preservedMaxFd,
|
|
372
|
+
activeStdioThrough: layout.activeStdioThrough ?? 2,
|
|
373
|
+
executableChildFd: layout.executableChildFd,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
@@ -17,6 +17,10 @@ import {
|
|
|
17
17
|
LINUX_GENERIC_PTY_LAUNCHER_PATH,
|
|
18
18
|
planLinuxGenericBubblewrap,
|
|
19
19
|
} from "./linux-generic-bwrap.js";
|
|
20
|
+
import {
|
|
21
|
+
buildLinuxBwrapDescriptorScrubbedLaunch,
|
|
22
|
+
LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PATH,
|
|
23
|
+
} from "./linux-bwrap-descriptor-launch.js";
|
|
20
24
|
|
|
21
25
|
const BWRAP_PATH = "/usr/bin/bwrap";
|
|
22
26
|
const MAX_ATTESTED_FILE_BYTES = 256 * 1024 * 1024;
|
|
@@ -831,6 +835,71 @@ function createTrustedResources(
|
|
|
831
835
|
bytes: supervisorBytes,
|
|
832
836
|
});
|
|
833
837
|
|
|
838
|
+
const descriptorScrubber = openPair(LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PATH, {
|
|
839
|
+
directory: false,
|
|
840
|
+
rootRequired: true,
|
|
841
|
+
executable: true,
|
|
842
|
+
});
|
|
843
|
+
const descriptorScrubberStat = runtime.fs.fstatSync(
|
|
844
|
+
descriptorScrubber.finalFd,
|
|
845
|
+
);
|
|
846
|
+
const descriptorScrubberBytes = Number(descriptorScrubberStat.size);
|
|
847
|
+
const descriptorScrubberProbeDigest = hashOpenFile(
|
|
848
|
+
runtime,
|
|
849
|
+
descriptorScrubber.probeFd,
|
|
850
|
+
descriptorScrubberBytes,
|
|
851
|
+
);
|
|
852
|
+
const descriptorScrubberFinalDigest = hashOpenFile(
|
|
853
|
+
runtime,
|
|
854
|
+
descriptorScrubber.finalFd,
|
|
855
|
+
descriptorScrubberBytes,
|
|
856
|
+
);
|
|
857
|
+
if (descriptorScrubberProbeDigest !== descriptorScrubberFinalDigest) {
|
|
858
|
+
throw new Error("descriptor_scrubber_digest_mismatch");
|
|
859
|
+
}
|
|
860
|
+
descriptorScrubber.identity = Object.freeze({
|
|
861
|
+
...descriptorScrubber.identity,
|
|
862
|
+
sha256: descriptorScrubberFinalDigest,
|
|
863
|
+
bytes: descriptorScrubberBytes,
|
|
864
|
+
mtimeMs: Number(descriptorScrubberStat.mtimeMs),
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
const spawnScrubbedCapability = (executableFd, executableArgs) => {
|
|
868
|
+
const scrubberFd = runtime.fs.openSync(
|
|
869
|
+
LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PATH,
|
|
870
|
+
openFlags({ directory: false }),
|
|
871
|
+
);
|
|
872
|
+
ownedFds.add(scrubberFd);
|
|
873
|
+
try {
|
|
874
|
+
const scrubberStat = runtime.fs.fstatSync(scrubberFd);
|
|
875
|
+
if (
|
|
876
|
+
!statMatchesIdentity(scrubberStat, descriptorScrubber.identity, {
|
|
877
|
+
directory: false,
|
|
878
|
+
}) ||
|
|
879
|
+
hashOpenFile(runtime, scrubberFd, descriptorScrubberBytes) !==
|
|
880
|
+
descriptorScrubberFinalDigest
|
|
881
|
+
) {
|
|
882
|
+
throw new Error("descriptor_scrubber_capability_reader_unattested");
|
|
883
|
+
}
|
|
884
|
+
const stdio = ["ignore", "pipe", "pipe", executableFd, scrubberFd];
|
|
885
|
+
const launch = buildLinuxBwrapDescriptorScrubbedLaunch({
|
|
886
|
+
scrubberChildFd: 4,
|
|
887
|
+
preservedMaxFd: 3,
|
|
888
|
+
executableChildFd: 3,
|
|
889
|
+
executableArgs,
|
|
890
|
+
});
|
|
891
|
+
return runtime.spawnSync(launch.command, launch.args, {
|
|
892
|
+
shell: false,
|
|
893
|
+
encoding: "utf8",
|
|
894
|
+
stdio,
|
|
895
|
+
timeout: 10_000,
|
|
896
|
+
env: { PATH: "/usr/bin:/bin", LANG: "C", LC_ALL: "C" },
|
|
897
|
+
});
|
|
898
|
+
} finally {
|
|
899
|
+
closeFd(scrubberFd);
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
|
|
834
903
|
const capabilityFd = runtime.fs.openSync(
|
|
835
904
|
BWRAP_PATH,
|
|
836
905
|
openFlags({ directory: false }),
|
|
@@ -846,13 +915,7 @@ function createTrustedResources(
|
|
|
846
915
|
) {
|
|
847
916
|
throw new Error("bubblewrap_capability_reader_unattested");
|
|
848
917
|
}
|
|
849
|
-
const capabilityResult =
|
|
850
|
-
shell: false,
|
|
851
|
-
encoding: "utf8",
|
|
852
|
-
stdio: ["ignore", "pipe", "pipe", capabilityFd],
|
|
853
|
-
timeout: 10_000,
|
|
854
|
-
env: { PATH: "/usr/bin:/bin", LANG: "C", LC_ALL: "C" },
|
|
855
|
-
});
|
|
918
|
+
const capabilityResult = spawnScrubbedCapability(capabilityFd, ["--help"]);
|
|
856
919
|
closeFd(capabilityFd);
|
|
857
920
|
if (capabilityResult?.error || capabilityResult?.status !== 0) {
|
|
858
921
|
const error = new Error("bubblewrap_capability_probe_failed");
|
|
@@ -916,16 +979,9 @@ function createTrustedResources(
|
|
|
916
979
|
) {
|
|
917
980
|
throw new Error("pty_launcher_capability_reader_unattested");
|
|
918
981
|
}
|
|
919
|
-
const launcherCapabilityResult =
|
|
920
|
-
|
|
982
|
+
const launcherCapabilityResult = spawnScrubbedCapability(
|
|
983
|
+
launcherCapabilityFd,
|
|
921
984
|
["--help"],
|
|
922
|
-
{
|
|
923
|
-
shell: false,
|
|
924
|
-
encoding: "utf8",
|
|
925
|
-
stdio: ["ignore", "pipe", "pipe", launcherCapabilityFd],
|
|
926
|
-
timeout: 10_000,
|
|
927
|
-
env: { PATH: "/usr/bin:/bin", LANG: "C", LC_ALL: "C" },
|
|
928
|
-
},
|
|
929
985
|
);
|
|
930
986
|
closeFd(launcherCapabilityFd);
|
|
931
987
|
const launcherHelp =
|
|
@@ -1201,6 +1257,16 @@ function createTrustedResources(
|
|
|
1201
1257
|
!descriptorAttested(supervisor.finalFd, supervisor.identity, false) ||
|
|
1202
1258
|
hashOpenFile(runtime, supervisor.finalFd, supervisorBytes) !==
|
|
1203
1259
|
supervisorFinalDigest ||
|
|
1260
|
+
!descriptorAttested(
|
|
1261
|
+
descriptorScrubber.finalFd,
|
|
1262
|
+
descriptorScrubber.identity,
|
|
1263
|
+
false,
|
|
1264
|
+
) ||
|
|
1265
|
+
hashOpenFile(
|
|
1266
|
+
runtime,
|
|
1267
|
+
descriptorScrubber.finalFd,
|
|
1268
|
+
descriptorScrubberBytes,
|
|
1269
|
+
) !== descriptorScrubberFinalDigest ||
|
|
1204
1270
|
(sandboxOpts?.pty === true &&
|
|
1205
1271
|
(!descriptorAttested(
|
|
1206
1272
|
ptyLauncher?.finalFd,
|
|
@@ -1474,6 +1540,14 @@ function createTrustedResources(
|
|
|
1474
1540
|
sha256: supervisorFinalDigest,
|
|
1475
1541
|
bytes: supervisorBytes,
|
|
1476
1542
|
},
|
|
1543
|
+
descriptorScrubber: {
|
|
1544
|
+
probeFd: descriptorScrubber.probeFd,
|
|
1545
|
+
finalFd: descriptorScrubber.finalFd,
|
|
1546
|
+
identity: descriptorScrubber.identity,
|
|
1547
|
+
sha256: descriptorScrubberFinalDigest,
|
|
1548
|
+
bytes: descriptorScrubberBytes,
|
|
1549
|
+
mtimeMs: Number(descriptorScrubberStat.mtimeMs),
|
|
1550
|
+
},
|
|
1477
1551
|
...(ptyLauncher
|
|
1478
1552
|
? {
|
|
1479
1553
|
ptyLauncher: {
|