chainlesschain 0.166.89 → 0.166.91
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/README.md +91 -5
- package/package.json +3 -3
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-C8AkN9R5.js → AIOps-DgV7xb8F.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BrAzSQor.js → ActionButton-CgANpkKu.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Cu56X8Oh.js → Analytics-DnvpX7RB.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BP1Riofl.js → AppLayout-C2bHccBM.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-CIW-nNAz.js → Artifacts-BIhijC9g.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CJtDabk-.js → Audit-CKRjWGdp.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DYIHeQ_P.js → BackgroundAgents-CblYtgBE.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B4CsFzj7.js → Backup-Cq35b78a.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-3eoJ5kfb.js → BaseInput-DcB7NoRz.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BBhX2L_E.js → Chat-tc3b-s7i.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-RN8cbv7w.js → ChatBubbleRenderer-fcc_Tvqu.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-5UvmwHVk.js → Checkbox-BLD5bH5u.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BFy8zsBN.js → Codegen-BLOsoazN.js} +1 -1
- package/src/assets/web-panel/assets/{Col-4M6bKRRO.js → Col-Bdr7JwIx.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D6LC0j7_.js → Community-C84BsWE0.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-Dd48xMcv.js → Compact-Dzdwd04z.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Ba85ggmy.js → Compliance-CCG-R0EV.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-D1BXlkuK.js → Cowork-BYj72SK0.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Ca2Uy7Ia.js → Cron-B6iKAwOf.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-C2bDRXZg.js → Crosschain-BJ-oDC6u.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DySZKAJf.js → DID-BnMckGLr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DDpYf-TT.js → Dashboard-Cyje-gCO.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DGjROfPv.js → Dropdown-BpNlenjK.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DxX9QYiB.js → EmailListRenderer-BhonO7Nv.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-TBCZyrSJ.js → EvolutionSettings-DVoNU-Id.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BeqwTXBa.js → FamilyGuardDashboard-tdn-KC67.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CiCpKJQ1.js → Federation--EEVrHhz.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CdTmbLkU.js → FormItemContext-Cy8zr0-4.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BwbkEY-5.js → GenericCardRenderer-BuUhpgFi.js} +1 -1
- package/src/assets/web-panel/assets/{Git-VnAga2vv.js → Git-Ctd3E5Pe.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-i-4Ebs-H.js → Governance-Ce7dV6aU.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CirjTgNw.js → Inference-CD1vExIH.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CunS7vhA.js → KnowledgeGraph-Dn64OdQ7.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DBuTF0c6.js → Logs-PmElVRrT.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-B-iE-tt_.js → MarkdownRenderer-BFiVKf5t.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BK6ZivTS.js → Marketplace-OW4jTXwx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CUnCRnd3.js → McpTools-BEq2Ib4x.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CBGGr8Gy.js → Memory-Can_P2oK.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-reB6iaWD.js → MobileBridge-DJ8R-dn3.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-o1YdVB7i.js → MobileProjects-B7kV9GOt.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-if5OE3GH.js → Mtc-BfxamolS.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-BTZWpq0j.js → MtcAudit-DHtuv7av.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-8cvMAYFL.js → Multisig-DLkLpvxc.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BMvUXAWo.js → NLProgramming-u4XtJTIt.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BWWjColh.js → Notes-BwuuPJLS.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-Ccr4lIhS.js → NotificationSettings-HEeu-E9v.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DhksGy6D.js → OrderTableRenderer-BtvN-Qwh.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DciXQfdY.js → Organization-Yh-czs3b.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-8DR7uMSx.js → Overflow-DmE8mYVM.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DE6euHYl.js → P2P-CWVck8WN.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-ByuWoauq.js → PdhVaultBrowser-DgFqekod.js} +4 -4
- package/src/assets/web-panel/assets/{Permissions-DkjM87ac.js → Permissions-BtJBVOHV.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-2DLp0KTL.js → PersonalDataHub-6VBObXzd.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-Ci2Qlkfr.js → Pipeline-D222FmqY.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DlwDnDVA.js → Privacy-Bi9FMikp.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CmMifW39.js → ProjectInit-Bo52H47H.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DJVFIh-6.js → ProjectSettings-BPkesfOc.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-P2nWBS70.js → Projects-GynohSFX.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-B2cxaGCU.js → Providers-DVdMg04n.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CpO77kcE.js → QrScannerModal-DqJCb595.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BDQl1hb0.js → QuickAsk-J7loQbXi.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DTD2f3IN.js → Recommend-BI5aURVc.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DGZAnwvs.js → RemoteSession-BN2sqGvz.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-B_R4vitb.js → Reputation-BGOND-Fi.js} +1 -1
- package/src/assets/web-panel/assets/{Row-4Jj6JyXN.js → Row-77dfwaUk.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-D1t1MCZ-.js → RssFeed-FtBAxS3g.js} +2 -2
- package/src/assets/web-panel/assets/{Search-CyOUlIn7.js → Search-BaYVLFb7.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BmknPT5Q.js → Security-LE3Vv6ab.js} +4 -4
- package/src/assets/web-panel/assets/{Services-DkEK8mpa.js → Services-C5pP-Whz.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Bvo5bpuk.js → Skeleton-CLqKUVsF.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-AMmG8fim.js → Skills-BPjN0SX5.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Dl7-OKOV.js → Sla-14jD70kg.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DtiGKu0E.js → SpeechSettings-Dr9ij42W.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Ch7mp3ES.js → SyncSettings-BzLHP7B8.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Ck-sEgj-.js → Tasks-YqV9b0rV.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BlV22Il8.js → Templates-CxxAE4PK.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CaaAu0mX.js → Tenant-CRb3PcKJ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-lA9g3FtJ.js → Terminal-CTzPpBaP.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CG26IFC3.js → TimelineRenderer-DjFUj_hy.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-iaJUBLBm.js → Tokens-Bbb8tPvx.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DWQJtLK3.js → Trigger-CSeWGM0W.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CTjmUwqp.js → Trust-JgESMBo3.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CMnxufgD.js → UkeySign-CiObLk0T.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-diCFSWJw.js → VideoEditing-CFEZaQ2x.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Ba1oND1K.js → Wallet-DR8ZGDNn.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DZDqPS-S.js → WebAuthn-DxZukvu7.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CfN8fPMe.js → WorkflowEditor-CKgSZQwn.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BiqMsO_i.js → chat-CTxEQE66.js} +1 -1
- package/src/assets/web-panel/assets/{colors-By8LkjqH.js → colors-CAjKMUu3.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-B0mxvRe3.js → compact-item-BXuz49at.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-Li2ub348.js → createContext-CFN_Hwr9.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CfB8DxT2.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DYbHPkbl.js → hasIn-BwoSBSfP.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVZNYRzM.js → index-B0QbLlWn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGZzexNa.js → index-B2o_BBjg.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYv3JIzl.js → index-B2tEnBPx.js} +1 -1
- package/src/assets/web-panel/assets/{index-1lVoRUrQ.js → index-B7kp-zRE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CTVPeUh3.js → index-B9yR7zqr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFhksbXp.js → index-BK4ftQ4d.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0D0HkkM.js → index-Bj4hIiLW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEp_3fKJ.js → index-BmQITjMU.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIImi0cd.js → index-BmXpdcHI.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6qL3QBU.js → index-Bqv_Cray.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSk0xuXP.js → index-Bu2P6u8m.js} +1 -1
- package/src/assets/web-panel/assets/{index-zSzXsF9b.js → index-Bw9s2d3c.js} +1 -1
- package/src/assets/web-panel/assets/{index-beDji-cB.js → index-C8er4W9u.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-RE3mFh.js → index-CB3kVd9c.js} +1 -1
- package/src/assets/web-panel/assets/index-CCsRfd0k.js +1 -0
- package/src/assets/web-panel/assets/{index-CA0AOURT.js → index-CF9lWi1o.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMh3VxgO.js → index-CN53dE_u.js} +1 -1
- package/src/assets/web-panel/assets/{index-KWt8Owo8.js → index-CSmFby3Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-DB4DCzqU.js → index-CehdwJ_Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHgiSV6R.js → index-Cgk0YEiq.js} +1 -1
- package/src/assets/web-panel/assets/{index-b4O_YBVR.js → index-Cp5y7lX_.js} +1 -1
- package/src/assets/web-panel/assets/index-CsmiZIQ4.js +1 -0
- package/src/assets/web-panel/assets/{index-DAOpBv3C.js → index-DTX9CJPx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZqTG7fP.js → index-DViK2bkv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bc6bxU24.js → index-DY-gBSm8.js} +1 -1
- package/src/assets/web-panel/assets/{index-Czt7WAtA.js → index-DjF5BOZx.js} +1 -1
- package/src/assets/web-panel/assets/{index-KqfqSdAC.js → index-DmkbAADP.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bd5znvCV.js → index-DpdDnZX_.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5Se6Lnv.js → index-Dv7V2kg6.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cpfn4YbT.js → index-DxunxaTw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcOJEgBE.js → index-F2E5RCwz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgyrklzQ.js → index-IY9bd5az.js} +1 -1
- package/src/assets/web-panel/assets/{index-ClsJN8sW.js → index-IahILygB.js} +3 -3
- package/src/assets/web-panel/assets/{index-hw3sCYAz.js → index-T3MTE6jB.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bm2P2Kgp.js → index-Tz5dheZa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRzewWeE.js → index-_ZtCyUdz.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPRgnazi.js → index-o9DpkZKf.js} +1 -1
- package/src/assets/web-panel/assets/{index-ByqFKMWL.js → index-t2Ch_JKn.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgMFnBOv.js → index-u9_DM3ZC.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-TgDL_7OY.js → initDefaultProps-BoiGJDoO.js} +1 -1
- package/src/assets/web-panel/assets/{motion-fHosyV5c.js → motion-5eL4E0pA.js} +1 -1
- package/src/assets/web-panel/assets/{move-C_QfW5qg.js → move-DjggDi_1.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-u7ywDVOg.js → mtc-parser-Ce8Vo2T3.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BEJdUgE9.js → omit-D1yOBaO2.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DGkQFAJ5.js → pickAttrs-8NLceQe8.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DUyZXAjt.js → placementArrow-CsIdBRmQ.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-B4xDxO7Q.js → responsiveObserve-GM5NE8En.js} +1 -1
- package/src/assets/web-panel/assets/{slide-B8WuJtst.js → slide-44yj3u49.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DLUqy7JO.js → statusUtils-B8tqtWcX.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BYOJOyqL.js → styleChecker-NhDPBbyB.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-WChWQURv.js → useFlexGapSupport-C8Qz1GtN.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-vLNpm3dv.js → useFs-ClUv4kih.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DSZ8unoU.js → usePersonalDataHub-BwkOVEh6.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-C4Xf7Kg1.js → vnode--gMF33R0.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BulmeAGy.js → zoom-DXg3TqOP.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +5 -5
- package/src/commands/agent-process-ownership.js +121 -0
- package/src/commands/agent.js +2 -0
- package/src/commands/automation.js +35 -8
- package/src/commands/hub.js +224 -0
- package/src/commands/project.js +162 -0
- package/src/data/changelog.json +26 -0
- package/src/gateways/ws/personal-data-hub-protocol.js +54 -8
- package/src/lib/audit-logger.js +59 -46
- package/src/lib/audit-sanitizer.js +279 -0
- package/src/lib/automation-center.js +14 -4
- package/src/lib/automation-engine.js +151 -39
- package/src/lib/checkpoint-restore-saga.js +11 -1
- package/src/lib/eval/verify01-host-evidence.js +36 -3
- package/src/lib/knowledge-graph.js +27 -0
- package/src/lib/personal-data-hub-wiring.js +44 -1
- package/src/lib/process-execution-broker/index.js +91 -1
- package/src/lib/process-execution-broker/platform-sandbox.js +42 -0
- package/src/lib/process-execution-broker/windows-native-evaluator-capabilities.js +757 -0
- package/src/lib/process-execution-broker/windows-native-evaluator.js +316 -0
- 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 +383 -11
- package/src/lib/scheduler-kernel/automation-adapter.js +15 -3
- package/src/lib/scheduler-kernel/automation-event-adapter.js +15 -3
- package/src/assets/web-panel/assets/devWarning-D90arbUg.js +0 -1
- package/src/assets/web-panel/assets/index-CeP1oROI.js +0 -1
- package/src/assets/web-panel/assets/index-Cu9gkyRc.js +0 -1
|
@@ -6,6 +6,8 @@ using System.IO;
|
|
|
6
6
|
using Microsoft.Win32.SafeHandles;
|
|
7
7
|
using System.Runtime.InteropServices;
|
|
8
8
|
using System.Security.Cryptography;
|
|
9
|
+
using System.Security.AccessControl;
|
|
10
|
+
using System.Security.Principal;
|
|
9
11
|
using System.Runtime.Serialization;
|
|
10
12
|
using System.Runtime.Serialization.Json;
|
|
11
13
|
using System.Text;
|
|
@@ -404,6 +406,45 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
404
406
|
private static extern Int32 DeleteAppContainerProfile(
|
|
405
407
|
string appContainerName);
|
|
406
408
|
|
|
409
|
+
[DllImport("FirewallAPI.dll")]
|
|
410
|
+
private static extern UInt32 NetworkIsolationGetAppContainerConfig(out UInt32 count, out IntPtr sids);
|
|
411
|
+
|
|
412
|
+
[DllImport("kernel32.dll")]
|
|
413
|
+
private static extern IntPtr GetProcessHeap();
|
|
414
|
+
|
|
415
|
+
[DllImport("kernel32.dll")]
|
|
416
|
+
[return: MarshalAs(UnmanagedType.Bool)]
|
|
417
|
+
private static extern bool HeapFree(IntPtr heap, UInt32 flags, IntPtr memory);
|
|
418
|
+
|
|
419
|
+
private static void AssertNoLoopbackExemption(IntPtr appSid)
|
|
420
|
+
{
|
|
421
|
+
UInt32 count;
|
|
422
|
+
IntPtr entries;
|
|
423
|
+
UInt32 result = NetworkIsolationGetAppContainerConfig(out count, out entries);
|
|
424
|
+
if (result != 0) throw new Win32Exception(checked((int)result), "Cannot attest AppContainer loopback exclusions");
|
|
425
|
+
// SID_AND_ATTRIBUTES contains a pointer and DWORD; x64 tail padding
|
|
426
|
+
// makes each entry two pointer widths. Free each SID and the array
|
|
427
|
+
// with the process heap, as documented by this API.
|
|
428
|
+
int stride = IntPtr.Size == 8 ? 16 : 8;
|
|
429
|
+
try
|
|
430
|
+
{
|
|
431
|
+
if (count > 65536 || (count > 0 && entries == IntPtr.Zero))
|
|
432
|
+
throw new InvalidDataException("Invalid AppContainer loopback configuration");
|
|
433
|
+
for (UInt32 index = 0; index < count; index++)
|
|
434
|
+
if (EqualSid(Marshal.ReadIntPtr(entries, checked((int)index * stride)), appSid))
|
|
435
|
+
throw new InvalidDataException("Native evaluator SID has a loopback exemption");
|
|
436
|
+
}
|
|
437
|
+
finally
|
|
438
|
+
{
|
|
439
|
+
if (entries != IntPtr.Zero)
|
|
440
|
+
{
|
|
441
|
+
for (UInt32 index = 0; index < Math.Min(count, 65536U); index++)
|
|
442
|
+
HeapFree(GetProcessHeap(), 0, Marshal.ReadIntPtr(entries, checked((int)index * stride)));
|
|
443
|
+
HeapFree(GetProcessHeap(), 0, entries);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
407
448
|
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
408
449
|
private static extern IntPtr _get_osfhandle(Int32 fileDescriptor);
|
|
409
450
|
|
|
@@ -584,6 +625,13 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
584
625
|
UInt32 desiredAccess,
|
|
585
626
|
out IntPtr token);
|
|
586
627
|
|
|
628
|
+
[DllImport("advapi32.dll", EntryPoint = "SetFileSecurityW", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
629
|
+
[return: MarshalAs(UnmanagedType.Bool)]
|
|
630
|
+
private static extern bool SetFileSecurity(
|
|
631
|
+
string path,
|
|
632
|
+
UInt32 securityInformation,
|
|
633
|
+
byte[] securityDescriptor);
|
|
634
|
+
|
|
587
635
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
588
636
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
589
637
|
private static extern bool CreateRestrictedToken(
|
|
@@ -995,7 +1043,7 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
995
1043
|
"restriction status");
|
|
996
1044
|
}
|
|
997
1045
|
|
|
998
|
-
private static bool TokenHasUnexpectedEnabledPrivileges(IntPtr token)
|
|
1046
|
+
private static bool TokenHasUnexpectedEnabledPrivileges(IntPtr token, bool includeDisabled = false)
|
|
999
1047
|
{
|
|
1000
1048
|
IntPtr privilegesBuffer = IntPtr.Zero;
|
|
1001
1049
|
try
|
|
@@ -1049,11 +1097,11 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
1049
1097
|
privilegeName.ToString(),
|
|
1050
1098
|
"SeChangeNotifyPrivilege",
|
|
1051
1099
|
StringComparison.Ordinal) &&
|
|
1052
|
-
(
|
|
1100
|
+
(includeDisabled || (
|
|
1053
1101
|
privilege.Attributes &
|
|
1054
1102
|
(
|
|
1055
1103
|
SE_PRIVILEGE_ENABLED |
|
|
1056
|
-
SE_PRIVILEGE_ENABLED_BY_DEFAULT)) != 0)
|
|
1104
|
+
SE_PRIVILEGE_ENABLED_BY_DEFAULT)) != 0))
|
|
1057
1105
|
{
|
|
1058
1106
|
return true;
|
|
1059
1107
|
}
|
|
@@ -1244,7 +1292,8 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
1244
1292
|
StringComparison.Ordinal))
|
|
1245
1293
|
{
|
|
1246
1294
|
throw new InvalidDataException(
|
|
1247
|
-
"Target AppContainer token retained an unexpected privilege"
|
|
1295
|
+
"Target AppContainer token retained an unexpected privilege: " + privilegeName +
|
|
1296
|
+
" (attributes=" + privilege.Attributes + ")");
|
|
1248
1297
|
}
|
|
1249
1298
|
}
|
|
1250
1299
|
return SidToString(actualAppContainerSid);
|
|
@@ -2102,6 +2151,7 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
2102
2151
|
string finalPath,
|
|
2103
2152
|
FILE_ID_INFO handleIdentity,
|
|
2104
2153
|
UInt64 handlePathStatFileId,
|
|
2154
|
+
bool allowDirectory,
|
|
2105
2155
|
out NodeFileIdentityProjection fixedProjection,
|
|
2106
2156
|
out NodeFileIdentityProjection node22Projection)
|
|
2107
2157
|
{
|
|
@@ -2131,8 +2181,10 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
2131
2181
|
}
|
|
2132
2182
|
|
|
2133
2183
|
UInt64 pathStatFileId = unchecked((UInt64)information.FileId);
|
|
2184
|
+
// Evaluator guards also attest directories. Keep the caller's
|
|
2185
|
+
// type restriction consistent across fast and legacy stat paths.
|
|
2134
2186
|
if (
|
|
2135
|
-
(information.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ||
|
|
2187
|
+
(!allowDirectory && (information.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) ||
|
|
2136
2188
|
(information.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 ||
|
|
2137
2189
|
information.VolumeSerialNumber !=
|
|
2138
2190
|
handleIdentity.VolumeSerialNumber ||
|
|
@@ -2165,13 +2217,14 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
2165
2217
|
}
|
|
2166
2218
|
|
|
2167
2219
|
private static LaunchPathFileIdentity ReadLaunchPathFileIdentity(
|
|
2168
|
-
IntPtr handle
|
|
2220
|
+
IntPtr handle,
|
|
2221
|
+
bool allowDirectory = false)
|
|
2169
2222
|
{
|
|
2170
2223
|
BY_HANDLE_FILE_INFORMATION basic;
|
|
2171
2224
|
if (!GetFileInformationByHandle(handle, out basic))
|
|
2172
2225
|
ThrowLastError("GetFileInformationByHandle(launch path)");
|
|
2173
2226
|
if (
|
|
2174
|
-
(basic.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ||
|
|
2227
|
+
(!allowDirectory && (basic.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) ||
|
|
2175
2228
|
(basic.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
|
|
2176
2229
|
{
|
|
2177
2230
|
throw new InvalidDataException(
|
|
@@ -2201,6 +2254,7 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
2201
2254
|
finalPath,
|
|
2202
2255
|
fileId,
|
|
2203
2256
|
handlePathStatFileId,
|
|
2257
|
+
allowDirectory,
|
|
2204
2258
|
out fixedFastNodeIdentity,
|
|
2205
2259
|
out node22FastNodeIdentity);
|
|
2206
2260
|
}
|
|
@@ -3203,6 +3257,248 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3203
3257
|
}
|
|
3204
3258
|
}
|
|
3205
3259
|
|
|
3260
|
+
[DataContract]
|
|
3261
|
+
public sealed class EvaluatorPathSpec
|
|
3262
|
+
{
|
|
3263
|
+
[DataMember] public string path { get; set; }
|
|
3264
|
+
[DataMember] public string dev { get; set; }
|
|
3265
|
+
[DataMember] public string ino { get; set; }
|
|
3266
|
+
[DataMember] public long bytes { get; set; }
|
|
3267
|
+
[DataMember] public string sha256 { get; set; }
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
[DataContract]
|
|
3271
|
+
public sealed class NativeEvaluatorSpec
|
|
3272
|
+
{
|
|
3273
|
+
[DataMember] public int version { get; set; }
|
|
3274
|
+
[DataMember] public string root { get; set; }
|
|
3275
|
+
[DataMember] public string workspace { get; set; }
|
|
3276
|
+
[DataMember] public string control { get; set; }
|
|
3277
|
+
[DataMember] public string scratch { get; set; }
|
|
3278
|
+
[DataMember] public string check { get; set; }
|
|
3279
|
+
[DataMember] public int wallTimeMs { get; set; }
|
|
3280
|
+
[DataMember] public string manifestDigest { get; set; }
|
|
3281
|
+
[DataMember] public EvaluatorPathSpec runtime { get; set; }
|
|
3282
|
+
[DataMember] public EvaluatorPathSpec[] directories { get; set; }
|
|
3283
|
+
[DataMember] public EvaluatorPathSpec[] files { get; set; }
|
|
3284
|
+
}
|
|
3285
|
+
|
|
3286
|
+
private static bool SameEvaluatorPath(string left, string right)
|
|
3287
|
+
{
|
|
3288
|
+
return String.Equals(Path.GetFullPath(left), Path.GetFullPath(right), StringComparison.OrdinalIgnoreCase);
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
private static IntPtr HoldEvaluatorPath(string file, bool directory, List<IntPtr> guards)
|
|
3292
|
+
{
|
|
3293
|
+
ValidateExistingLocalPath(file, "Native evaluator path", false);
|
|
3294
|
+
SECURITY_ATTRIBUTES attributes = new SECURITY_ATTRIBUTES();
|
|
3295
|
+
attributes.nLength = checked((UInt32)Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)));
|
|
3296
|
+
// Directory handles block rename/deletion; read-only file handles
|
|
3297
|
+
// block writes and deletion for the complete target Job lifetime.
|
|
3298
|
+
IntPtr handle = CreateFile(file, directory ? FILE_READ_ATTRIBUTES : GENERIC_READ,
|
|
3299
|
+
directory ? FILE_SHARE_READ | FILE_SHARE_WRITE : FILE_SHARE_READ,
|
|
3300
|
+
ref attributes, OPEN_EXISTING, directory ? 0x02200000U : 0x00200000U, IntPtr.Zero);
|
|
3301
|
+
if (IsInvalidHandle(handle)) ThrowLastError("CreateFile(native evaluator guard)");
|
|
3302
|
+
guards.Add(handle);
|
|
3303
|
+
return handle;
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3306
|
+
private static void VerifyEvaluatorPath(EvaluatorPathSpec expected, IntPtr handle, bool directory)
|
|
3307
|
+
{
|
|
3308
|
+
LaunchPathFileIdentity actual = ReadLaunchPathFileIdentity(handle, directory);
|
|
3309
|
+
UInt64 device, inode;
|
|
3310
|
+
if (!UInt64.TryParse(expected.dev, out device) || !UInt64.TryParse(expected.ino, out inode) ||
|
|
3311
|
+
!MatchesExpectedNodeFileIdentity(actual, device, inode) ||
|
|
3312
|
+
!SameEvaluatorPath(NormalizeFinalPath(actual.FinalPath), expected.path) ||
|
|
3313
|
+
(((actual.Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) != directory))
|
|
3314
|
+
throw new InvalidDataException("Native evaluator path identity changed");
|
|
3315
|
+
if (directory) return;
|
|
3316
|
+
if (actual.Links != 1 || actual.Bytes != (UInt64)expected.bytes || !IsLowercaseSha256(expected.sha256))
|
|
3317
|
+
throw new InvalidDataException("Native evaluator file identity or link count changed");
|
|
3318
|
+
using (SafeFileHandle safe = new SafeFileHandle(handle, false))
|
|
3319
|
+
using (FileStream stream = new FileStream(safe, FileAccess.Read))
|
|
3320
|
+
using (SHA256 algorithm = SHA256.Create())
|
|
3321
|
+
{
|
|
3322
|
+
string digest = BitConverter.ToString(algorithm.ComputeHash(stream)).Replace("-", "").ToLowerInvariant();
|
|
3323
|
+
if (digest != expected.sha256) throw new InvalidDataException("Native evaluator file digest changed");
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
|
|
3327
|
+
private static void PrepareNativeEvaluator(NativeEvaluatorSpec spec, string application,
|
|
3328
|
+
string[] arguments, string workingDirectory, string appSid, int wallTimeMs,
|
|
3329
|
+
List<IntPtr> guards, ref bool rootAttested)
|
|
3330
|
+
{
|
|
3331
|
+
if (spec.version != 1 || !IsLowercaseSha256(spec.manifestDigest) || spec.runtime == null ||
|
|
3332
|
+
spec.directories == null || spec.directories.Length < 4 || spec.directories.Length > 128 ||
|
|
3333
|
+
spec.files == null || spec.files.Length < 2 || spec.files.Length > 65 ||
|
|
3334
|
+
wallTimeMs < 1 || spec.wallTimeMs != wallTimeMs || String.IsNullOrWhiteSpace(appSid))
|
|
3335
|
+
throw new InvalidDataException("Native evaluator manifest is incomplete");
|
|
3336
|
+
string root = NormalizeLocalDosPath(spec.root, null, "Native evaluator stage");
|
|
3337
|
+
string expectedParent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Temp");
|
|
3338
|
+
if (!SameEvaluatorPath(Path.GetDirectoryName(root), expectedParent) ||
|
|
3339
|
+
!System.Text.RegularExpressions.Regex.IsMatch(Path.GetFileName(root), "^cc-native-evaluator-[A-Za-z0-9_-]{6}$") ||
|
|
3340
|
+
!SameEvaluatorPath(spec.workspace, Path.Combine(root, "workspace")) ||
|
|
3341
|
+
!SameEvaluatorPath(spec.control, Path.Combine(root, "control")) ||
|
|
3342
|
+
!SameEvaluatorPath(spec.scratch, Path.Combine(root, "scratch")) ||
|
|
3343
|
+
!SameEvaluatorPath(spec.check, Path.Combine(spec.control, "check.cjs")) ||
|
|
3344
|
+
!SameEvaluatorPath(spec.runtime.path, Path.Combine(spec.control, "node.exe")) ||
|
|
3345
|
+
!SameEvaluatorPath(application, spec.runtime.path) || arguments.Length != 5 ||
|
|
3346
|
+
arguments[0] != "--preserve-symlinks" || arguments[1] != "--preserve-symlinks-main" ||
|
|
3347
|
+
!SameEvaluatorPath(arguments[2], spec.check) || !SameEvaluatorPath(arguments[3], spec.workspace) ||
|
|
3348
|
+
!SameEvaluatorPath(arguments[4], spec.scratch) || !SameEvaluatorPath(workingDirectory, spec.scratch) ||
|
|
3349
|
+
!SameEvaluatorPath(spec.directories[0].path, root))
|
|
3350
|
+
throw new InvalidDataException("Native evaluator launch or private stage binding changed");
|
|
3351
|
+
string ancestor = Path.GetPathRoot(root);
|
|
3352
|
+
foreach (string part in root.Substring(ancestor.Length).Split(Path.DirectorySeparatorChar))
|
|
3353
|
+
{
|
|
3354
|
+
ancestor = Path.Combine(ancestor, part);
|
|
3355
|
+
if (!SameEvaluatorPath(ancestor, root)) HoldEvaluatorPath(ancestor, true, guards);
|
|
3356
|
+
}
|
|
3357
|
+
HashSet<string> expected = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
3358
|
+
foreach (EvaluatorPathSpec directory in spec.directories)
|
|
3359
|
+
{
|
|
3360
|
+
string full = Path.GetFullPath(directory.path);
|
|
3361
|
+
if ((!SameEvaluatorPath(full, root) && !full.StartsWith(root + "\\", StringComparison.OrdinalIgnoreCase)) || !expected.Add(full))
|
|
3362
|
+
throw new InvalidDataException("Native evaluator directory is outside the private stage or duplicated");
|
|
3363
|
+
VerifyEvaluatorPath(directory, HoldEvaluatorPath(full, true, guards), true);
|
|
3364
|
+
if (SameEvaluatorPath(full, root)) rootAttested = true;
|
|
3365
|
+
}
|
|
3366
|
+
long total = 0;
|
|
3367
|
+
foreach (EvaluatorPathSpec file in spec.files)
|
|
3368
|
+
{
|
|
3369
|
+
string full = Path.GetFullPath(file.path);
|
|
3370
|
+
if ((!full.StartsWith(spec.workspace + "\\", StringComparison.OrdinalIgnoreCase) && !SameEvaluatorPath(full, spec.check)) ||
|
|
3371
|
+
!expected.Add(full) || file.bytes < 0 || file.bytes > 1024 * 1024)
|
|
3372
|
+
throw new InvalidDataException("Native evaluator file is outside its read-only roots or exceeds bounds");
|
|
3373
|
+
total = checked(total + file.bytes);
|
|
3374
|
+
if (total > 8 * 1024 * 1024) throw new InvalidDataException("Native evaluator tree exceeds byte bound");
|
|
3375
|
+
VerifyEvaluatorPath(file, HoldEvaluatorPath(full, false, guards), false);
|
|
3376
|
+
}
|
|
3377
|
+
if (!expected.Contains(spec.check) || !expected.Contains(spec.workspace) || !expected.Contains(spec.control) || !expected.Contains(spec.scratch))
|
|
3378
|
+
throw new InvalidDataException("Native evaluator manifest omits a required path");
|
|
3379
|
+
if (spec.runtime.bytes < 1 || spec.runtime.bytes > 128 * 1024 * 1024 || !expected.Add(spec.runtime.path))
|
|
3380
|
+
throw new InvalidDataException("Native evaluator runtime exceeds byte bound or duplicates a path");
|
|
3381
|
+
VerifyEvaluatorPath(spec.runtime, HoldEvaluatorPath(application, false, guards), false);
|
|
3382
|
+
foreach (EvaluatorPathSpec directory in spec.directories)
|
|
3383
|
+
foreach (string child in Directory.GetFileSystemEntries(directory.path))
|
|
3384
|
+
if (!expected.Contains(child)) throw new InvalidDataException("Native evaluator tree has an unlisted entry");
|
|
3385
|
+
if (Directory.GetFileSystemEntries(spec.scratch).Length != 0)
|
|
3386
|
+
throw new InvalidDataException("Native evaluator scratch must start empty");
|
|
3387
|
+
SecurityIdentifier sid = new SecurityIdentifier(appSid);
|
|
3388
|
+
SecurityIdentifier owner = WindowsIdentity.GetCurrent().User;
|
|
3389
|
+
SecurityIdentifier system = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
|
|
3390
|
+
foreach (EvaluatorPathSpec directory in spec.directories)
|
|
3391
|
+
{
|
|
3392
|
+
DirectorySecurity security = new DirectorySecurity();
|
|
3393
|
+
security.SetAccessRuleProtection(true, false);
|
|
3394
|
+
security.AddAccessRule(new FileSystemAccessRule(owner, FileSystemRights.FullControl,
|
|
3395
|
+
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
|
|
3396
|
+
security.AddAccessRule(new FileSystemAccessRule(system, FileSystemRights.FullControl,
|
|
3397
|
+
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
|
|
3398
|
+
bool scratch = SameEvaluatorPath(directory.path, spec.scratch);
|
|
3399
|
+
security.AddAccessRule(new FileSystemAccessRule(sid,
|
|
3400
|
+
scratch ? FileSystemRights.Modify : FileSystemRights.ReadAndExecute,
|
|
3401
|
+
scratch ? InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit : InheritanceFlags.None,
|
|
3402
|
+
PropagationFlags.None, AccessControlType.Allow));
|
|
3403
|
+
SetEvaluatorAccessControl(directory.path, security);
|
|
3404
|
+
}
|
|
3405
|
+
foreach (EvaluatorPathSpec file in spec.files)
|
|
3406
|
+
{
|
|
3407
|
+
FileSecurity security = new FileSecurity();
|
|
3408
|
+
security.SetAccessRuleProtection(true, false);
|
|
3409
|
+
security.AddAccessRule(new FileSystemAccessRule(owner, FileSystemRights.FullControl, AccessControlType.Allow));
|
|
3410
|
+
security.AddAccessRule(new FileSystemAccessRule(system, FileSystemRights.FullControl, AccessControlType.Allow));
|
|
3411
|
+
security.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.ReadAndExecute, AccessControlType.Allow));
|
|
3412
|
+
SetEvaluatorAccessControl(file.path, security);
|
|
3413
|
+
}
|
|
3414
|
+
FileSecurity runtimeSecurity = new FileSecurity();
|
|
3415
|
+
runtimeSecurity.SetAccessRuleProtection(true, false);
|
|
3416
|
+
runtimeSecurity.AddAccessRule(new FileSystemAccessRule(owner, FileSystemRights.FullControl, AccessControlType.Allow));
|
|
3417
|
+
runtimeSecurity.AddAccessRule(new FileSystemAccessRule(system, FileSystemRights.FullControl, AccessControlType.Allow));
|
|
3418
|
+
runtimeSecurity.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.ReadAndExecute, AccessControlType.Allow));
|
|
3419
|
+
SetEvaluatorAccessControl(spec.runtime.path, runtimeSecurity);
|
|
3420
|
+
}
|
|
3421
|
+
|
|
3422
|
+
private static void SetEvaluatorAccessControl(string path, FileSystemSecurity security)
|
|
3423
|
+
{
|
|
3424
|
+
// Directory/File.SetAccessControl exist only in .NET Framework.
|
|
3425
|
+
// Persist the same protected DACL through Win32 so the byte-loaded
|
|
3426
|
+
// assembly enforces identical ACLs in Windows PowerShell and pwsh.
|
|
3427
|
+
if (!security.AreAccessRulesProtected)
|
|
3428
|
+
throw new InvalidDataException("Native evaluator DACL must be protected");
|
|
3429
|
+
const UInt32 DACL_SECURITY_INFORMATION = 0x00000004;
|
|
3430
|
+
const UInt32 PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000;
|
|
3431
|
+
if (!SetFileSecurity(path,
|
|
3432
|
+
DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
|
|
3433
|
+
security.GetSecurityDescriptorBinaryForm()))
|
|
3434
|
+
ThrowLastError("SetFileSecurity(native evaluator protected DACL)");
|
|
3435
|
+
}
|
|
3436
|
+
|
|
3437
|
+
// This timer belongs to the native supervisor, not the JavaScript
|
|
3438
|
+
// caller. It also covers a target that stops reading its entry pipe.
|
|
3439
|
+
// The gate prevents a queued callback from touching a closed/reused
|
|
3440
|
+
// Job handle after Dispose. Cleanup still requires an empty-Job fence.
|
|
3441
|
+
private sealed class JobWallTimeWatchdog : IDisposable
|
|
3442
|
+
{
|
|
3443
|
+
private readonly object gate = new object();
|
|
3444
|
+
private readonly IntPtr job;
|
|
3445
|
+
private readonly int milliseconds;
|
|
3446
|
+
private readonly System.Diagnostics.Stopwatch clock;
|
|
3447
|
+
private readonly Timer timer;
|
|
3448
|
+
private bool stopped;
|
|
3449
|
+
private bool expired;
|
|
3450
|
+
private int terminationError;
|
|
3451
|
+
|
|
3452
|
+
public JobWallTimeWatchdog(IntPtr jobHandle, int wallTimeMs)
|
|
3453
|
+
{
|
|
3454
|
+
job = jobHandle;
|
|
3455
|
+
milliseconds = wallTimeMs;
|
|
3456
|
+
clock = System.Diagnostics.Stopwatch.StartNew();
|
|
3457
|
+
timer = new Timer(Expire, null, wallTimeMs, Timeout.Infinite);
|
|
3458
|
+
}
|
|
3459
|
+
|
|
3460
|
+
private void Expire(object state)
|
|
3461
|
+
{
|
|
3462
|
+
lock (gate)
|
|
3463
|
+
{
|
|
3464
|
+
if (stopped) return;
|
|
3465
|
+
expired = true;
|
|
3466
|
+
if (!TerminateJobObject(job, 125))
|
|
3467
|
+
terminationError = Marshal.GetLastWin32Error();
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
|
|
3471
|
+
public UInt32 RemainingMilliseconds
|
|
3472
|
+
{
|
|
3473
|
+
get
|
|
3474
|
+
{
|
|
3475
|
+
return checked((UInt32)Math.Max(
|
|
3476
|
+
0L, milliseconds - clock.ElapsedMilliseconds));
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
public void ThrowIfExpired()
|
|
3481
|
+
{
|
|
3482
|
+
lock (gate)
|
|
3483
|
+
{
|
|
3484
|
+
if (expired || clock.ElapsedMilliseconds >= milliseconds)
|
|
3485
|
+
throw new TimeoutException(
|
|
3486
|
+
"Windows sandbox wall-time limit exceeded" +
|
|
3487
|
+
(terminationError == 0 ? String.Empty :
|
|
3488
|
+
" (Job termination error " + terminationError + ")"));
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
|
|
3492
|
+
public void Dispose()
|
|
3493
|
+
{
|
|
3494
|
+
lock (gate)
|
|
3495
|
+
{
|
|
3496
|
+
stopped = true;
|
|
3497
|
+
timer.Dispose();
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
|
|
3206
3502
|
public static int Run(
|
|
3207
3503
|
string application,
|
|
3208
3504
|
string[] arguments,
|
|
@@ -3222,8 +3518,12 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3222
3518
|
LaunchPathLockSpec[] launchPathLockSpecs,
|
|
3223
3519
|
byte[] entrySnapshotOverride,
|
|
3224
3520
|
string snapshotTestGateToken,
|
|
3225
|
-
string snapshotTestGateReleasePath
|
|
3521
|
+
string snapshotTestGateReleasePath,
|
|
3522
|
+
int wallTimeMs = 0,
|
|
3523
|
+
NativeEvaluatorSpec nativeEvaluator = null)
|
|
3226
3524
|
{
|
|
3525
|
+
if (wallTimeMs < 0 || wallTimeMs > 3600000)
|
|
3526
|
+
throw new ArgumentOutOfRangeException("wallTimeMs");
|
|
3227
3527
|
targetEnvironment =
|
|
3228
3528
|
targetEnvironment ?? CaptureCurrentEnvironment();
|
|
3229
3529
|
workingDirectory = NormalizeLocalDosPath(
|
|
@@ -3290,6 +3590,9 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3290
3590
|
bool targetExited = false;
|
|
3291
3591
|
int targetExitCode = 125;
|
|
3292
3592
|
Exception launchError = null;
|
|
3593
|
+
JobWallTimeWatchdog wallTimeWatchdog = null;
|
|
3594
|
+
List<IntPtr> evaluatorGuards = new List<IntPtr>();
|
|
3595
|
+
bool evaluatorRootAttested = false;
|
|
3293
3596
|
|
|
3294
3597
|
try
|
|
3295
3598
|
{
|
|
@@ -3359,6 +3662,19 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3359
3662
|
}
|
|
3360
3663
|
ConfigureAppContainerEnvironment(targetEnvironment);
|
|
3361
3664
|
}
|
|
3665
|
+
if (nativeEvaluator != null)
|
|
3666
|
+
{
|
|
3667
|
+
if (!useAppContainer || nodeIpcFd >= 0 || detached || entrySnapshot != null)
|
|
3668
|
+
throw new InvalidDataException("Native evaluator requires a synchronous AppContainer launch");
|
|
3669
|
+
AssertNoLoopbackExemption(appContainerSid);
|
|
3670
|
+
PrepareNativeEvaluator(nativeEvaluator, application, arguments, workingDirectory,
|
|
3671
|
+
expectedAppContainerSid, wallTimeMs, evaluatorGuards, ref evaluatorRootAttested);
|
|
3672
|
+
targetEnvironment = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
3673
|
+
targetEnvironment["SystemRoot"] = Path.GetDirectoryName(Environment.SystemDirectory);
|
|
3674
|
+
targetEnvironment["WINDIR"] = Path.GetDirectoryName(Environment.SystemDirectory);
|
|
3675
|
+
targetEnvironment["PATH"] = Path.GetDirectoryName(application);
|
|
3676
|
+
ConfigureAppContainerEnvironment(targetEnvironment);
|
|
3677
|
+
}
|
|
3362
3678
|
environmentBuffer =
|
|
3363
3679
|
BuildEnvironmentBlock(targetEnvironment);
|
|
3364
3680
|
|
|
@@ -3387,8 +3703,12 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3387
3703
|
// an exact primary-token duplicate instead of filtering again.
|
|
3388
3704
|
bool sourceTokenWasFiltered =
|
|
3389
3705
|
TokenWasFiltered(sourceToken);
|
|
3706
|
+
// A UAC-filtered token can retain disabled privileges. The
|
|
3707
|
+
// AppContainer attestation requires their removal, not merely
|
|
3708
|
+
// that they are disabled. Compatibility workers retain their
|
|
3709
|
+
// existing enabled-only predicate for nested token support.
|
|
3390
3710
|
bool sourceTokenHasUnexpectedEnabledPrivileges =
|
|
3391
|
-
TokenHasUnexpectedEnabledPrivileges(sourceToken);
|
|
3711
|
+
TokenHasUnexpectedEnabledPrivileges(sourceToken, useAppContainer);
|
|
3392
3712
|
bool sourceTokenHasEnabledAdministratorSid =
|
|
3393
3713
|
disableAdministratorSids &&
|
|
3394
3714
|
TokenHasEnabledAdministratorSid(sourceToken);
|
|
@@ -3627,6 +3947,8 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3627
3947
|
// atomic handoff; release the stream guards before resume so
|
|
3628
3948
|
// target code cannot deadlock on a break owned by the helper.
|
|
3629
3949
|
ReleaseLaunchPathLocks(launchPathLocks);
|
|
3950
|
+
if (wallTimeMs > 0)
|
|
3951
|
+
wallTimeWatchdog = new JobWallTimeWatchdog(job, wallTimeMs);
|
|
3630
3952
|
if (ResumeThread(processInfo.hThread) == UInt32.MaxValue)
|
|
3631
3953
|
{
|
|
3632
3954
|
TerminateProcess(processInfo.hProcess, 125);
|
|
@@ -3668,7 +3990,13 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3668
3990
|
|
|
3669
3991
|
UInt32 targetWait = WaitForSingleObject(
|
|
3670
3992
|
processInfo.hProcess,
|
|
3671
|
-
INFINITE
|
|
3993
|
+
wallTimeWatchdog == null ? INFINITE :
|
|
3994
|
+
wallTimeWatchdog.RemainingMilliseconds);
|
|
3995
|
+
if (targetWait == WAIT_TIMEOUT && wallTimeWatchdog != null)
|
|
3996
|
+
throw new TimeoutException(
|
|
3997
|
+
"Windows sandbox wall-time limit exceeded");
|
|
3998
|
+
if (wallTimeWatchdog != null)
|
|
3999
|
+
wallTimeWatchdog.ThrowIfExpired();
|
|
3672
4000
|
if (targetWait != WAIT_OBJECT_0)
|
|
3673
4001
|
ThrowLastError("WaitForSingleObject(target)");
|
|
3674
4002
|
targetExited = true;
|
|
@@ -3684,6 +4012,12 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3684
4012
|
finally
|
|
3685
4013
|
{
|
|
3686
4014
|
Exception cleanupError = null;
|
|
4015
|
+
if (wallTimeWatchdog != null)
|
|
4016
|
+
{
|
|
4017
|
+
wallTimeWatchdog.Dispose();
|
|
4018
|
+
try { wallTimeWatchdog.ThrowIfExpired(); }
|
|
4019
|
+
catch (TimeoutException error) { launchError = error; }
|
|
4020
|
+
}
|
|
3687
4021
|
if (processInfo.hProcess != IntPtr.Zero && !targetExited)
|
|
3688
4022
|
TerminateProcess(processInfo.hProcess, 125);
|
|
3689
4023
|
if (job != IntPtr.Zero)
|
|
@@ -3742,6 +4076,11 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3742
4076
|
foreach (IntPtr handle in ownedStandardHandles)
|
|
3743
4077
|
CloseHandle(handle);
|
|
3744
4078
|
if (limitBuffer != IntPtr.Zero) Marshal.FreeHGlobal(limitBuffer);
|
|
4079
|
+
if (nativeEvaluator != null && !IsInvalidHandle(appContainerSid))
|
|
4080
|
+
{
|
|
4081
|
+
try { AssertNoLoopbackExemption(appContainerSid); }
|
|
4082
|
+
catch (Exception error) { cleanupError = error; }
|
|
4083
|
+
}
|
|
3745
4084
|
if (!IsInvalidHandle(appContainerSid)) FreeSid(appContainerSid);
|
|
3746
4085
|
if (restrictedToken != IntPtr.Zero) CloseHandle(restrictedToken);
|
|
3747
4086
|
if (sourceToken != IntPtr.Zero) CloseHandle(sourceToken);
|
|
@@ -3776,11 +4115,38 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3776
4115
|
launchError,
|
|
3777
4116
|
cleanupError);
|
|
3778
4117
|
}
|
|
4118
|
+
if (nativeEvaluator != null && evaluatorRootAttested && cleanupError == null)
|
|
4119
|
+
{
|
|
4120
|
+
try
|
|
4121
|
+
{
|
|
4122
|
+
PublishTargetIdentity(Path.Combine(nativeEvaluator.root, "settlement.json"),
|
|
4123
|
+
JsonCodec.SerializeObject("manifestDigest", nativeEvaluator.manifestDigest,
|
|
4124
|
+
"cleanupConfirmed", true, "capabilityCount", 0,
|
|
4125
|
+
"loopbackExemptionAbsent", true,
|
|
4126
|
+
"targetPid", processInfo.dwProcessId,
|
|
4127
|
+
"appContainerSid", expectedAppContainerSid,
|
|
4128
|
+
"wallTimeMs", wallTimeMs,
|
|
4129
|
+
"targetExitCode", targetExitCode,
|
|
4130
|
+
"supervisorUserSidSha256", HashEvaluatorUserSid(),
|
|
4131
|
+
"executionFailed", launchError != null));
|
|
4132
|
+
}
|
|
4133
|
+
catch (Exception error) { launchError = error; }
|
|
4134
|
+
}
|
|
4135
|
+
foreach (IntPtr guard in evaluatorGuards) CloseHandle(guard);
|
|
4136
|
+
evaluatorGuards.Clear();
|
|
3779
4137
|
}
|
|
3780
4138
|
if (launchError != null)
|
|
3781
4139
|
throw launchError;
|
|
3782
4140
|
return targetExitCode;
|
|
3783
4141
|
}
|
|
4142
|
+
|
|
4143
|
+
private static string HashEvaluatorUserSid()
|
|
4144
|
+
{
|
|
4145
|
+
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
|
|
4146
|
+
using (SHA256 algorithm = SHA256.Create())
|
|
4147
|
+
return BitConverter.ToString(algorithm.ComputeHash(Encoding.UTF8.GetBytes(identity.User.Value)))
|
|
4148
|
+
.Replace("-", "").ToLowerInvariant();
|
|
4149
|
+
}
|
|
3784
4150
|
}
|
|
3785
4151
|
|
|
3786
4152
|
public static class Program
|
|
@@ -3791,6 +4157,10 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
3791
4157
|
[DataContract]
|
|
3792
4158
|
public sealed class LaunchSpec
|
|
3793
4159
|
{
|
|
4160
|
+
[DataMember]
|
|
4161
|
+
public Native.NativeEvaluatorSpec nativeEvaluator { get; set; }
|
|
4162
|
+
[DataMember]
|
|
4163
|
+
public int wallTimeMs { get; set; }
|
|
3794
4164
|
[DataMember]
|
|
3795
4165
|
public int cpuSeconds { get; set; }
|
|
3796
4166
|
[DataMember]
|
|
@@ -4159,7 +4529,9 @@ namespace ChainlessChain.WindowsSandbox
|
|
|
4159
4529
|
spec.launchPathLocks,
|
|
4160
4530
|
null,
|
|
4161
4531
|
spec.snapshotTestGateToken,
|
|
4162
|
-
spec.snapshotTestGateReleasePath
|
|
4532
|
+
spec.snapshotTestGateReleasePath,
|
|
4533
|
+
spec.wallTimeMs,
|
|
4534
|
+
spec.nativeEvaluator);
|
|
4163
4535
|
}
|
|
4164
4536
|
catch (Exception error)
|
|
4165
4537
|
{
|
|
@@ -779,7 +779,7 @@ function existingExecutionResult(db, occurrence, expected, now) {
|
|
|
779
779
|
}
|
|
780
780
|
if (execution.status !== EXECUTION_STATUS.SUCCESS) {
|
|
781
781
|
throw automationError(
|
|
782
|
-
|
|
782
|
+
executionFailureCode(execution.status),
|
|
783
783
|
`Automation execution did not succeed: ${execution.id}`,
|
|
784
784
|
{ executionId: execution.id, status: execution.status },
|
|
785
785
|
);
|
|
@@ -790,6 +790,14 @@ function existingExecutionResult(db, occurrence, expected, now) {
|
|
|
790
790
|
return execution;
|
|
791
791
|
}
|
|
792
792
|
|
|
793
|
+
function executionFailureCode(status) {
|
|
794
|
+
if (status === EXECUTION_STATUS.UNSUPPORTED)
|
|
795
|
+
return "AUTOMATION_EXECUTION_UNSUPPORTED";
|
|
796
|
+
if (status === EXECUTION_STATUS.SIMULATED)
|
|
797
|
+
return "AUTOMATION_EXECUTION_SIMULATED";
|
|
798
|
+
return "AUTOMATION_SCHEDULER_EXECUTION_FAILED";
|
|
799
|
+
}
|
|
800
|
+
|
|
793
801
|
export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
|
|
794
802
|
if (!db || typeof db.prepare !== "function") {
|
|
795
803
|
throw automationError(
|
|
@@ -930,9 +938,13 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
|
|
|
930
938
|
}
|
|
931
939
|
if (execution.status !== EXECUTION_STATUS.SUCCESS) {
|
|
932
940
|
throw automationError(
|
|
933
|
-
|
|
941
|
+
executionFailureCode(execution.status),
|
|
934
942
|
`Automation execution failed: ${execution.id}`,
|
|
935
|
-
{
|
|
943
|
+
{
|
|
944
|
+
executionId: execution.id,
|
|
945
|
+
status: execution.status,
|
|
946
|
+
error: execution.error,
|
|
947
|
+
},
|
|
936
948
|
);
|
|
937
949
|
}
|
|
938
950
|
resolveAutomationExecutionIncidentsForSucceededRun(db, execution.id, {
|
|
@@ -576,7 +576,7 @@ function existingExecutionResult(db, occurrence, expectedFlow, now) {
|
|
|
576
576
|
}
|
|
577
577
|
if (execution.status !== EXECUTION_STATUS.SUCCESS) {
|
|
578
578
|
throw eventError(
|
|
579
|
-
|
|
579
|
+
executionFailureCode(execution.status),
|
|
580
580
|
`automation event execution did not succeed: ${execution.id}`,
|
|
581
581
|
{ executionId: execution.id, status: execution.status },
|
|
582
582
|
);
|
|
@@ -587,6 +587,14 @@ function existingExecutionResult(db, occurrence, expectedFlow, now) {
|
|
|
587
587
|
return execution;
|
|
588
588
|
}
|
|
589
589
|
|
|
590
|
+
function executionFailureCode(status) {
|
|
591
|
+
if (status === EXECUTION_STATUS.UNSUPPORTED)
|
|
592
|
+
return "AUTOMATION_EXECUTION_UNSUPPORTED";
|
|
593
|
+
if (status === EXECUTION_STATUS.SIMULATED)
|
|
594
|
+
return "AUTOMATION_EXECUTION_SIMULATED";
|
|
595
|
+
return "AUTOMATION_EVENT_EXECUTION_FAILED";
|
|
596
|
+
}
|
|
597
|
+
|
|
590
598
|
export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
|
|
591
599
|
if (!db || typeof db.prepare !== "function") {
|
|
592
600
|
throw eventError(
|
|
@@ -729,9 +737,13 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
|
|
|
729
737
|
}
|
|
730
738
|
if (execution.status !== EXECUTION_STATUS.SUCCESS) {
|
|
731
739
|
throw eventError(
|
|
732
|
-
|
|
740
|
+
executionFailureCode(execution.status),
|
|
733
741
|
`automation event execution failed: ${execution.id}`,
|
|
734
|
-
{
|
|
742
|
+
{
|
|
743
|
+
executionId: execution.id,
|
|
744
|
+
status: execution.status,
|
|
745
|
+
error: execution.error,
|
|
746
|
+
},
|
|
735
747
|
);
|
|
736
748
|
}
|
|
737
749
|
resolveAutomationExecutionIncidentsForSucceededRun(db, execution.id, {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Q as r}from"./index-ClsJN8sW.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as o}from"./Row-4Jj6JyXN.js";import{a0 as t}from"./index-ClsJN8sW.js";import"./vendor-Bn1JzzAn.js";import"./responsiveObserve-B4xDxO7Q.js";import"./useFlexGapSupport-WChWQURv.js";import"./styleChecker-BYOJOyqL.js";import"./index-KWt8Owo8.js";import"./icons-DG5UD-6K.js";const l=t(o);export{l as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-4M6bKRRO.js";import{a0 as t}from"./index-ClsJN8sW.js";import"./vendor-Bn1JzzAn.js";import"./index-KWt8Owo8.js";import"./icons-DG5UD-6K.js";const s=t(o);export{s as default};
|