@holoscript/holosystem 0.2.3 → 0.2.4

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 CHANGED
@@ -511,6 +511,16 @@ AMD64 host, `qemu-system-x86_64.exe`, q35, 128 MiB, one CPU, and exactly two
511
511
  launches. Plans cannot provide a command, argument, environment variable,
512
512
  device, network, firmware, monitor, display, or fallback setting.
513
513
 
514
+ `vm-launch-whpx-sandboxed` is a third, separately named vocabulary. It retains
515
+ the explicit WHPX contract and additionally launches QEMU through the measured
516
+ Windows helper shipped in this package. The helper creates a
517
+ `CreateRestrictedToken(DISABLE_MAX_PRIVILEGE)` filtered token, lowers it to low
518
+ integrity, admits at most the single Windows pass-through privilege, creates
519
+ the process suspended with an explicit three-handle allowlist, assigns it to a
520
+ kill-on-close Job Object with one-process, memory, and UI restrictions, and
521
+ only then resumes it. A private low-integrity temporary directory is the only
522
+ intended writable launch location.
523
+
514
524
  First measure the complete caller-owned QEMU runtime closure and both guest
515
525
  artifacts:
516
526
 
@@ -567,6 +577,25 @@ arguments for the WHPX schema. WHPX requires the Windows Hypervisor Platform
567
577
  API exposed to QEMU; see the [QEMU WHPX documentation](https://www.qemu.org/docs/master/system/whpx.html)
568
578
  and [Microsoft's Windows Hypervisor Platform API overview](https://learn.microsoft.com/en-us/virtualization/api/).
569
579
 
580
+ For the sandboxed adapter, use schema
581
+ `holoscript.holosystem.whpx-sandboxed-vm-launch-plan.v1`, add the following
582
+ closed field, and call `vm-launch-whpx-sandboxed`:
583
+
584
+ ```json
585
+ {
586
+ "sandbox": {
587
+ "kind": "windows-low-integrity-job-v1",
588
+ "launcherDigest": "sha256:<HOLOSYSTEM_WINDOWS_SANDBOX_LAUNCHER_DIGEST>"
589
+ }
590
+ }
591
+ ```
592
+
593
+ The exported `HOLOSYSTEM_WINDOWS_SANDBOX_LAUNCHER_DIGEST` is the digest of the
594
+ package's audited launcher binary. A plan with another digest is blocked before
595
+ process creation. The launcher source and local rebuild recipe are shipped in
596
+ `native/windows-sandbox`; the measured binary is shipped in
597
+ `native/windows-x64`.
598
+
570
599
  The runner creates a private snapshot and remeasures the complete QEMU closure,
571
600
  kernel, and initramfs before and after each launch. It then generates QEMU
572
601
  arguments that disable user configuration, default devices, networking, USB,
@@ -583,12 +612,21 @@ A verified TCG receipt includes `machine-vm-launch`,
583
612
  `hardwareBacked: false`, and leaves hardware acceleration missing. A verified
584
613
  WHPX receipt additionally includes `hardware-hypervisor-acceleration` and sets
585
614
  `hardwareBacked: true` only after two explicit WHPX launches succeed. Both
586
- adapters leave `host-process-isolation` missing: QEMU still has the ambient
615
+ ambient adapters leave `host-process-isolation` missing: QEMU still has the ambient
587
616
  rights of the Windows process. Receipts therefore expose
588
617
  `isolation.hostProcess: "ambient-windows-process"` and
589
618
  `isolation.verified: false` even when WHPX acceleration is verified. Neither
590
- receipt proves an IOMMU, measured boot, firmware authenticity, confidential
591
- memory, or side-channel resistance. The
619
+ ambient adapter receipt proves an IOMMU, measured boot, firmware authenticity,
620
+ confidential memory, or side-channel resistance.
621
+
622
+ A verified `vm-launch-whpx-sandboxed` receipt includes
623
+ `host-process-isolation` only for the declared integrity, privilege,
624
+ inherited-handle, lifetime, process-count, memory, and UI scope. It deliberately
625
+ leaves `host-filesystem-confidentiality` and `host-network-isolation` missing:
626
+ low integrity prevents writes up to medium-integrity objects but does not
627
+ prevent reads, and the filtered token is not an AppContainer network capability
628
+ boundary. The sandboxed receipt also does not prove the broader hardware and
629
+ firmware properties named above. The
592
630
  exact claims are in the [VM launch threat model](./docs/vm-launch-threat-model.md).
593
631
 
594
632
  ```js
@@ -596,8 +634,11 @@ import {
596
634
  inspectVmExecutor,
597
635
  inspectVmLaunchAsset,
598
636
  inspectVmLaunchPlan,
637
+ inspectWindowsVmSandboxLauncher,
638
+ inspectWhpxSandboxedVmLaunchPlan,
599
639
  inspectWhpxVmLaunchPlan,
600
640
  runVmLaunch,
641
+ runWhpxSandboxedVmLaunch,
601
642
  runWhpxVmLaunch,
602
643
  } from '@holoscript/holosystem';
603
644
  ```
@@ -15,6 +15,7 @@ import {
15
15
  inspectVmLaunchAsset,
16
16
  runNativeBuild,
17
17
  runVmLaunch,
18
+ runWhpxSandboxedVmLaunch,
18
19
  runWhpxVmLaunch,
19
20
  } from '../src/index.mjs';
20
21
 
@@ -35,6 +36,7 @@ Usage:
35
36
  holosystem vm-asset --kind <kernel|initrd> --file <file> [--json]
36
37
  holosystem vm-launch --plan <file> --runtime <directory> --kernel <file> --initrd <file> [--output <receipt>] [--force] [--json]
37
38
  holosystem vm-launch-whpx --plan <file> --runtime <directory> --kernel <file> --initrd <file> [--output <receipt>] [--force] [--json]
39
+ holosystem vm-launch-whpx-sandboxed --plan <file> --runtime <directory> --kernel <file> --initrd <file> [--output <receipt>] [--force] [--json]
38
40
  holosystem substrate --input <file> [--output <file>] [--force] [--json]
39
41
  holosystem --help
40
42
  holosystem --version
@@ -706,6 +708,11 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
706
708
  launcher: runWhpxVmLaunch,
707
709
  commandName: 'vm-launch-whpx',
708
710
  });
