@openclaw/openshell-sandbox 2026.10.5-beta.4 → 2026.10.10-beta.2

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.
Files changed (240) hide show
  1. package/README.md +1 -1
  2. package/node_modules/@openclaw/fs-safe/CHANGELOG.md +148 -0
  3. package/node_modules/@openclaw/fs-safe/README.md +20 -4
  4. package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +2 -1
  5. package/node_modules/@openclaw/fs-safe/dist/advanced.js +1 -0
  6. package/node_modules/@openclaw/fs-safe/dist/archive-merge.js +28 -3
  7. package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
  8. package/node_modules/@openclaw/fs-safe/dist/archive-read.js +11 -5
  9. package/node_modules/@openclaw/fs-safe/dist/archive-zip-loader.js +4 -2
  10. package/node_modules/@openclaw/fs-safe/dist/archive.js +2 -2
  11. package/node_modules/@openclaw/fs-safe/dist/atomic-io.js +2 -2
  12. package/node_modules/@openclaw/fs-safe/dist/bounded-read.d.ts +1 -0
  13. package/node_modules/@openclaw/fs-safe/dist/bounded-read.js +9 -2
  14. package/node_modules/@openclaw/fs-safe/dist/clone-metadata.d.ts +2 -0
  15. package/node_modules/@openclaw/fs-safe/dist/clone-metadata.js +2 -1
  16. package/node_modules/@openclaw/fs-safe/dist/config.d.ts +6 -0
  17. package/node_modules/@openclaw/fs-safe/dist/config.js +5 -0
  18. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.d.ts +3 -1
  19. package/node_modules/@openclaw/fs-safe/dist/copy-file-input.js +8 -7
  20. package/node_modules/@openclaw/fs-safe/dist/copy-link.d.ts +26 -0
  21. package/node_modules/@openclaw/fs-safe/dist/copy-link.js +170 -0
  22. package/node_modules/@openclaw/fs-safe/dist/copy-metadata.d.ts +9 -0
  23. package/node_modules/@openclaw/fs-safe/dist/copy-metadata.js +39 -0
  24. package/node_modules/@openclaw/fs-safe/dist/copy-path-admission.js +11 -2
  25. package/node_modules/@openclaw/fs-safe/dist/copy-root-file-sync.d.ts +2 -4
  26. package/node_modules/@openclaw/fs-safe/dist/copy-root-file-sync.js +4 -2
  27. package/node_modules/@openclaw/fs-safe/dist/copy-tree-portable.js +3 -6
  28. package/node_modules/@openclaw/fs-safe/dist/copy.js +3 -3
  29. package/node_modules/@openclaw/fs-safe/dist/create.js +1 -1
  30. package/node_modules/@openclaw/fs-safe/dist/creation-boundary.js +7 -4
  31. package/node_modules/@openclaw/fs-safe/dist/darwin-acl.d.ts +12 -0
  32. package/node_modules/@openclaw/fs-safe/dist/darwin-acl.js +29 -0
  33. package/node_modules/@openclaw/fs-safe/dist/directory-durability.d.ts +7 -4
  34. package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +20 -5
  35. package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.d.ts +3 -0
  36. package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.js +27 -2
  37. package/node_modules/@openclaw/fs-safe/dist/directory-receipt.d.ts +7 -7
  38. package/node_modules/@openclaw/fs-safe/dist/directory-receipt.js +9 -4
  39. package/node_modules/@openclaw/fs-safe/dist/durability.d.ts +2 -1
  40. package/node_modules/@openclaw/fs-safe/dist/entry-publication.js +2 -2
  41. package/node_modules/@openclaw/fs-safe/dist/exact-identity.d.ts +17 -0
  42. package/node_modules/@openclaw/fs-safe/dist/exact-identity.js +29 -0
  43. package/node_modules/@openclaw/fs-safe/dist/file-handle-transfer.js +4 -2
  44. package/node_modules/@openclaw/fs-safe/dist/file-hash.d.ts +1 -1
  45. package/node_modules/@openclaw/fs-safe/dist/file-hash.js +11 -9
  46. package/node_modules/@openclaw/fs-safe/dist/file-identity.d.ts +7 -1
  47. package/node_modules/@openclaw/fs-safe/dist/file-identity.js +27 -5
  48. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync-admission.js +1 -2
  49. package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +8 -1
  50. package/node_modules/@openclaw/fs-safe/dist/file-lock.d.ts +1 -0
  51. package/node_modules/@openclaw/fs-safe/dist/file-lock.js +1 -0
  52. package/node_modules/@openclaw/fs-safe/dist/file-write-lease.d.ts +9 -0
  53. package/node_modules/@openclaw/fs-safe/dist/file-write-lease.js +42 -0
  54. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +1 -0
  55. package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +22 -15
  56. package/node_modules/@openclaw/fs-safe/dist/guest-native-python.js +3 -0
  57. package/node_modules/@openclaw/fs-safe/dist/hardlink-fallback.d.ts +1 -0
  58. package/node_modules/@openclaw/fs-safe/dist/hardlink-fallback.js +5 -0
  59. package/node_modules/@openclaw/fs-safe/dist/index.d.ts +1 -0
  60. package/node_modules/@openclaw/fs-safe/dist/index.js +1 -0
  61. package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.js +16 -3
  62. package/node_modules/@openclaw/fs-safe/dist/local-file-descriptor.js +24 -13
  63. package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +85 -18
  64. package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +5 -0
  65. package/node_modules/@openclaw/fs-safe/dist/native-config.js +11 -0
  66. package/node_modules/@openclaw/fs-safe/dist/native-directory-observation.js +6 -4
  67. package/node_modules/@openclaw/fs-safe/dist/native-fallback-warning.d.ts +2 -1
  68. package/node_modules/@openclaw/fs-safe/dist/native-fallback-warning.js +26 -2
  69. package/node_modules/@openclaw/fs-safe/dist/native-guidance.d.ts +3 -0
  70. package/node_modules/@openclaw/fs-safe/dist/native-guidance.js +21 -0
  71. package/node_modules/@openclaw/fs-safe/dist/native-move-fallback.d.ts +1 -1
  72. package/node_modules/@openclaw/fs-safe/dist/native-move-fallback.js +2 -0
  73. package/node_modules/@openclaw/fs-safe/dist/native-operations.js +8 -6
  74. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.d.ts +44 -4
  75. package/node_modules/@openclaw/fs-safe/dist/native-parent-admission.js +85 -15
  76. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.d.ts +3 -3
  77. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.js +33 -6
  78. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.d.ts +4 -1
  79. package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +22 -3
  80. package/node_modules/@openclaw/fs-safe/dist/native-policy-directory-observation.js +4 -3
  81. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.d.ts +1 -1
  82. package/node_modules/@openclaw/fs-safe/dist/native-policy-parent.js +3 -0
  83. package/node_modules/@openclaw/fs-safe/dist/native-staged-file-metadata.d.ts +3 -0
  84. package/node_modules/@openclaw/fs-safe/dist/native-staged-file-metadata.js +16 -0
  85. package/node_modules/@openclaw/fs-safe/dist/native-staged-file.d.ts +1 -1
  86. package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +15 -5
  87. package/node_modules/@openclaw/fs-safe/dist/native-stat-identity.d.ts +3 -0
  88. package/node_modules/@openclaw/fs-safe/dist/native-stat-identity.js +7 -0
  89. package/node_modules/@openclaw/fs-safe/dist/native-status.d.ts +17 -0
  90. package/node_modules/@openclaw/fs-safe/dist/native-status.js +30 -0
  91. package/node_modules/@openclaw/fs-safe/dist/native.d.ts +31 -4
  92. package/node_modules/@openclaw/fs-safe/dist/native.js +107 -9
  93. package/node_modules/@openclaw/fs-safe/dist/opened-realpath.js +9 -1
  94. package/node_modules/@openclaw/fs-safe/dist/overwrite-file-handle.js +4 -1
  95. package/node_modules/@openclaw/fs-safe/dist/owner-dacl-batch.js +1 -1
  96. package/node_modules/@openclaw/fs-safe/dist/owner-dacl.js +1 -1
  97. package/node_modules/@openclaw/fs-safe/dist/permission-exec.js +9 -1
  98. package/node_modules/@openclaw/fs-safe/dist/permissions-public.d.ts +1 -0
  99. package/node_modules/@openclaw/fs-safe/dist/permissions-public.js +1 -0
  100. package/node_modules/@openclaw/fs-safe/dist/permissions-windows.js +83 -47
  101. package/node_modules/@openclaw/fs-safe/dist/pinned-open.d.ts +2 -0
  102. package/node_modules/@openclaw/fs-safe/dist/pinned-open.js +8 -3
  103. package/node_modules/@openclaw/fs-safe/dist/pinned-write-input.js +13 -0
  104. package/node_modules/@openclaw/fs-safe/dist/pinned-write-staged.js +10 -8
  105. package/node_modules/@openclaw/fs-safe/dist/pinned-write-types.d.ts +2 -1
  106. package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +7 -5
  107. package/node_modules/@openclaw/fs-safe/dist/pipe.d.ts +9 -0
  108. package/node_modules/@openclaw/fs-safe/dist/pipe.js +26 -0
  109. package/node_modules/@openclaw/fs-safe/dist/private-directory.js +1 -1
  110. package/node_modules/@openclaw/fs-safe/dist/private-producer-handoff.js +2 -5
  111. package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.d.ts +3 -2
  112. package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.js +38 -10
  113. package/node_modules/@openclaw/fs-safe/dist/publish-copy-stage.js +92 -10
  114. package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.d.ts +3 -0
  115. package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.js +3 -0
  116. package/node_modules/@openclaw/fs-safe/dist/publish-file.d.ts +5 -3
  117. package/node_modules/@openclaw/fs-safe/dist/publish-file.js +26 -20
  118. package/node_modules/@openclaw/fs-safe/dist/read-opened-file.d.ts +2 -0
  119. package/node_modules/@openclaw/fs-safe/dist/read-opened-file.js +3 -4
  120. package/node_modules/@openclaw/fs-safe/dist/realpath.js +32 -0
  121. package/node_modules/@openclaw/fs-safe/dist/regular-file.d.ts +4 -0
  122. package/node_modules/@openclaw/fs-safe/dist/regular-file.js +11 -15
  123. package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +3 -2
  124. package/node_modules/@openclaw/fs-safe/dist/root-copy.d.ts +18 -0
  125. package/node_modules/@openclaw/fs-safe/dist/root-copy.js +128 -0
  126. package/node_modules/@openclaw/fs-safe/dist/root-create-native.d.ts +8 -13
  127. package/node_modules/@openclaw/fs-safe/dist/root-create-native.js +252 -27
  128. package/node_modules/@openclaw/fs-safe/dist/root-directory-creation.js +5 -1
  129. package/node_modules/@openclaw/fs-safe/dist/root-directory-list-types.d.ts +11 -8
  130. package/node_modules/@openclaw/fs-safe/dist/root-directory-list.js +35 -13
  131. package/node_modules/@openclaw/fs-safe/dist/root-file-open-batch-sync.d.ts +8 -0
  132. package/node_modules/@openclaw/fs-safe/dist/root-file-open-batch-sync.js +108 -0
  133. package/node_modules/@openclaw/fs-safe/dist/root-file.d.ts +7 -0
  134. package/node_modules/@openclaw/fs-safe/dist/root-file.js +15 -0
  135. package/node_modules/@openclaw/fs-safe/dist/root-impl.d.ts +2 -0
  136. package/node_modules/@openclaw/fs-safe/dist/root-impl.js +154 -175
  137. package/node_modules/@openclaw/fs-safe/dist/root-mkdir-native.d.ts +2 -0
  138. package/node_modules/@openclaw/fs-safe/dist/root-mkdir-native.js +239 -0
  139. package/node_modules/@openclaw/fs-safe/dist/root-move-noreplace.js +37 -15
  140. package/node_modules/@openclaw/fs-safe/dist/root-native-creation-path.d.ts +32 -0
  141. package/node_modules/@openclaw/fs-safe/dist/root-native-creation-path.js +56 -0
  142. package/node_modules/@openclaw/fs-safe/dist/root-options.d.ts +2 -0
  143. package/node_modules/@openclaw/fs-safe/dist/root-public-types.d.ts +1 -0
  144. package/node_modules/@openclaw/fs-safe/dist/root-remove-native.js +95 -16
  145. package/node_modules/@openclaw/fs-safe/dist/root-remove.js +6 -4
  146. package/node_modules/@openclaw/fs-safe/dist/root-walk.js +23 -19
  147. package/node_modules/@openclaw/fs-safe/dist/root-write-admission.js +8 -6
  148. package/node_modules/@openclaw/fs-safe/dist/root-write-publication.js +5 -1
  149. package/node_modules/@openclaw/fs-safe/dist/secure-file-windows.js +3 -1
  150. package/node_modules/@openclaw/fs-safe/dist/secure-file.d.ts +2 -0
  151. package/node_modules/@openclaw/fs-safe/dist/secure-file.js +10 -4
  152. package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +1 -1
  153. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +2 -2
  154. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-retained.js +1 -1
  155. package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-target.js +8 -1
  156. package/node_modules/@openclaw/fs-safe/dist/staged-directory.d.ts +13 -0
  157. package/node_modules/@openclaw/fs-safe/dist/staged-directory.js +29 -0
  158. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-child-admission.js +5 -3
  159. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-descriptor.d.ts +8 -0
  160. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-descriptor.js +13 -2
  161. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.js +71 -3
  162. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-ownership.d.ts +2 -1
  163. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-ownership.js +22 -0
  164. package/node_modules/@openclaw/fs-safe/dist/temp-workspace-types.d.ts +3 -0
  165. package/node_modules/@openclaw/fs-safe/dist/test-hooks.d.ts +1 -0
  166. package/node_modules/@openclaw/fs-safe/dist/test-hooks.js +1 -0
  167. package/node_modules/@openclaw/fs-safe/dist/trash.js +2 -2
  168. package/node_modules/@openclaw/fs-safe/dist/types.d.ts +4 -0
  169. package/node_modules/@openclaw/fs-safe/dist/watch-native.js +2 -2
  170. package/node_modules/@openclaw/fs-safe/dist/windows-appcontainer.d.ts +5 -0
  171. package/node_modules/@openclaw/fs-safe/dist/windows-appcontainer.js +39 -0
  172. package/node_modules/@openclaw/fs-safe/dist/windows-owner.d.ts +1 -0
  173. package/node_modules/@openclaw/fs-safe/dist/windows-owner.js +25 -36
  174. package/node_modules/@openclaw/fs-safe/dist/windows-security-command.js +24 -5
  175. package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.d.ts +2 -1
  176. package/node_modules/@openclaw/fs-safe/dist/windows-security-facts.js +4 -0
  177. package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.d.ts +2 -0
  178. package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.exe +0 -0
  179. package/node_modules/@openclaw/fs-safe/dist/windows-security-helper.js +7 -0
  180. package/node_modules/@openclaw/fs-safe/dist/windows-test-hooks.d.ts +16 -0
  181. package/node_modules/@openclaw/fs-safe/dist/windows-test-hooks.js +51 -0
  182. package/node_modules/@openclaw/fs-safe/dist/write-file-handle.d.ts +1 -0
  183. package/node_modules/@openclaw/fs-safe/dist/write-file-handle.js +12 -10
  184. package/node_modules/@openclaw/fs-safe/docs/advanced.md +2 -1
  185. package/node_modules/@openclaw/fs-safe/docs/archive.md +16 -0
  186. package/node_modules/@openclaw/fs-safe/docs/config.md +71 -1
  187. package/node_modules/@openclaw/fs-safe/docs/contributing.md +45 -5
  188. package/node_modules/@openclaw/fs-safe/docs/copy.md +45 -5
  189. package/node_modules/@openclaw/fs-safe/docs/durability.md +34 -7
  190. package/node_modules/@openclaw/fs-safe/docs/errors.md +8 -0
  191. package/node_modules/@openclaw/fs-safe/docs/guest.md +2 -0
  192. package/node_modules/@openclaw/fs-safe/docs/install.md +47 -27
  193. package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +6 -6
  194. package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.6.md +1 -1
  195. package/node_modules/@openclaw/fs-safe/docs/native-helper.md +79 -6
  196. package/node_modules/@openclaw/fs-safe/docs/native.md +279 -8
  197. package/node_modules/@openclaw/fs-safe/docs/permissions.md +64 -15
  198. package/node_modules/@openclaw/fs-safe/docs/pipe.md +81 -0
  199. package/node_modules/@openclaw/fs-safe/docs/platform-capabilities.md +63 -0
  200. package/node_modules/@openclaw/fs-safe/docs/public-api.md +10 -0
  201. package/node_modules/@openclaw/fs-safe/docs/queue-link-free-design.md +237 -0
  202. package/node_modules/@openclaw/fs-safe/docs/quickstart.md +23 -3
  203. package/node_modules/@openclaw/fs-safe/docs/reading.md +56 -2
  204. package/node_modules/@openclaw/fs-safe/docs/regular-file.md +2 -0
  205. package/node_modules/@openclaw/fs-safe/docs/secret-file.md +5 -5
  206. package/node_modules/@openclaw/fs-safe/docs/secure-file.md +1 -1
  207. package/node_modules/@openclaw/fs-safe/docs/security-model.md +35 -0
  208. package/node_modules/@openclaw/fs-safe/docs/sidecar-lock.md +31 -13
  209. package/node_modules/@openclaw/fs-safe/docs/staged-file.md +18 -0
  210. package/node_modules/@openclaw/fs-safe/docs/store.md +15 -0
  211. package/node_modules/@openclaw/fs-safe/docs/temp.md +39 -0
  212. package/node_modules/@openclaw/fs-safe/docs/testing.md +13 -0
  213. package/node_modules/@openclaw/fs-safe/docs/types.md +51 -81
  214. package/node_modules/@openclaw/fs-safe/docs/walk.md +4 -1
  215. package/node_modules/@openclaw/fs-safe/docs/watch.md +3 -2
  216. package/node_modules/@openclaw/fs-safe/docs/writing.md +121 -14
  217. package/node_modules/@openclaw/fs-safe/package.json +21 -12
  218. package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
  219. package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +1 -1
  220. package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
  221. package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +1 -1
  222. package/node_modules/@openclaw/fs-safe-freebsd-arm64/fs-safe-native.node +0 -0
  223. package/node_modules/@openclaw/fs-safe-freebsd-arm64/package.json +29 -0
  224. package/node_modules/@openclaw/fs-safe-freebsd-x64/fs-safe-native.node +0 -0
  225. package/node_modules/@openclaw/fs-safe-freebsd-x64/package.json +29 -0
  226. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
  227. package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +1 -1
  228. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
  229. package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +1 -1
  230. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
  231. package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +1 -1
  232. package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
  233. package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +1 -1
  234. package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/fs-safe-native.node +0 -0
  235. package/node_modules/@openclaw/fs-safe-win32-arm64-msvc/package.json +29 -0
  236. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
  237. package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +1 -1
  238. package/package.json +5 -5
  239. package/node_modules/@openclaw/fs-safe/dist/windows-security-bridge.cs +0 -336
  240. package/node_modules/@openclaw/fs-safe/dist/windows-security-bridge.ps1 +0 -90
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@openclaw/fs-safe-freebsd-arm64",
3
+ "version": "0.26.5",
4
+ "description": "FreeBSD 14.4+ arm64 native binding for @openclaw/fs-safe.",
5
+ "license": "MIT",
6
+ "author": "OpenClaw Team <dev@openclaw.ai>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/openclaw/fs-safe.git",
10
+ "directory": "packages/freebsd-arm64"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "provenance": true
15
+ },
16
+ "os": [
17
+ "freebsd"
18
+ ],
19
+ "cpu": [
20
+ "arm64"
21
+ ],
22
+ "main": "fs-safe-native.node",
23
+ "files": [
24
+ "fs-safe-native.node"
25
+ ],
26
+ "engines": {
27
+ "node": ">=22"
28
+ }
29
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@openclaw/fs-safe-freebsd-x64",
3
+ "version": "0.26.5",
4
+ "description": "FreeBSD 14.4+ x64 native binding for @openclaw/fs-safe.",
5
+ "license": "MIT",
6
+ "author": "OpenClaw Team <dev@openclaw.ai>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/openclaw/fs-safe.git",
10
+ "directory": "packages/freebsd-x64"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "provenance": true
15
+ },
16
+ "os": [
17
+ "freebsd"
18
+ ],
19
+ "cpu": [
20
+ "x64"
21
+ ],
22
+ "main": "fs-safe-native.node",
23
+ "files": [
24
+ "fs-safe-native.node"
25
+ ],
26
+ "engines": {
27
+ "node": ">=22"
28
+ }
29
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe-linux-arm64-gnu",
3
- "version": "0.25.0",
3
+ "version": "0.26.5",
4
4
  "description": "Linux arm64 glibc native binding for @openclaw/fs-safe.",
5
5
  "license": "MIT",
6
6
  "author": "OpenClaw Team <dev@openclaw.ai>",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe-linux-arm64-musl",
3
- "version": "0.25.0",
3
+ "version": "0.26.5",
4
4
  "description": "Linux arm64 musl native binding for @openclaw/fs-safe.",
5
5
  "license": "MIT",
6
6
  "author": "OpenClaw Team <dev@openclaw.ai>",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe-linux-x64-gnu",
3
- "version": "0.25.0",
3
+ "version": "0.26.5",
4
4
  "description": "Linux x64 glibc native binding for @openclaw/fs-safe.",
5
5
  "license": "MIT",
6
6
  "author": "OpenClaw Team <dev@openclaw.ai>",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe-linux-x64-musl",
3
- "version": "0.25.0",
3
+ "version": "0.26.5",
4
4
  "description": "Linux x64 musl native binding for @openclaw/fs-safe.",
5
5
  "license": "MIT",
6
6
  "author": "OpenClaw Team <dev@openclaw.ai>",
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@openclaw/fs-safe-win32-arm64-msvc",
3
+ "version": "0.26.5",
4
+ "description": "Windows ARM64 MSVC native binding for @openclaw/fs-safe.",
5
+ "license": "MIT",
6
+ "author": "OpenClaw Team <dev@openclaw.ai>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/openclaw/fs-safe.git",
10
+ "directory": "packages/win32-arm64-msvc"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "provenance": true
15
+ },
16
+ "os": [
17
+ "win32"
18
+ ],
19
+ "cpu": [
20
+ "arm64"
21
+ ],
22
+ "main": "fs-safe-native.node",
23
+ "files": [
24
+ "fs-safe-native.node"
25
+ ],
26
+ "engines": {
27
+ "node": ">=22"
28
+ }
29
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/fs-safe-win32-x64-msvc",
3
- "version": "0.25.0",
3
+ "version": "0.26.5",
4
4
  "description": "Windows x64 MSVC native binding for @openclaw/fs-safe.",