711
+ } else if (command === 'vm-launch-whpx-sandboxed') {
712
+ runVmLaunchCommand(argv.slice(1), {
713
+ launcher: runWhpxSandboxedVmLaunch,
714
+ commandName: 'vm-launch-whpx-sandboxed',
715
+ });
709
716
  } else if (command === 'substrate') {
710
717
  runSubstrate(argv.slice(1));
711
718
  } else {
@@ -17,6 +17,16 @@ Windows Hypervisor Platform adapter for those launches; it does not prove host
17
17
  process isolation. QEMU retains the ambient rights of its Windows process in
18
18
  both adapters.
19
19
 
20
+ `vm-launch-whpx-sandboxed` is a separate schema and receipt. It runs the same
21
+ measured WHPX launch behind a measured native Windows launcher that creates a
22
+ filtered token with `DISABLE_MAX_PRIVILEGE`, sets low mandatory integrity,
23
+ verifies at most the single pass-through privilege remains enabled, creates
24
+ QEMU suspended with only NUL/stdout/stderr handles inherited, assigns QEMU to a
25
+ Job Object before resume, and applies kill-on-close, one-process, 512 MiB, and
26
+ full Job UI restrictions. Its `host-process-isolation` claim is limited to
27
+ those controls. It is not an AppContainer and does not claim host filesystem
28
+ confidentiality or host network isolation.
29
+
20
30
  ## Protected assets and trust boundaries
21
31
 
22
32
  The protected inputs are the declarative plan, the complete caller-owned QEMU
@@ -39,20 +49,23 @@ than implied away by a successful boot.
39
49
 
40
50
  ## Adversary specifications
41
51
 
42
- | Adversary action | Required result | Receipt or test evidence |
43
- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------- |
44
- | Add a shell command, argument vector, environment field, device, network mode, or unknown plan field | Reject before process launch | `vm-launch-field-unknown`; closed-vocabulary test |
45
- | Put WHPX in a TCG plan, TCG in a WHPX plan, or request a fallback | Reject rather than downgrade, cross-route, or overclaim | Separate schemas; accelerator/unknown-field tests |
46
- | Replace any QEMU executable, DLL, firmware file, kernel, or initramfs before measurement | Reject before process launch | Runtime, binary, kernel, and initrd digest mismatch issues |
47
- | Replace measured files while the launch snapshot is being created | Reject the snapshot | Runtime, kernel, and initrd snapshot mismatch issues |
48
- | Replace caller-owned files after the first launch | Second launch still uses the same private snapshot | Private-snapshot substitution test |
49
- | Persistently self-modify the private runtime or guest artifacts during a launch | Reject on post-launch remeasurement | Private-snapshot drift test |
50
- | Inject QEMU behavior through inherited environment variables or user configuration | Launch with a minimal environment and `-no-user-config` | Generated-argv test |
51
- | Obtain implicit host devices or a communication channel | Start with `-nodefaults`, `-nic none`, USB off, no display, and no monitor | Generated-argv test |
52
- | Forge the guest signal, use the wrong exit path, or change adapter diagnostics | Reject the receipt and retain no raw output | Console, exit-code, and diagnostic-digest tests |
53
- | Make clean launches observably disagree | Reject deterministic coverage | `vm-launch-nondeterministic` |
54
- | Inject a fake process runner through the public API | Ignore it and execute only the bound process implementation | Public process-runner injection test |
55
- | Put an operational path or guest output in the receipt | Withhold it; report only digest and byte count | Receipt disclosure assertions |
52
+ | Adversary action | Required result | Receipt or test evidence |
53
+ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------- |
54
+ | Add a shell command, argument vector, environment field, device, network mode, or unknown plan field | Reject before process launch | `vm-launch-field-unknown`; closed-vocabulary test |
55
+ | Put WHPX in a TCG plan, TCG in a WHPX plan, or request a fallback | Reject rather than downgrade, cross-route, or overclaim | Separate schemas; accelerator/unknown-field tests |
56
+ | Replace any QEMU executable, DLL, firmware file, kernel, or initramfs before measurement | Reject before process launch | Runtime, binary, kernel, and initrd digest mismatch issues |
57
+ | Replace measured files while the launch snapshot is being created | Reject the snapshot | Runtime, kernel, and initrd snapshot mismatch issues |
58
+ | Replace caller-owned files after the first launch | Second launch still uses the same private snapshot | Private-snapshot substitution test |
59
+ | Persistently self-modify the private runtime or guest artifacts during a launch | Reject on post-launch remeasurement | Private-snapshot drift test |
60
+ | Inject QEMU behavior through inherited environment variables or user configuration | Launch with a minimal environment and `-no-user-config` | Generated-argv test |
61
+ | Obtain implicit host devices or a communication channel | Start with `-nodefaults`, `-nic none`, USB off, no display, and no monitor | Generated-argv test |
62
+ | Forge the guest signal, use the wrong exit path, or change adapter diagnostics | Reject the receipt and retain no raw output | Console, exit-code, and diagnostic-digest tests |
63
+ | Make clean launches observably disagree | Reject deterministic coverage | `vm-launch-nondeterministic` |
64
+ | Inject a fake process runner through the public API | Ignore it and execute only the bound process implementation | Public process-runner injection test |
65
+ | Select ambient execution, weaken a sandbox control, change the launcher, or forge its protocol | Reject the distinct sandbox schema, launcher digest, or incomplete evidence | Closed sandbox vocabulary and protocol-forgery tests |
66
+ | Pass inherited parent handles into sandboxed QEMU | Admit only NUL input and the two bounded output pipes | Native handle-list evidence and receipt assertion |
67
+ | Spawn another process or escape launcher lifetime/resource bounds | Assign suspended QEMU before resume to a one-process, kill-on-close Job | Native Job evidence and adversarial receipt tests |
68
+ | Put an operational path or guest output in the receipt | Withhold it; report only digest and byte count | Receipt disclosure assertions |
56
69
 
57
70
  ## Fixed launch policy
58
71
 
@@ -73,6 +86,13 @@ produce the plan-pinned diagnostic digest after removal of only the exact,
73
86
  randomized private-executor prefix that QEMU repeats at diagnostic line starts. Raw
74
87
  stdout and stderr are never included in the receipt.
75
88
 
89
+ The sandboxed adapter additionally copies the package-pinned launcher into the
90
+ private measured snapshot. The launcher protocol is closed and binary-safe: it
91
+ returns base64 child streams plus derived control evidence, and HoloSystem
92
+ rejects unknown fields, non-canonical base64, an unbounded enabled-privilege
93
+ count, a missing control, or launcher stderr. Launcher and QEMU snapshots are
94
+ remeasured before and after both launches.
95
+
76
96
  ## Residual risk and next layer
77
97
 
78
98
  The QEMU runtime closure includes firmware data files and DLLs, so substitution
@@ -80,12 +100,22 @@ changes its digest. Hashing does not establish provenance or measured boot.
80
100
  Windows QEMU also cannot disable host crash-dump capture through this contract;
81
101
  `host-crash-dump-custody` remains an explicit boundary.
82
102
 
83
- QEMU is not yet placed in an AppContainer, restricted token, job-object filesystem
84
- sandbox, or separate host VM. `virtual-device-minimization` therefore describes
85
- only the generated guest-facing virtual device surface; it must not be read as
86
- host-process or physical-device isolation.
87
-
88
- The next stronger layer must add a separately measured Windows host-process
89
- sandbox and firmware/measured-boot evidence. It must not reinterpret WHPX
90
- execution as proof of either property, and it must continue to report IOMMU,
91
- device-assignment, crash-dump custody, and side-channel boundaries separately.
103
+ The ambient adapters do not place QEMU behind an OS process sandbox.
104
+ `virtual-device-minimization` therefore describes only their generated
105
+ guest-facing virtual device surface.
106
+
107
+ The sandboxed adapter is narrower than AppContainer or a separate host VM. Its
108
+ filtered token retains normal read access allowed to the caller and does not
109
+ create an OS network capability boundary. The QEMU command still contains no
110
+ guest network device, but a compromised host QEMU process could use host
111
+ network APIs. `host-filesystem-confidentiality` and `host-network-isolation`
112
+ therefore remain explicit missing layers even when the declared process
113
+ isolation controls verify. The launcher binary is measured, but source-to-binary
114
+ reproducibility and code signing remain part of `qemu-runtime-supply-chain` and
115
+ host correctness trust.
116
+
117
+ The next stronger layer is an AppContainer or separate-host-VM adapter that can
118
+ retain WHPX access while proving capability-scoped filesystem and network
119
+ denial, followed by firmware/measured-boot evidence. It must continue to report
120
+ IOMMU, device-assignment, crash-dump custody, and side-channel boundaries
121
+ separately.