5
5
  "license": "MIT",
6
6
  "author": "OpenClaw Team <dev@openclaw.ai>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/openshell-sandbox",
3
- "version": "2026.10.5-beta.4",
3
+ "version": "2026.10.10-beta.2",
4
4
  "description": "OpenClaw sandbox backend for the NVIDIA OpenShell CLI with mirrored local workspaces and SSH command execution.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "type": "module",
10
10
  "dependencies": {
11
- "@openclaw/fs-safe": "0.25.0",
11
+ "@openclaw/fs-safe": "0.26.5",
12
12
  "p-limit": "7.3.3",
13
13
  "zod": "4.6.5"
14
14
  },
@@ -23,10 +23,10 @@
23
23
  "minHostVersion": ">=2026.5.12-beta.1"
24
24
  },
25
25
  "compat": {
26
- "pluginApi": ">=2026.10.5-beta.4"
26
+ "pluginApi": ">=2026.10.10-beta.2"
27
27
  },
28
28
  "build": {
29
- "openclawVersion": "2026.10.5-beta.4",
29
+ "openclawVersion": "2026.10.10-beta.2",
30
30
  "bundledDist": false
31
31
  },
32
32
  "release": {
@@ -45,7 +45,7 @@
45
45
  "assets/activity.svg"
46
46
  ],
47
47
  "peerDependencies": {
48
- "openclaw": ">=2026.10.5-beta.4"
48
+ "openclaw": ">=2026.10.10-beta.2"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "openclaw": {
@@ -1,336 +0,0 @@
1
- // Executed only by the built-in Windows PowerShell/.NET host. The raw security
2
- // descriptor never passes through CommonSecurityDescriptor's ACE normalization.
3
- using System;
4
- using System.Collections.Generic;
5
- using System.Runtime.InteropServices;
6
- using System.Security.AccessControl;
7
- using System.Security.Principal;
8
- using System.Text;
9
- using Microsoft.Win32.SafeHandles;
10
-
11
- public static partial class FsSafeWindowsBridge {
12
- [StructLayout(LayoutKind.Sequential)] struct IoStatus { public IntPtr Status; public UIntPtr Information; }
13
- [StructLayout(LayoutKind.Sequential)] struct UnicodeString { public ushort Length, MaximumLength; public IntPtr Buffer; }
14
- [StructLayout(LayoutKind.Sequential)] struct ObjectAttributes {
15
- public uint Length; public IntPtr RootDirectory, ObjectName; public uint Attributes;
16
- public IntPtr SecurityDescriptor, SecurityQualityOfService;
17
- }
18
- [StructLayout(LayoutKind.Sequential)] struct FileInfo {
19
- public uint Attributes, CreationLow, CreationHigh, AccessLow, AccessHigh, WriteLow, WriteHigh;
20
- public uint Volume, SizeHigh, SizeLow, Links, IndexHigh, IndexLow;
21
- }
22
- [StructLayout(LayoutKind.Sequential)] struct FileId {
23
- public ulong Volume; [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public byte[] Id;
24
- }
25
- [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true)] static extern SafeFileHandle CreateFileW(string path, uint access, uint share, IntPtr security, uint disposition, uint flags, IntPtr template);
26
- [DllImport("kernel32.dll", SetLastError=true)] static extern IntPtr GetStdHandle(int standard);
27
- [DllImport("kernel32.dll", SetLastError=true)] static extern uint GetFileType(SafeFileHandle handle);
28
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool GetFileInformationByHandle(SafeFileHandle handle, out FileInfo information);
29
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool GetFileInformationByHandleEx(SafeFileHandle handle, int kind, out FileId information, uint size);
30
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool SetFileInformationByHandle(SafeFileHandle handle, int kind, ref uint information, uint size);
31
- [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true)] static extern uint GetFinalPathNameByHandleW(SafeFileHandle handle, StringBuilder path, uint capacity, uint flags);
32
- [DllImport("kernel32.dll")] static extern IntPtr LocalFree(IntPtr memory);
33
- [DllImport("advapi32.dll")] static extern uint GetSecurityInfo(SafeFileHandle handle, int kind, uint sections, out IntPtr owner, out IntPtr group, out IntPtr dacl, out IntPtr sacl, out IntPtr descriptor);
34
- [DllImport("advapi32.dll")] static extern uint GetSecurityDescriptorLength(IntPtr descriptor);
35
- [DllImport("advapi32.dll", SetLastError=true)] static extern bool GetSecurityDescriptorDacl(IntPtr descriptor, out bool present, out IntPtr dacl, out bool defaulted);
36
- [DllImport("advapi32.dll", SetLastError=true)] static extern bool GetSecurityDescriptorOwner(IntPtr descriptor, out IntPtr owner, out bool defaulted);
37
- [DllImport("advapi32.dll")] static extern uint SetSecurityInfo(SafeFileHandle handle, int kind, uint sections, IntPtr owner, IntPtr group, IntPtr dacl, IntPtr sacl);
38
- [DllImport("ntdll.dll")] static extern int NtQueryInformationFile(SafeFileHandle handle, out IoStatus io, [Out] byte[] information, uint length, int kind);
39
- [DllImport("ntdll.dll")] static extern int NtCreateFile(out SafeFileHandle handle, uint access, ref ObjectAttributes attributes, out IoStatus io, IntPtr allocation, uint flags, uint share, uint disposition, uint options, IntPtr ea, uint eaLength);
40
- [DllImport("ntdll.dll")] static extern uint RtlNtStatusToDosError(int status);
41
-
42
- sealed class Failure : Exception {
43
- public readonly string Code;
44
- public Failure(string code, string message) : base(message) { Code=code; }
45
- }
46
- static Failure OsFailure(uint error, string operation, bool identity=false, bool fullIdentity=false) {
47
- // Native security calls retain EACCES; shared handle identity calls use EPERM.
48
- string code=error==5 ? (identity ? "EPERM" : "EACCES") : error==80 || error==183 ? "EEXIST" : error==2 || error==3 ? "ENOENT" :
49
- identity && (error==112 || error==39) ? "ENOSPC" : identity && (error==32 || error==33) ? "EBUSY" :
50
- fullIdentity && (error==1 || error==50 || error==87) ? "ENOTSUP" : "EIO";
51
- return new Failure(code, operation+" failed with Windows error "+error);
52
- }
53
- static Failure CreateFailure(uint error) {
54
- var failure=OsFailure(error,"create private directory",true);
55
- return failure.Code=="EPERM" ? new Failure("EACCES",failure.Message) : failure;
56
- }
57
- static void Require(bool condition, string code, string message) {
58
- if (!condition) throw new Failure(code,message);
59
- }
60
- static Dictionary<string,object> Row(params object[] fields) {
61
- var result=new Dictionary<string,object>();
62
- for(int i=0;i<fields.Length;i+=2) result.Add((string)fields[i],fields[i+1]);
63
- return result;
64
- }
65
- static SafeFileHandle Open(string path, uint access, bool noFollow) {
66
- var handle=CreateFileW(path,access,7,IntPtr.Zero,3,0x02000000u | (noFollow ? 0x00200000u : 0),IntPtr.Zero);
67
- if(handle.IsInvalid) { uint error=(uint)Marshal.GetLastWin32Error(); handle.Dispose(); throw OsFailure(error,"open security handle"); }
68
- return handle;
69
- }
70
- static FileInfo Information(SafeFileHandle handle) {
71
- FileInfo info;
72
- if(!GetFileInformationByHandle(handle,out info)) throw OsFailure((uint)Marshal.GetLastWin32Error(),"inspect handle identity",true);
73
- return info;
74
- }
75
- static string Identity(SafeFileHandle handle) {
76
- var info=Information(handle);
77
- return info.Volume.ToString("x8")+":"+(((ulong)info.IndexHigh<<32)|info.IndexLow).ToString("x16");
78
- }
79
- static string DirectoryIdentity(SafeFileHandle handle, bool requireLocal=false) {
80
- var info=Information(handle);
81
- Require((info.Attributes&0x400)==0,"ELOOP","private directory must not be a reparse point");
82
- Require((info.Attributes&0x10)!=0,"ENOTDIR","private directory handle must name a directory");
83
- if(requireLocal) Require(IsLocal(handle),"ENOTSUP","private directories require a local filesystem");
84
- return FullIdentity(handle);
85
- }
86
- static string FullIdentity(SafeFileHandle handle) {
87
- FileId id;
88
- if(!GetFileInformationByHandleEx(handle,18,out id,24)) throw OsFailure((uint)Marshal.GetLastWin32Error(),"inspect 128-bit file identity",true,true);
89
- Require(id.Id!=null && id.Id.Length==16,"EIO","file identity is incomplete");
90
- return id.Volume.ToString("x16")+":"+BitConverter.ToString(id.Id).Replace("-","").ToLowerInvariant();
91
- }
92
- static string FileIdentity(SafeFileHandle handle, uint expectedLinks) {
93
- var info=Information(handle);
94
- Require((info.Attributes&0x400)==0,"ELOOP","private file must not be a reparse point");
95
- Require((info.Attributes&0x10)==0 && GetFileType(handle)==1,"EINVAL","private file must be a regular disk file");
96
- Require(info.Links==expectedLinks,"EIO","private file link count changed");
97
- return FullIdentity(handle);
98
- }
99
- static string FinalPath(SafeFileHandle handle, uint flags) {
100
- int capacity=512;
101
- for(int attempt=0;attempt<4;attempt++) {
102
- var path=new StringBuilder(capacity);
103
- uint length=GetFinalPathNameByHandleW(handle,path,(uint)capacity,flags);
104
- if(length==0) throw OsFailure((uint)Marshal.GetLastWin32Error(),"inspect handle locality");
105
- if(length<capacity) return path.ToString();
106
- Require(length<32768,"EIO","final handle path exceeds the inspection budget");
107
- capacity=(int)length+1;
108
- }
109
- throw new Failure("EIO","final handle path changed during inspection");
110
- }
111
- static bool IsVolumeGuidPath(string path) {
112
- return path.Length>=49 && path.StartsWith(@"\\?\Volume{",StringComparison.OrdinalIgnoreCase) &&
113
- path[47]=='}' && path[48]=='\\' &&
114
- System.Text.RegularExpressions.Regex.IsMatch(path.Substring(11,36),@"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
115
- }
116
- static bool IsLocalFinalPath(string path) {
117
- return !path.StartsWith(@"\\?\UNC\",StringComparison.Ordinal) &&
118
- (!path.StartsWith(@"\\",StringComparison.Ordinal) || path.StartsWith(@"\\?\",StringComparison.Ordinal));
119
- }
120
- static bool IsLocal(SafeFileHandle handle) {
121
- IoStatus io; var remote=new byte[]{255};
122
- int status=NtQueryInformationFile(handle,out io,remote,1,51);
123
- if(status==0 && io.Information.ToUInt64()==1 && remote[0]<=1) return remote[0]==0;
124
- try {
125
- if(IsVolumeGuidPath(FinalPath(handle,9))) return true;
126
- } catch(Failure) { }
127
- return IsLocalFinalPath(FinalPath(handle,0));
128
- }
129
- static string Sid(SecurityIdentifier sid) {
130
- Require(sid!=null,"EIO","security descriptor SID is missing");
131
- return sid.Value.ToLowerInvariant();
132
- }
133
- static Dictionary<string,object> Security(SafeFileHandle handle, bool requireLocality=true) {
134
- IntPtr owner,group,dacl,sacl,descriptor;
135
- uint error=GetSecurityInfo(handle,1,5,out owner,out group,out dacl,out sacl,out descriptor);
136
- if(error!=0) throw OsFailure(error,"read owner and DACL");
137
- try {
138
- Require(descriptor!=IntPtr.Zero && owner!=IntPtr.Zero,"EIO","security descriptor is incomplete");
139
- uint length=GetSecurityDescriptorLength(descriptor);
140
- Require(length>=20 && length<=1024*1024,"EIO","security descriptor exceeds the inspection budget");
141
- var bytes=new byte[length]; Marshal.Copy(descriptor,bytes,0,(int)length);
142
- var raw=new RawSecurityDescriptor(bytes,0);
143
- string ownerSid=Sid(raw.Owner), currentSid;
144
- using(var current=WindowsIdentity.GetCurrent()) currentSid=Sid(current.User);
145
- var aces=new List<object>(); var unsupported=new List<int>();
146
- if(raw.DiscretionaryAcl!=null) foreach(GenericAce ace in raw.DiscretionaryAcl) {
147
- var basic=ace as CommonAce;
148
- if(basic==null || basic.IsCallback || (ace.AceType!=AceType.AccessAllowed && ace.AceType!=AceType.AccessDenied)) {
149
- unsupported.Add((int)ace.AceType); continue;
150
- }
151
- byte flags=(byte)ace.AceFlags;
152
- aces.Add(Row("sid",Sid(basic.SecurityIdentifier),"mask",unchecked((uint)basic.AccessMask),
153
- "aceType",ace.AceType==AceType.AccessAllowed ? "allow" : "deny",
154
- "flags",Row("raw",flags,"objectInherit",(flags&1)!=0,"containerInherit",(flags&2)!=0,
155
- "noPropagateInherit",(flags&4)!=0,"inheritOnly",(flags&8)!=0,"inherited",(flags&16)!=0,
156
- "successfulAccess",(flags&64)!=0,"failedAccess",(flags&128)!=0)));
157
- }
158
- bool isLocal;
159
- try { isLocal=IsLocal(handle); }
160
- catch(Failure) { if(requireLocality) throw; isLocal=false; }
161
- return Row("ownerSid",ownerSid,"currentUserSid",currentSid,"daclPresent",raw.DiscretionaryAcl!=null,
162
- "daclProtected",(raw.ControlFlags&ControlFlags.DiscretionaryAclProtected)!=0,
163
- "isLocal",isLocal,"aceListComplete",unsupported.Count==0,"unsupportedAceTypes",unsupported.ToArray(),"aces",aces.ToArray());
164
- } finally { if(descriptor!=IntPtr.Zero) LocalFree(descriptor); }
165
- }
166
- static byte[] PrivateSecurity(bool inherit=true) {
167
- SecurityIdentifier current;
168
- using(var identity=WindowsIdentity.GetCurrent()) current=identity.User;
169
- var acl=new RawAcl(2,3);
170
- var principals=new[]{current,new SecurityIdentifier("S-1-5-18"),new SecurityIdentifier("S-1-5-32-544")};
171
- var flags=inherit ? AceFlags.ObjectInherit|AceFlags.ContainerInherit : AceFlags.None;
172
- foreach(var principal in principals) acl.InsertAce(acl.Count,new CommonAce(flags,AceQualifier.AccessAllowed,0x1f01ff,principal,false,null));
173
- var descriptor=new RawSecurityDescriptor(ControlFlags.DiscretionaryAclPresent|ControlFlags.DiscretionaryAclProtected|ControlFlags.SelfRelative,current,null,null,acl);
174
- var bytes=new byte[descriptor.BinaryLength]; descriptor.GetBinaryForm(bytes,0); return bytes;
175
- }
176
- static SafeFileHandle CreateRelative(SafeFileHandle parent,string name) {
177
- byte[] security=PrivateSecurity();
178
- var pin=GCHandle.Alloc(security,GCHandleType.Pinned);
179
- IntPtr nameBuffer=Marshal.StringToHGlobalUni(name), unicodeBuffer=IntPtr.Zero;
180
- try {
181
- int byteLength=checked(name.Length*2);
182
- Require(byteLength>0 && byteLength<=65532,"EINVAL","private directory name is invalid");
183
- var unicode=new UnicodeString { Length=(ushort)byteLength, MaximumLength=(ushort)(byteLength+2), Buffer=nameBuffer };
184
- unicodeBuffer=Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnicodeString))); Marshal.StructureToPtr(unicode,unicodeBuffer,false);
185
- var attributes=new ObjectAttributes { Length=(uint)Marshal.SizeOf(typeof(ObjectAttributes)),RootDirectory=parent.DangerousGetHandle(),
186
- ObjectName=unicodeBuffer,Attributes=0x40|0x1000,SecurityDescriptor=pin.AddrOfPinnedObject() };
187
- IoStatus io; SafeFileHandle created;
188
- int status=NtCreateFile(out created,0x00130180,ref attributes,out io,IntPtr.Zero,0,7,2,0x00200021,IntPtr.Zero,0);
189
- if(status<0) { if(created!=null) created.Dispose(); throw CreateFailure(RtlNtStatusToDosError(status)); }
190
- return created;
191
- } finally { if(unicodeBuffer!=IntPtr.Zero) Marshal.FreeHGlobal(unicodeBuffer); Marshal.FreeHGlobal(nameBuffer); pin.Free(); }
192
- }
193
- static void RequirePrivate(Dictionary<string,object> facts, bool requireProtected=true, bool requirePrivateChildren=false, bool allowAdministratorsOwner=false) {
194
- string current=(string)facts["currentUserSid"], owner=(string)facts["ownerSid"];
195
- Require((bool)facts["isLocal"] && (bool)facts["daclPresent"] && (!requireProtected || (bool)facts["daclProtected"]) &&
196
- (bool)facts["aceListComplete"] && (owner==current || (allowAdministratorsOwner && owner=="s-1-5-32-544")),
197
- "EACCES","private object security was not enforced");
198
- foreach(Dictionary<string,object> ace in (object[])facts["aces"]) {
199
- var flags=(Dictionary<string,object>)ace["flags"];
200
- string sid=(string)ace["sid"];
201
- if((string)ace["aceType"]=="deny" || sid==current || sid=="s-1-5-18" || sid=="s-1-5-32-544") continue;
202
- if((bool)flags["inheritOnly"] && (!requirePrivateChildren || (!(bool)flags["objectInherit"] && !(bool)flags["containerInherit"]))) continue;
203
- uint mask=(uint)ace["mask"];
204
- Require((mask&0xd00d01dfu)==0,"EACCES","private object permits untrusted access");
205
- }
206
- }
207
- static void SplitParent(string path, out string parentPath, out string name) {
208
- // JavaScript has already admitted and resolved this spelling. Keep extended
209
- // Win32 paths out of .NET Framework's separate pathname normalization.
210
- int separator=path.LastIndexOf('\\');
211
- Require(separator>0 && separator<path.Length-1,"EINVAL","private object must name a child");
212
- parentPath=path.Substring(0,separator); name=path.Substring(separator+1);
213
- if(parentPath.EndsWith(":")) parentPath+="\\";
214
- }
215
- static string ExpectedIdentity(string variable, bool required=true) {
216
- string identity=Environment.GetEnvironmentVariable(variable) ?? "";
217
- Require((!required && identity.Length==0) || System.Text.RegularExpressions.Regex.IsMatch(identity,@"\A[0-9a-f]{16}:[0-9a-f]{32}\z"),
218
- "EINVAL","complete expected Windows identity is required");
219
- return identity;
220
- }
221
- static void CheckParent(SafeFileHandle parent, string path, string identity) {
222
- Require(DirectoryIdentity(parent,true)==identity,"EIO","retained private parent changed");
223
- using(var named=Open(path,0x80,true)) Require(DirectoryIdentity(named,true)==identity,"EIO","private parent pathname changed");
224
- }
225
- static object InspectDirectory(string path) {
226
- bool requirePrivate=Environment.GetEnvironmentVariable("FS_SAFE_WINDOWS_SECURITY_REQUIRE_PRIVATE")=="1";
227
- using(var handle=Open(path,requirePrivate ? 0x00020080u : 0x80u,true)) {
228
- string identity=DirectoryIdentity(handle,true);
229
- if(requirePrivate) RequirePrivate(Security(handle),true,true);
230
- return Row("identity",identity);
231
- }
232
- }
233
- static void ProtectFileSecurity(SafeFileHandle handle) {
234
- byte[] security=PrivateSecurity(false);
235
- var pin=GCHandle.Alloc(security,GCHandleType.Pinned);
236
- try {
237
- bool present,defaulted; IntPtr dacl,owner;
238
- if(!GetSecurityDescriptorDacl(pin.AddrOfPinnedObject(),out present,out dacl,out defaulted)) {
239
- throw OsFailure((uint)Marshal.GetLastWin32Error(),"inspect private file DACL");
240
- }
241
- Require(present && dacl!=IntPtr.Zero,"EIO","private file DACL is incomplete");
242
- if(!GetSecurityDescriptorOwner(pin.AddrOfPinnedObject(),out owner,out defaulted)) {
243
- throw OsFailure((uint)Marshal.GetLastWin32Error(),"inspect private file owner");
244
- }
245
- Require(owner!=IntPtr.Zero,"EIO","private file owner is incomplete");
246
- uint error=SetSecurityInfo(handle,1,0x80000005u,owner,IntPtr.Zero,dacl,IntPtr.Zero);
247
- if(error!=0) throw OsFailure(error,"protect private file owner and DACL");
248
- } finally { pin.Free(); }
249
- }
250
- static void CheckFileAssociation(SafeFileHandle held, string path, string identity, uint links, SafeFileHandle parent, string parentPath, string parentIdentity) {
251
- Require(FileIdentity(held,links)==identity,"EIO","retained private file changed");
252
- using(var named=Open(path,0x80,true)) Require(FileIdentity(named,links)==identity,"EIO","private file pathname changed");
253
- CheckParent(parent,parentPath,parentIdentity);
254
- }
255
- static object PrivateFile(string path, bool protect) {
256
- string expectedParent=ExpectedIdentity("FS_SAFE_WINDOWS_SECURITY_PARENT_IDENTITY");
257
- string expectedFile=protect ? "" : ExpectedIdentity("FS_SAFE_WINDOWS_SECURITY_FILE_IDENTITY");
258
- uint links=1;
259
- if(!protect) Require(uint.TryParse(Environment.GetEnvironmentVariable("FS_SAFE_WINDOWS_SECURITY_EXPECTED_LINKS"),
260
- System.Globalization.NumberStyles.None,System.Globalization.CultureInfo.InvariantCulture,out links) && links>0,
261
- "EINVAL","private file expected link count is invalid");
262
- string parentPath,name; SplitParent(path,out parentPath,out name);
263
- using(var held=new SafeFileHandle(GetStdHandle(-10),false)) {
264
- Require(!held.IsInvalid,"EBADF","inherited file handle is unavailable");
265
- string identity=FileIdentity(held,links);
266
- if(!protect) Require(identity==expectedFile,"EIO","private file identity changed");
267
- // Windows can use Administrators as the creating token's default owner.
268
- // The inherited ACL must already be private: later changes cannot revoke
269
- // an earlier reader handle.
270
- RequirePrivate(Security(held),requireProtected:!protect,allowAdministratorsOwner:protect);
271
- using(var parent=Open(parentPath,0x80,true)) {
272
- CheckFileAssociation(held,path,identity,links,parent,parentPath,expectedParent);
273
- if(protect) using(var writable=Open(path,0x000e0080,true)) {
274
- Require(FileIdentity(writable,links)==identity,"EIO","private file changed before owner and DACL protection");
275
- RequirePrivate(Security(writable),requireProtected:false,allowAdministratorsOwner:true);
276
- CheckParent(parent,parentPath,expectedParent);
277
- ProtectFileSecurity(writable);
278
- RequirePrivate(Security(writable));
279
- }
280
- RequirePrivate(Security(held));
281
- CheckFileAssociation(held,path,identity,links,parent,parentPath,expectedParent);
282
- return Row("identity",identity);
283
- }
284
- }
285
- }
286
- static object CreatePrivate(string path) {
287
- string parentPath,name; SplitParent(path,out parentPath,out name);
288
- string expectedParent=ExpectedIdentity("FS_SAFE_WINDOWS_SECURITY_PARENT_IDENTITY",false);
289
- using(var parent=Open(parentPath,0xa4,true)) {
290
- string parentId=DirectoryIdentity(parent,true);
291
- if(expectedParent.Length!=0) Require(parentId==expectedParent,"EIO","private parent changed before creation");
292
- using(var created=CreateRelative(parent,name)) {
293
- try {
294
- string createdId=DirectoryIdentity(created);
295
- RequirePrivate(Security(created));
296
- Require(DirectoryIdentity(parent)==parentId,"EIO","retained private parent changed");
297
- using(var namedParent=Open(parentPath,0x80,true)) Require(DirectoryIdentity(namedParent,true)==parentId,"EIO","private parent pathname changed");
298
- using(var named=Open(path,0x80,true)) {
299
- Require(DirectoryIdentity(named,true)==createdId,"EIO","private directory pathname changed");
300
- }
301
- return Row("created",true,"identity",createdId);
302
- } catch(Exception primary) {
303
- uint flags=0x13;
304
- if(!SetFileInformationByHandle(created,21,ref flags,4)) {
305
- var failure=primary as Failure;
306
- throw new Failure(failure==null ? "EIO" : failure.Code,
307
- (failure==null ? "private directory validation failed" : failure.Message)+
308
- "; owned-handle cleanup failed with Windows error "+Marshal.GetLastWin32Error());
309
- }
310
- throw;
311
- }
312
- }
313
- }
314
- }
315
- static object InspectPath(string path) {
316
- // Raw reporting retains ACL facts when locality is unknown; admission remains strict.
317
- using(var handle=Open(path,0x00020080,false)) return Security(handle,false);
318
- }
319
- public static object Execute(string operation,string path) {
320
- try {
321
- object result;
322
- if(operation=="create") result=CreatePrivate(path);
323
- else if(operation=="directory") result=InspectDirectory(path);
324
- else if(operation=="protect-file" || operation=="verify-file") result=PrivateFile(path,operation=="protect-file");
325
- else if(operation=="descriptor") {
326
- using(var handle=new SafeFileHandle(GetStdHandle(-10),false)) {
327
- Require(!handle.IsInvalid,"EBADF","inherited file handle is unavailable");
328
- result=Row("identity",Identity(handle),"security",Security(handle));
329
- }
330
- } else if(operation=="path") result=InspectPath(path);
331
- else throw new Failure("EINVAL","unknown Windows security operation");
332
- return Row("ok",true,"result",result);
333
- } catch(Failure error) { return Row("ok",false,"code",error.Code,"message",error.Message); }
334
- catch(Exception) { return Row("ok",false,"code","EIO","message","Windows security descriptor processing failed"); }
335
- }
336
- }
@@ -1,90 +0,0 @@
1
- param(
2
- [Parameter(Mandatory = $true)]
3
- [ValidateSet('path', 'paths', 'descriptor', 'create', 'directory', 'protect-file', 'verify-file')]
4
- [string] $Operation
5
- )
6
-
7
- $ErrorActionPreference = 'Stop'
8
- $ProgressPreference = 'SilentlyContinue'
9
- # Avoid scanning unrelated installed modules before loading system cmdlets.
10
- $env:PSModulePath = [IO.Path]::Combine($PSHOME, 'Modules')
11
- [Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
12
-
13
- Microsoft.PowerShell.Utility\Add-Type -LiteralPath ([IO.Path]::Combine($PSScriptRoot, 'windows-security-bridge.cs'))
14
- if ($Operation -eq 'paths') {
15
- $reply = $null
16
- $limit = 16 * 1024 * 1024
17
- try {
18
- $inputStream = [Console]::OpenStandardInput()
19
- $inputBytes = [IO.MemoryStream]::new()
20
- try {
21
- $buffer = [byte[]]::new(8192)
22
- while (($read = $inputStream.Read($buffer, 0, $buffer.Length)) -gt 0) {
23
- if ($inputBytes.Length + $read -gt $limit) {
24
- throw 'Windows security path batch exceeds the input budget'
25
- }
26
- $inputBytes.Write($buffer, 0, $read)
27
- }
28
- $inputJson = [Text.UTF8Encoding]::new($false, $true).GetString($inputBytes.ToArray())
29
- } finally {
30
- $inputBytes.Dispose()
31
- $inputStream.Dispose()
32
- }
33
- if (-not $inputJson.TrimStart().StartsWith('[')) {
34
- throw 'Windows security paths must be a JSON array'
35
- }
36
- # Validate the whole document before wrapping it; the wrapper keeps empty,
37
- # singleton, and nested arrays intact on Windows PowerShell 5.1.
38
- $null = Microsoft.PowerShell.Utility\ConvertFrom-Json -InputObject $inputJson
39
- $request = Microsoft.PowerShell.Utility\ConvertFrom-Json -InputObject ('{"paths":' + $inputJson + '}')
40
- if ($request.paths -isnot [array]) {
41
- throw 'Windows security paths must be a JSON array'
42
- }
43
- for ($index = 0; $index -lt $request.paths.Length; $index++) {
44
- $value = $request.paths[$index]
45
- if ($value -isnot [string] -or $value.Length -eq 0 -or $value.IndexOf([char]0) -ge 0) {
46
- throw 'Windows security paths must be nonempty strings without NUL bytes'
47
- }
48
- }
49
- } catch {
50
- $reply = @{ ok = $false; code = 'EINVAL'; message = 'Invalid Windows security path batch' }
51
- }
52
- if ($null -eq $reply) {
53
- $utf8 = [Console]::OutputEncoding
54
- $prefix = '{"ok":true,"result":['
55
- $suffix = ']}'
56
- $bytes = $utf8.GetByteCount($prefix) + $utf8.GetByteCount($suffix)
57
- $encoded = [Text.StringBuilder]::new($prefix)
58
- $separator = ''
59
- foreach ($pathname in $request.paths) {
60
- try {
61
- $reply = [FsSafeWindowsBridge]::Execute('path', $pathname)
62
- } catch {
63
- $reply = @{ ok = $false; code = 'EINVAL'; message = 'Invalid Windows security path batch' }
64
- }
65
- if (-not $reply.ok) { break }
66
- $rowJson = Microsoft.PowerShell.Utility\ConvertTo-Json -InputObject ([ordered]@{ path = $pathname; security = $reply.result }) -Depth 8 -Compress
67
- $reply = $null
68
- $nextBytes = $bytes + $separator.Length + $utf8.GetByteCount($rowJson)
69
- if ($nextBytes -gt $limit) {
70
- $rowJson = $null
71
- $reply = @{ ok = $false; code = 'too-large'; message = 'Windows security batch exceeded its output budget' }
72
- break
73
- }
74
- [void]$encoded.Append($separator).Append($rowJson)
75
- $bytes = $nextBytes
76
- $separator = ','
77
- $rowJson = $null
78
- }
79
- if ($null -eq $reply) {
80
- [void]$encoded.Append($suffix)
81
- [Console]::Write($encoded.ToString())
82
- return
83
- }
84
- $encoded = $null
85
- }
86
- } else {
87
- $targetPath = [Environment]::GetEnvironmentVariable('FS_SAFE_WINDOWS_SECURITY_PATH')
88
- $reply = [FsSafeWindowsBridge]::Execute($Operation, $targetPath)
89
- }
90
- $reply | Microsoft.PowerShell.Utility\ConvertTo-Json -Depth 8 -Compress