@openclaw/fs-safe 0.12.0 → 0.13.0

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 (383) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +12 -7
  3. package/dist/absolute-path.d.ts.map +1 -1
  4. package/dist/absolute-path.js +32 -11
  5. package/dist/advanced.d.ts +2 -0
  6. package/dist/advanced.d.ts.map +1 -1
  7. package/dist/advanced.js +2 -0
  8. package/dist/archive-input.d.ts.map +1 -1
  9. package/dist/archive-input.js +6 -2
  10. package/dist/archive-merge.d.ts.map +1 -1
  11. package/dist/archive-merge.js +15 -2
  12. package/dist/archive-native.d.ts.map +1 -1
  13. package/dist/archive-native.js +7 -19
  14. package/dist/archive-plan.js +1 -1
  15. package/dist/archive-read.d.ts.map +1 -1
  16. package/dist/archive-read.js +18 -13
  17. package/dist/archive-staging.d.ts.map +1 -1
  18. package/dist/archive-staging.js +43 -10
  19. package/dist/archive-tar-inspect.d.ts.map +1 -1
  20. package/dist/archive-tar-inspect.js +4 -1
  21. package/dist/archive-zip-admission.d.ts +1 -1
  22. package/dist/archive-zip-admission.d.ts.map +1 -1
  23. package/dist/archive-zip-admission.js +2 -2
  24. package/dist/archive-zip-directory.d.ts +3 -0
  25. package/dist/archive-zip-directory.d.ts.map +1 -1
  26. package/dist/archive-zip-directory.js +13 -2
  27. package/dist/archive-zip-loader.d.ts +3 -2
  28. package/dist/archive-zip-loader.d.ts.map +1 -1
  29. package/dist/archive-zip-loader.js +30 -4
  30. package/dist/archive-zip-manifest.d.ts +5 -0
  31. package/dist/archive-zip-manifest.d.ts.map +1 -0
  32. package/dist/archive-zip-manifest.js +22 -0
  33. package/dist/archive-zip-names.d.ts +6 -1
  34. package/dist/archive-zip-names.d.ts.map +1 -1
  35. package/dist/archive-zip-names.js +35 -14
  36. package/dist/archive-zip-preflight.d.ts.map +1 -1
  37. package/dist/archive-zip-preflight.js +3 -2
  38. package/dist/archive.d.ts.map +1 -1
  39. package/dist/archive.js +9 -4
  40. package/dist/darwin-acl.d.ts +4 -0
  41. package/dist/darwin-acl.d.ts.map +1 -0
  42. package/dist/darwin-acl.js +24 -0
  43. package/dist/deny-mutations.d.ts.map +1 -1
  44. package/dist/deny-mutations.js +8 -2
  45. package/dist/directory-durability.d.ts.map +1 -1
  46. package/dist/directory-durability.js +67 -23
  47. package/dist/directory-entry-path.d.ts +3 -0
  48. package/dist/directory-entry-path.d.ts.map +1 -0
  49. package/dist/directory-entry-path.js +21 -0
  50. package/dist/directory-guard.d.ts +17 -1
  51. package/dist/directory-guard.d.ts.map +1 -1
  52. package/dist/directory-guard.js +134 -48
  53. package/dist/directory-mode-node.d.ts +12 -0
  54. package/dist/directory-mode-node.d.ts.map +1 -1
  55. package/dist/directory-mode-node.js +102 -4
  56. package/dist/effective-uid.d.ts +2 -0
  57. package/dist/effective-uid.d.ts.map +1 -0
  58. package/dist/effective-uid.js +25 -0
  59. package/dist/file-handle-transfer.d.ts.map +1 -1
  60. package/dist/file-handle-transfer.js +98 -27
  61. package/dist/file-hash.d.ts.map +1 -1
  62. package/dist/file-hash.js +3 -0
  63. package/dist/file-lock-sync.d.ts.map +1 -1
  64. package/dist/file-lock-sync.js +36 -6
  65. package/dist/file-lock.d.ts.map +1 -1
  66. package/dist/file-lock.js +29 -9
  67. package/dist/file-observation.d.ts +1 -1
  68. package/dist/file-observation.d.ts.map +1 -1
  69. package/dist/file-store-boundary.d.ts +6 -2
  70. package/dist/file-store-boundary.d.ts.map +1 -1
  71. package/dist/file-store-boundary.js +20 -65
  72. package/dist/file-store-copy-source.d.ts +5 -0
  73. package/dist/file-store-copy-source.d.ts.map +1 -0
  74. package/dist/file-store-copy-source.js +31 -0
  75. package/dist/file-store-path.d.ts.map +1 -1
  76. package/dist/file-store-path.js +4 -1
  77. package/dist/file-store-sync-directory.d.ts +16 -0
  78. package/dist/file-store-sync-directory.d.ts.map +1 -0
  79. package/dist/file-store-sync-directory.js +349 -0
  80. package/dist/file-store.d.ts.map +1 -1
  81. package/dist/file-store.js +11 -28
  82. package/dist/filename.d.ts.map +1 -1
  83. package/dist/filename.js +65 -20
  84. package/dist/fs.d.ts.map +1 -1
  85. package/dist/fs.js +3 -2
  86. package/dist/guarded-mkdir.d.ts +8 -0
  87. package/dist/guarded-mkdir.d.ts.map +1 -1
  88. package/dist/guarded-mkdir.js +176 -27
  89. package/dist/guest.d.ts.map +1 -1
  90. package/dist/guest.js +4 -1
  91. package/dist/home-dir.d.ts.map +1 -1
  92. package/dist/home-dir.js +73 -10
  93. package/dist/install-path.d.ts.map +1 -1
  94. package/dist/install-path.js +54 -19
  95. package/dist/json-durable-queue-ownership.d.ts +6 -0
  96. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  97. package/dist/json-durable-queue-ownership.js +89 -42
  98. package/dist/json-durable-queue-paths.d.ts +11 -0
  99. package/dist/json-durable-queue-paths.d.ts.map +1 -0
  100. package/dist/json-durable-queue-paths.js +42 -0
  101. package/dist/json-durable-queue-read.d.ts.map +1 -1
  102. package/dist/json-durable-queue-read.js +2 -0
  103. package/dist/json-durable-queue.d.ts.map +1 -1
  104. package/dist/json-durable-queue.js +50 -58
  105. package/dist/json-store.d.ts.map +1 -1
  106. package/dist/json-store.js +5 -1
  107. package/dist/json.d.ts.map +1 -1
  108. package/dist/json.js +54 -22
  109. package/dist/local-file-access.d.ts.map +1 -1
  110. package/dist/local-file-access.js +4 -0
  111. package/dist/local-file-descriptor.d.ts +17 -0
  112. package/dist/local-file-descriptor.d.ts.map +1 -0
  113. package/dist/local-file-descriptor.js +84 -0
  114. package/dist/local-roots.d.ts.map +1 -1
  115. package/dist/local-roots.js +35 -7
  116. package/dist/move-path-cleanup.d.ts +2 -0
  117. package/dist/move-path-cleanup.d.ts.map +1 -1
  118. package/dist/move-path-cleanup.js +44 -18
  119. package/dist/move-path.d.ts.map +1 -1
  120. package/dist/move-path.js +31 -6
  121. package/dist/native-binding.d.ts +14 -0
  122. package/dist/native-binding.d.ts.map +1 -1
  123. package/dist/native-directory-observation.d.ts +17 -0
  124. package/dist/native-directory-observation.d.ts.map +1 -0
  125. package/dist/native-directory-observation.js +37 -0
  126. package/dist/native-parent-admission.d.ts +31 -0
  127. package/dist/native-parent-admission.d.ts.map +1 -0
  128. package/dist/native-parent-admission.js +124 -0
  129. package/dist/native-pinned-write-windows.d.ts +0 -1
  130. package/dist/native-pinned-write-windows.d.ts.map +1 -1
  131. package/dist/native-pinned-write-windows.js +0 -3
  132. package/dist/native-pinned-write.d.ts.map +1 -1
  133. package/dist/native-pinned-write.js +309 -40
  134. package/dist/output.d.ts.map +1 -1
  135. package/dist/output.js +15 -5
  136. package/dist/overwrite-file-handle.d.ts.map +1 -1
  137. package/dist/overwrite-file-handle.js +5 -1
  138. package/dist/owner-dacl.d.ts.map +1 -1
  139. package/dist/owner-dacl.js +2 -0
  140. package/dist/path-policy.d.ts.map +1 -1
  141. package/dist/path-policy.js +7 -2
  142. package/dist/path-prefix.d.ts +7 -0
  143. package/dist/path-prefix.d.ts.map +1 -0
  144. package/dist/path-prefix.js +82 -0
  145. package/dist/path-scope-lexical.d.ts.map +1 -1
  146. package/dist/path-scope-lexical.js +18 -8
  147. package/dist/path-segment-route.d.ts +7 -0
  148. package/dist/path-segment-route.d.ts.map +1 -0
  149. package/dist/path-segment-route.js +24 -0
  150. package/dist/path-suffix-aliases.d.ts +10 -0
  151. package/dist/path-suffix-aliases.d.ts.map +1 -0
  152. package/dist/path-suffix-aliases.js +386 -0
  153. package/dist/path.d.ts.map +1 -1
  154. package/dist/path.js +16 -5
  155. package/dist/permissions-windows.d.ts.map +1 -1
  156. package/dist/permissions-windows.js +14 -3
  157. package/dist/permissions.d.ts.map +1 -1
  158. package/dist/permissions.js +37 -8
  159. package/dist/pinned-mutation-admission.d.ts +25 -0
  160. package/dist/pinned-mutation-admission.d.ts.map +1 -0
  161. package/dist/pinned-mutation-admission.js +425 -0
  162. package/dist/pinned-mutation-observation.d.ts +34 -0
  163. package/dist/pinned-mutation-observation.d.ts.map +1 -0
  164. package/dist/pinned-mutation-observation.js +142 -0
  165. package/dist/pinned-mutation-shared-route.d.ts +24 -0
  166. package/dist/pinned-mutation-shared-route.d.ts.map +1 -0
  167. package/dist/pinned-mutation-shared-route.js +70 -0
  168. package/dist/pinned-open.d.ts +6 -0
  169. package/dist/pinned-open.d.ts.map +1 -1
  170. package/dist/pinned-open.js +28 -10
  171. package/dist/pinned-write-types.d.ts +75 -0
  172. package/dist/pinned-write-types.d.ts.map +1 -0
  173. package/dist/pinned-write-types.js +1 -0
  174. package/dist/pinned-write.d.ts +7 -33
  175. package/dist/pinned-write.d.ts.map +1 -1
  176. package/dist/pinned-write.js +151 -17
  177. package/dist/private-directory.d.ts.map +1 -1
  178. package/dist/private-directory.js +2 -0
  179. package/dist/private-producer-handoff.d.ts +16 -0
  180. package/dist/private-producer-handoff.d.ts.map +1 -0
  181. package/dist/private-producer-handoff.js +272 -0
  182. package/dist/private-temp-workspace.d.ts +2 -39
  183. package/dist/private-temp-workspace.d.ts.map +1 -1
  184. package/dist/private-temp-workspace.js +183 -77
  185. package/dist/publish-file.d.ts.map +1 -1
  186. package/dist/publish-file.js +33 -29
  187. package/dist/regular-file.d.ts.map +1 -1
  188. package/dist/regular-file.js +56 -45
  189. package/dist/replace-directory.d.ts.map +1 -1
  190. package/dist/replace-directory.js +12 -5
  191. package/dist/replace-file-temp-owner.d.ts +1 -0
  192. package/dist/replace-file-temp-owner.d.ts.map +1 -1
  193. package/dist/replace-file-temp-owner.js +12 -1
  194. package/dist/replace-file.d.ts.map +1 -1
  195. package/dist/replace-file.js +24 -24
  196. package/dist/root-boundary.d.ts +4 -0
  197. package/dist/root-boundary.d.ts.map +1 -1
  198. package/dist/root-boundary.js +6 -1
  199. package/dist/root-context.d.ts +12 -1
  200. package/dist/root-context.d.ts.map +1 -1
  201. package/dist/root-context.js +57 -11
  202. package/dist/root-directory-creation.d.ts +13 -0
  203. package/dist/root-directory-creation.d.ts.map +1 -0
  204. package/dist/root-directory-creation.js +212 -0
  205. package/dist/root-directory-list.d.ts +16 -4
  206. package/dist/root-directory-list.d.ts.map +1 -1
  207. package/dist/root-directory-list.js +180 -39
  208. package/dist/root-directory.d.ts +23 -0
  209. package/dist/root-directory.d.ts.map +1 -0
  210. package/dist/root-directory.js +141 -0
  211. package/dist/root-errors.d.ts.map +1 -1
  212. package/dist/root-errors.js +12 -1
  213. package/dist/root-file-final-admission.d.ts +21 -0
  214. package/dist/root-file-final-admission.d.ts.map +1 -0
  215. package/dist/root-file-final-admission.js +83 -0
  216. package/dist/root-file.d.ts.map +1 -1
  217. package/dist/root-file.js +103 -24
  218. package/dist/root-impl.d.ts +1 -0
  219. package/dist/root-impl.d.ts.map +1 -1
  220. package/dist/root-impl.js +289 -317
  221. package/dist/root-move-noreplace.d.ts +14 -0
  222. package/dist/root-move-noreplace.d.ts.map +1 -0
  223. package/dist/root-move-noreplace.js +202 -0
  224. package/dist/root-observed-path.d.ts +9 -0
  225. package/dist/root-observed-path.d.ts.map +1 -0
  226. package/dist/root-observed-path.js +95 -0
  227. package/dist/root-path-errors.d.ts +12 -0
  228. package/dist/root-path-errors.d.ts.map +1 -0
  229. package/dist/root-path-errors.js +13 -0
  230. package/dist/root-path-existing.d.ts.map +1 -1
  231. package/dist/root-path-existing.js +53 -20
  232. package/dist/root-path-observation.d.ts +63 -0
  233. package/dist/root-path-observation.d.ts.map +1 -0
  234. package/dist/root-path-observation.js +180 -0
  235. package/dist/root-path-stat.d.ts +5 -0
  236. package/dist/root-path-stat.d.ts.map +1 -0
  237. package/dist/root-path-stat.js +101 -0
  238. package/dist/root-path-symlink.d.ts.map +1 -1
  239. package/dist/root-path-symlink.js +23 -4
  240. package/dist/root-path.d.ts +11 -0
  241. package/dist/root-path.d.ts.map +1 -1
  242. package/dist/root-path.js +215 -53
  243. package/dist/root-paths-lexical.d.ts +9 -0
  244. package/dist/root-paths-lexical.d.ts.map +1 -0
  245. package/dist/root-paths-lexical.js +22 -0
  246. package/dist/root-paths.d.ts +3 -25
  247. package/dist/root-paths.d.ts.map +1 -1
  248. package/dist/root-paths.js +77 -154
  249. package/dist/root-read-admission.d.ts +26 -0
  250. package/dist/root-read-admission.d.ts.map +1 -0
  251. package/dist/root-read-admission.js +94 -0
  252. package/dist/root-remove-identity.d.ts +15 -0
  253. package/dist/root-remove-identity.d.ts.map +1 -0
  254. package/dist/root-remove-identity.js +89 -0
  255. package/dist/root-remove-receipt.d.ts +17 -0
  256. package/dist/root-remove-receipt.d.ts.map +1 -0
  257. package/dist/root-remove-receipt.js +37 -0
  258. package/dist/root-remove.d.ts +2 -1
  259. package/dist/root-remove.d.ts.map +1 -1
  260. package/dist/root-remove.js +172 -10
  261. package/dist/root-write-admission.d.ts +68 -0
  262. package/dist/root-write-admission.d.ts.map +1 -0
  263. package/dist/root-write-admission.js +322 -0
  264. package/dist/root-write-compatibility.d.ts +13 -0
  265. package/dist/root-write-compatibility.d.ts.map +1 -0
  266. package/dist/root-write-compatibility.js +74 -0
  267. package/dist/root-write-complete-parent.d.ts +42 -0
  268. package/dist/root-write-complete-parent.d.ts.map +1 -0
  269. package/dist/root-write-complete-parent.js +195 -0
  270. package/dist/root-write-publication.d.ts +24 -0
  271. package/dist/root-write-publication.d.ts.map +1 -0
  272. package/dist/root-write-publication.js +85 -0
  273. package/dist/root-write-verification.d.ts.map +1 -1
  274. package/dist/root-write-verification.js +6 -4
  275. package/dist/secret-file.d.ts.map +1 -1
  276. package/dist/secret-file.js +62 -24
  277. package/dist/secret-read-async.d.ts.map +1 -1
  278. package/dist/secret-read-async.js +18 -13
  279. package/dist/secret-read-policy.d.ts.map +1 -1
  280. package/dist/secret-read-policy.js +5 -1
  281. package/dist/secure-file.d.ts.map +1 -1
  282. package/dist/secure-file.js +92 -7
  283. package/dist/secure-temp-dir.d.ts +6 -3
  284. package/dist/secure-temp-dir.d.ts.map +1 -1
  285. package/dist/secure-temp-dir.js +121 -101
  286. package/dist/secure-temp-repair.d.ts +35 -0
  287. package/dist/secure-temp-repair.d.ts.map +1 -0
  288. package/dist/secure-temp-repair.js +106 -0
  289. package/dist/sibling-staged-file.d.ts +3 -2
  290. package/dist/sibling-staged-file.d.ts.map +1 -1
  291. package/dist/sibling-staged-file.js +179 -55
  292. package/dist/sibling-temp.d.ts.map +1 -1
  293. package/dist/sibling-temp.js +27 -13
  294. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  295. package/dist/sidecar-lock-acquire.js +44 -14
  296. package/dist/sidecar-lock-root.d.ts.map +1 -1
  297. package/dist/sidecar-lock-root.js +4 -2
  298. package/dist/staged-directory.d.ts +14 -5
  299. package/dist/staged-directory.d.ts.map +1 -1
  300. package/dist/staged-directory.js +54 -3
  301. package/dist/standalone-publication-path.d.ts +2 -0
  302. package/dist/standalone-publication-path.d.ts.map +1 -0
  303. package/dist/standalone-publication-path.js +6 -0
  304. package/dist/stat-observation.d.ts +11 -0
  305. package/dist/stat-observation.d.ts.map +1 -0
  306. package/dist/stat-observation.js +64 -0
  307. package/dist/strict-file-identity.d.ts.map +1 -1
  308. package/dist/strict-file-identity.js +39 -2
  309. package/dist/symlink-parents.d.ts.map +1 -1
  310. package/dist/symlink-parents.js +7 -2
  311. package/dist/temp-target.d.ts +2 -0
  312. package/dist/temp-target.d.ts.map +1 -1
  313. package/dist/temp-target.js +130 -3
  314. package/dist/temp-workspace-admission.d.ts +22 -0
  315. package/dist/temp-workspace-admission.d.ts.map +1 -0
  316. package/dist/temp-workspace-admission.js +374 -0
  317. package/dist/temp-workspace-child-admission.d.ts +13 -0
  318. package/dist/temp-workspace-child-admission.d.ts.map +1 -0
  319. package/dist/temp-workspace-child-admission.js +95 -0
  320. package/dist/temp-workspace-descriptor.d.ts +48 -0
  321. package/dist/temp-workspace-descriptor.d.ts.map +1 -0
  322. package/dist/temp-workspace-descriptor.js +363 -0
  323. package/dist/temp-workspace-identity.d.ts +15 -0
  324. package/dist/temp-workspace-identity.d.ts.map +1 -0
  325. package/dist/temp-workspace-identity.js +41 -0
  326. package/dist/temp-workspace-owner.d.ts +7 -6
  327. package/dist/temp-workspace-owner.d.ts.map +1 -1
  328. package/dist/temp-workspace-owner.js +121 -61
  329. package/dist/temp-workspace-permissions.d.ts +4 -0
  330. package/dist/temp-workspace-permissions.d.ts.map +1 -0
  331. package/dist/temp-workspace-permissions.js +32 -0
  332. package/dist/temp-workspace-types.d.ts +40 -0
  333. package/dist/temp-workspace-types.d.ts.map +1 -0
  334. package/dist/temp-workspace-types.js +1 -0
  335. package/dist/temp.d.ts +1 -1
  336. package/dist/temp.d.ts.map +1 -1
  337. package/dist/temp.js +1 -1
  338. package/dist/test-hooks.d.ts +7 -0
  339. package/dist/test-hooks.d.ts.map +1 -1
  340. package/dist/text-atomic.d.ts.map +1 -1
  341. package/dist/text-atomic.js +3 -1
  342. package/dist/trash.d.ts.map +1 -1
  343. package/dist/trash.js +54 -8
  344. package/dist/walk.d.ts.map +1 -1
  345. package/dist/walk.js +9 -6
  346. package/dist/windows-owner.d.ts.map +1 -1
  347. package/dist/windows-owner.js +5 -0
  348. package/dist/windows-path-alias.d.ts +39 -0
  349. package/dist/windows-path-alias.d.ts.map +1 -0
  350. package/dist/windows-path-alias.js +153 -0
  351. package/docs/advanced.md +25 -0
  352. package/docs/archive.md +23 -2
  353. package/docs/atomic.md +27 -3
  354. package/docs/copy.md +3 -0
  355. package/docs/durability.md +14 -0
  356. package/docs/errors.md +14 -6
  357. package/docs/file-store.md +24 -3
  358. package/docs/filename.md +14 -7
  359. package/docs/install-path.md +2 -2
  360. package/docs/install.md +8 -7
  361. package/docs/json-store.md +5 -1
  362. package/docs/json.md +11 -0
  363. package/docs/mutation-policy-proof.md +65 -0
  364. package/docs/native-helper.md +26 -9
  365. package/docs/native.md +32 -8
  366. package/docs/output.md +33 -11
  367. package/docs/path-prefix.md +64 -0
  368. package/docs/path-suffix-aliases.md +159 -0
  369. package/docs/path.md +11 -0
  370. package/docs/private-file-store.md +14 -0
  371. package/docs/public-api.md +9 -0
  372. package/docs/quickstart.md +1 -1
  373. package/docs/reading.md +8 -1
  374. package/docs/root.md +18 -3
  375. package/docs/secret-file.md +3 -0
  376. package/docs/secure-file.md +6 -2
  377. package/docs/security-model.md +75 -8
  378. package/docs/sidecar-lock.md +28 -1
  379. package/docs/store.md +5 -1
  380. package/docs/temp.md +260 -36
  381. package/docs/test-hooks.md +14 -0
  382. package/docs/writing.md +38 -8
  383. package/package.json +10 -10
@@ -1,5 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { isPathInside, isPathRelativeEscape } from "./path.js";
3
+ import { hasWindowsPathAlias, resolvePathFromBasePreservingWindowsRoot } from "./windows-path-alias.js";
3
4
  function pathStaysWithinRoot(rootDir, candidatePath) {
4
5
  if (process.platform !== "win32") {
5
6
  return candidatePath !== rootDir && isPathInside(rootDir, candidatePath);
@@ -8,20 +9,29 @@ function pathStaysWithinRoot(rootDir, candidatePath) {
8
9
  return Boolean(relative) && !isPathRelativeEscape(relative);
9
10
  }
10
11
  export function resolvePathWithinNormalizedRoot(params, root) {
11
- const raw = params.requestedPath.trim();
12
+ const requestedPath = params.requestedPath;
13
+ const defaultFileName = params.defaultFileName;
14
+ const scopeLabel = params.scopeLabel;
15
+ if (hasWindowsPathAlias(params.rootDir, "filesystem") ||
16
+ hasWindowsPathAlias(root, "filesystem") ||
17
+ hasWindowsPathAlias(requestedPath, "filesystem") ||
18
+ (defaultFileName !== undefined && hasWindowsPathAlias(defaultFileName, "filesystem"))) {
19
+ return { ok: false, error: `Invalid path: must stay within ${scopeLabel}` };
20
+ }
21
+ const raw = requestedPath.trim();
12
22
  if (!raw) {
13
- if (!params.defaultFileName) {
23
+ if (!defaultFileName) {
14
24
  return { ok: false, error: "path is required" };
15
25
  }
16
- const defaultPath = path.resolve(root, params.defaultFileName);
17
- if (!pathStaysWithinRoot(root, defaultPath)) {
18
- return { ok: false, error: `Invalid path: must stay within ${params.scopeLabel}` };
26
+ const defaultPath = resolvePathFromBasePreservingWindowsRoot(root, defaultFileName);
27
+ if (hasWindowsPathAlias(defaultPath, "filesystem") || !pathStaysWithinRoot(root, defaultPath)) {
28
+ return { ok: false, error: `Invalid path: must stay within ${scopeLabel}` };
19
29
  }
20
30
  return { ok: true, path: defaultPath };
21
31
  }
22
- const resolved = path.resolve(root, raw);
23
- if (!pathStaysWithinRoot(root, resolved)) {
24
- return { ok: false, error: `Invalid path: must stay within ${params.scopeLabel}` };
32
+ const resolved = resolvePathFromBasePreservingWindowsRoot(root, raw);
33
+ if (hasWindowsPathAlias(resolved, "filesystem") || !pathStaysWithinRoot(root, resolved)) {
34
+ return { ok: false, error: `Invalid path: must stay within ${scopeLabel}` };
25
35
  }
26
36
  return { ok: true, path: resolved };
27
37
  }
@@ -0,0 +1,7 @@
1
+ export type PathSegmentRoute = Readonly<{
2
+ joined: string;
3
+ offsets: readonly number[];
4
+ }>;
5
+ export declare function createPathSegmentRoute(segments: readonly string[]): PathSegmentRoute;
6
+ export declare function joinPathSegmentRoute(base: string, route: PathSegmentRoute, offset: number, tail?: string): string;
7
+ //# sourceMappingURL=path-segment-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-segment-route.d.ts","sourceRoot":"","sources":["../src/path-segment-route.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,CAAC,CAAC;AAEH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,CAUpF;AAID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CAMR"}
@@ -0,0 +1,24 @@
1
+ import path from "node:path";
2
+ export function createPathSegmentRoute(segments) {
3
+ const offsets = new Array(segments.length + 1);
4
+ let cursor = 0;
5
+ for (let index = 0; index < segments.length; index += 1) {
6
+ offsets[index] = cursor;
7
+ cursor += segments[index].length;
8
+ if (index + 1 < segments.length)
9
+ cursor += path.sep.length;
10
+ }
11
+ offsets[segments.length] = cursor;
12
+ return Object.freeze({ joined: segments.join(path.sep), offsets: Object.freeze(offsets) });
13
+ }
14
+ // Select the immutable suffix by character offset so callers perform at most
15
+ // one path normalization without copying a shrinking segment array.
16
+ export function joinPathSegmentRoute(base, route, offset, tail) {
17
+ const start = route.offsets[offset];
18
+ if (start === undefined)
19
+ throw new RangeError("path segment offset is outside the route");
20
+ const suffix = route.joined.slice(start);
21
+ if (suffix)
22
+ return tail === undefined ? path.join(base, suffix) : path.join(base, suffix, tail);
23
+ return tail === undefined ? base : path.join(base, tail);
24
+ }
@@ -0,0 +1,10 @@
1
+ export type ProbePathSuffixAliasesOptions = {
2
+ directory: string;
3
+ left: string;
4
+ right: string;
5
+ /** Synchronous caller policy for differing NFC pairs not equivalent under ASCII case folding. */
6
+ shouldProbeCaseVariants?: (leftNfc: string, rightNfc: string) => boolean;
7
+ };
8
+ /** Observe bounded missing suffix aliases; the caller owns caching and ambiguity policy. */
9
+ export declare function probePathSuffixAliasesSync(options: ProbePathSuffixAliasesOptions): boolean | undefined;
10
+ //# sourceMappingURL=path-suffix-aliases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-suffix-aliases.d.ts","sourceRoot":"","sources":["../src/path-suffix-aliases.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,uBAAuB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1E,CAAC;AA6UF,4FAA4F;AAC5F,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,GAAG,SAAS,CA8CtG"}
@@ -0,0 +1,386 @@
1
+ import { randomInt } from "node:crypto";
2
+ import fs, {} from "node:fs";
3
+ import path from "node:path";
4
+ import { assertDirectoryIdentitySync, inspectDirectoryIdentitySync } from "./directory-guard.js";
5
+ import { isWindowsReservedDeviceName } from "./device-path.js";
6
+ import { FsSafeError } from "./errors.js";
7
+ import { sameFileIdentityForCleanup } from "./file-identity.js";
8
+ import { hasNodeErrorCode } from "./path.js";
9
+ import { realpathSync } from "./realpath.js";
10
+ import { inspectFileIdentitySync } from "./strict-file-identity.js";
11
+ import { pathForWindowsFilesystem, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
12
+ const MAX_SUFFIX_LENGTH = 8_192;
13
+ const MAX_PATH_LENGTH = 32_768;
14
+ const MAX_SUFFIX_DEPTH = 32;
15
+ const MAX_MKDIR_ATTEMPTS = 128;
16
+ const MAX_CREATED_DIRECTORIES = 64;
17
+ const MAX_FORWARD_OBSERVATIONS = 4_096;
18
+ const PROBE_NAME_LENGTH = 6;
19
+ const PROBE_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
20
+ const PROBE_FIRST_ALPHABET = "bdefghijkmoqrstuvwxyz";
21
+ function unavailable() {
22
+ throw new Error("path suffix probe resources or cleanup authority are unavailable");
23
+ }
24
+ function assertMutationPath(value) {
25
+ if (value.length > MAX_PATH_LENGTH)
26
+ unavailable();
27
+ }
28
+ function suffixSegments(value) {
29
+ if (typeof value !== "string")
30
+ throw new TypeError("suffix must be a string");
31
+ if (value.length > MAX_SUFFIX_LENGTH)
32
+ throw new RangeError("suffix exceeds 8192 code units");
33
+ if (value.includes("\0") || path.isAbsolute(value)) {
34
+ throw new TypeError("suffix must be a relative path without NUL bytes");
35
+ }
36
+ const windows = process.platform === "win32";
37
+ const segments = (windows ? value.replaceAll("/", "\\") : value).split(path.sep);
38
+ if (segments.length > MAX_SUFFIX_DEPTH)
39
+ throw new RangeError("suffix exceeds 32 components");
40
+ if (segments.some(segment => !segment || segment === "." || segment === ".." ||
41
+ (windows && (segment.includes(":") || /^[ .]+$/u.test(segment) ||
42
+ isWindowsReservedDeviceName(segment))))) {
43
+ throw new TypeError("suffix must contain ordinary relative path components");
44
+ }
45
+ return segments;
46
+ }
47
+ function areAsciiCaseVariants(left, right) {
48
+ const fold = (value) => value.replace(/[A-Z]/gu, letter => String.fromCharCode(letter.charCodeAt(0) + 0x20));
49
+ return fold(left) === fold(right);
50
+ }
51
+ function forbiddenNames(leftNfc, rightNfc) {
52
+ const lower = new Set([leftNfc.toLowerCase(), rightNfc.toLowerCase()]);
53
+ const upper = new Set([leftNfc.toUpperCase(), rightNfc.toUpperCase()]);
54
+ // These conservative exclusions never classify filesystem aliases.
55
+ return candidate => {
56
+ const normalized = candidate.normalize("NFC");
57
+ return lower.has(normalized.toLowerCase()) || upper.has(normalized.toUpperCase());
58
+ };
59
+ }
60
+ function* normalizationProbePairs(left, right, forbidden, availableNameLength) {
61
+ const seen = new Set();
62
+ const replaceAscii = (value, replacements) => value.replace(/[A-Za-z]/gu, character => {
63
+ const lower = character.toLowerCase();
64
+ const replacement = replacements.get(lower);
65
+ return replacement ? character === lower ? replacement : replacement.toUpperCase() : character;
66
+ });
67
+ const presentAscii = [...new Set(`${left}${right}`.toLowerCase().match(/[a-z]/gu) ?? [])];
68
+ const mutableAscii = presentAscii.filter(source => {
69
+ const replacements = new Map([[source, source === "z" ? "y" : "z"]]);
70
+ return areAsciiCaseVariants(replaceAscii(left, replacements).normalize("NFC"), replaceAscii(right, replacements).normalize("NFC"));
71
+ });
72
+ for (let attempt = 0; attempt < 24 && mutableAscii.length > 0; attempt++) {
73
+ const replacements = new Map(mutableAscii.map(source => [
74
+ source, String.fromCharCode("a".charCodeAt(0) + randomInt(26)),
75
+ ]));
76
+ const first = replaceAscii(left, replacements);
77
+ const second = replaceAscii(right, replacements);
78
+ if (first.length > availableNameLength || second.length > availableNameLength ||
79
+ !areAsciiCaseVariants(first.normalize("NFC"), second.normalize("NFC")) ||
80
+ isWindowsReservedDeviceName(first) || isWindowsReservedDeviceName(second) ||
81
+ forbidden(first) || forbidden(second))
82
+ continue;
83
+ const key = `${first}\0${second}`;
84
+ if (!seen.has(key)) {
85
+ seen.add(key);
86
+ yield [first, second];
87
+ }
88
+ }
89
+ }
90
+ function createPrivateProbeName(nameLength) {
91
+ let name = "";
92
+ for (let index = 0; index < nameLength; index++) {
93
+ const alphabet = index === 0 ? PROBE_FIRST_ALPHABET : PROBE_ALPHABET;
94
+ name += alphabet[randomInt(alphabet.length)];
95
+ }
96
+ return name;
97
+ }
98
+ function* asciiCaseProbePairs(nameLength, forbidden) {
99
+ let count = 0;
100
+ for (let attempt = 0; attempt < 96 && count < 24; attempt++) {
101
+ const first = createPrivateProbeName(nameLength);
102
+ const second = `${first[0].toUpperCase()}${first.slice(1)}`;
103
+ if (!forbidden(first) && !forbidden(second)) {
104
+ count++;
105
+ yield [first, second];
106
+ }
107
+ }
108
+ }
109
+ function* privateProbeNames(nameLength, forbidden) {
110
+ let count = 0;
111
+ for (let attempt = 0; attempt < 96 && count < 24; attempt++) {
112
+ const name = createPrivateProbeName(nameLength);
113
+ if (!forbidden(name)) {
114
+ count++;
115
+ yield name;
116
+ }
117
+ }
118
+ }
119
+ function* prependPair(first, remaining) {
120
+ yield first;
121
+ yield* remaining;
122
+ }
123
+ class ProbeDirectories {
124
+ requestedDirectory;
125
+ root;
126
+ created = [];
127
+ cleanupComplete = true;
128
+ observations = 0;
129
+ mkdirAttempts = 0;
130
+ creations = 0;
131
+ constructor(requestedDirectory) {
132
+ this.requestedDirectory = requestedDirectory;
133
+ this.observe(1);
134
+ const canonical = realpathSync.native(pathForWindowsFilesystem(requestedDirectory));
135
+ assertMutationPath(canonical);
136
+ this.observe(2);
137
+ this.root = { path: canonical, identity: inspectDirectoryIdentitySync(canonical) };
138
+ this.assert(this.root);
139
+ }
140
+ reserveObservations(units) {
141
+ if (this.observations + units > MAX_FORWARD_OBSERVATIONS)
142
+ unavailable();
143
+ }
144
+ observe(units, cleanup = false) {
145
+ if (cleanup)
146
+ return;
147
+ this.reserveObservations(units);
148
+ this.observations += units;
149
+ }
150
+ assert(directory, cleanup = false) {
151
+ this.observe(1, cleanup);
152
+ if (realpathSync.native(pathForWindowsFilesystem(this.requestedDirectory)) !== this.root.path) {
153
+ throw new FsSafeError("path-mismatch", "probe directory changed");
154
+ }
155
+ for (let current = directory; current; current = current.parent) {
156
+ // Each strict identity helper can perform two observations on Windows.
157
+ this.observe(2, cleanup);
158
+ assertDirectoryIdentitySync(current.path, current.identity);
159
+ }
160
+ }
161
+ create(parent, name) {
162
+ if (this.mkdirAttempts >= MAX_MKDIR_ATTEMPTS || this.creations >= MAX_CREATED_DIRECTORIES)
163
+ unavailable();
164
+ const probePath = path.join(parent.path, name);
165
+ assertMutationPath(probePath);
166
+ this.assert(parent);
167
+ // Exhaustion must not itself create an entry whose first identity cannot be read.
168
+ this.reserveObservations(2);
169
+ this.mkdirAttempts++;
170
+ try {
171
+ fs.mkdirSync(probePath);
172
+ }
173
+ catch (error) {
174
+ if (hasNodeErrorCode(error, "EEXIST"))
175
+ return undefined;
176
+ throw error;
177
+ }
178
+ this.creations++;
179
+ this.observe(2);
180
+ // A failed initial observation can still leave an entry: mkdir returns no descriptor.
181
+ const created = { path: probePath, identity: inspectDirectoryIdentitySync(probePath), parent };
182
+ this.created.push(created);
183
+ this.assert(created);
184
+ return created;
185
+ }
186
+ remove(created, cleanup = false) {
187
+ try {
188
+ this.assert(created, cleanup);
189
+ assertMutationPath(created.path);
190
+ // Never recurse: unexpected children and replacements must remain.
191
+ fs.rmdirSync(created.path);
192
+ return true;
193
+ }
194
+ catch {
195
+ return false;
196
+ }
197
+ }
198
+ probe(parent, pairs) {
199
+ for (const [first, alternate] of pairs) {
200
+ const alternatePath = path.join(parent.path, alternate);
201
+ assertMutationPath(alternatePath);
202
+ const created = this.create(parent, first);
203
+ if (!created)
204
+ continue;
205
+ let alias;
206
+ this.observe(2);
207
+ try {
208
+ alias = inspectFileIdentitySync(() => fs.lstatSync(alternatePath, { bigint: true }));
209
+ }
210
+ catch (error) {
211
+ if (!hasNodeErrorCode(error, "ENOENT"))
212
+ throw error;
213
+ }
214
+ this.assert(created);
215
+ if (!alias)
216
+ return { aliases: false, directory: created };
217
+ if (alias.isDirectory() && !alias.isSymbolicLink() && sameFileIdentityForCleanup(created.identity, alias)) {
218
+ return { aliases: true, directory: created };
219
+ }
220
+ // A different alternate entry is a collision. Lost cleanup authority ends probing.
221
+ if (!this.remove(created)) {
222
+ this.cleanupComplete = false;
223
+ unavailable();
224
+ }
225
+ this.created.splice(this.created.indexOf(created), 1);
226
+ }
227
+ return undefined;
228
+ }
229
+ neutral(parent, nameLength, forbidden) {
230
+ for (const name of privateProbeNames(nameLength, forbidden)) {
231
+ const created = this.create(parent, name);
232
+ if (created)
233
+ return created;
234
+ }
235
+ return undefined;
236
+ }
237
+ cleanup() {
238
+ // Cleanup bypasses the forward budget; creation and depth caps bound its work.
239
+ for (let index = this.created.length - 1; index >= 0; index--) {
240
+ if (!this.remove(this.created[index], true))
241
+ this.cleanupComplete = false;
242
+ }
243
+ try {
244
+ this.assert(this.root, true);
245
+ }
246
+ catch {
247
+ this.cleanupComplete = false;
248
+ }
249
+ return this.cleanupComplete;
250
+ }
251
+ }
252
+ function observeSuffixes(getOwner, leftSegments, rightSegments, shouldProbeCaseVariants) {
253
+ let maxProbePathLength;
254
+ let probeParent;
255
+ for (let index = 0; index < leftSegments.length; index++) {
256
+ const left = leftSegments[index];
257
+ const right = rightSegments[index];
258
+ const normalizedLeft = left.normalize("NFC");
259
+ const normalizedRight = right.normalize("NFC");
260
+ const asciiCaseVariants = areAsciiCaseVariants(normalizedLeft, normalizedRight);
261
+ if (normalizedLeft !== normalizedRight && !asciiCaseVariants &&
262
+ !shouldProbeCaseVariants(normalizedLeft, normalizedRight))
263
+ return false;
264
+ const needsNormalization = left !== normalizedLeft || right !== normalizedRight;
265
+ if (normalizedLeft === normalizedRight && !needsNormalization && index === leftSegments.length - 1)
266
+ continue;
267
+ const owner = getOwner();
268
+ probeParent ??= owner.root;
269
+ maxProbePathLength ??= Math.max(path.join(owner.root.path, leftSegments.join(path.sep)).length, path.join(owner.root.path, rightSegments.join(path.sep)).length);
270
+ const availableNameLength = maxProbePathLength - probeParent.path.length -
271
+ (probeParent.path.endsWith(path.sep) ? 0 : 1);
272
+ const nameLength = Math.max(1, Math.min(PROBE_NAME_LENGTH, left.length, right.length));
273
+ const forbidden = forbiddenNames(normalizedLeft, normalizedRight);
274
+ let next;
275
+ if (normalizedLeft !== normalizedRight) {
276
+ let caseParent = probeParent;
277
+ let pairs;
278
+ if (asciiCaseVariants) {
279
+ pairs = asciiCaseProbePairs(nameLength, forbidden);
280
+ }
281
+ else {
282
+ const neutral = owner.neutral(probeParent, nameLength, forbidden);
283
+ if (!neutral)
284
+ return undefined;
285
+ caseParent = neutral;
286
+ pairs = [[left, right]];
287
+ }
288
+ const observed = owner.probe(caseParent, pairs);
289
+ if (!observed)
290
+ return undefined;
291
+ if (!observed.aliases)
292
+ return false;
293
+ next = observed.directory;
294
+ }
295
+ if (needsNormalization) {
296
+ const generated = normalizationProbePairs(left, right, forbidden, availableNameLength);
297
+ const first = generated.next();
298
+ let pairs;
299
+ let normalizationParent = probeParent;
300
+ // Fallback only when no generated pair exists, not when generated names collide.
301
+ if (first.done) {
302
+ const neutral = owner.neutral(probeParent, nameLength, forbidden);
303
+ if (!neutral)
304
+ return undefined;
305
+ normalizationParent = neutral;
306
+ pairs = [[left, right]];
307
+ }
308
+ else {
309
+ pairs = prependPair(first.value, generated);
310
+ }
311
+ const observed = owner.probe(normalizationParent, pairs);
312
+ if (!observed)
313
+ return undefined;
314
+ if (!observed.aliases)
315
+ return false;
316
+ next ??= observed.directory;
317
+ }
318
+ if (index < leftSegments.length - 1) {
319
+ next ??= owner.neutral(probeParent, nameLength, forbidden);
320
+ if (!next)
321
+ return undefined;
322
+ probeParent = next;
323
+ }
324
+ }
325
+ return true;
326
+ }
327
+ /** Observe bounded missing suffix aliases; the caller owns caching and ambiguity policy. */
328
+ export function probePathSuffixAliasesSync(options) {
329
+ const requestedDirectory = options.directory;
330
+ if (typeof requestedDirectory !== "string")
331
+ throw new TypeError("directory must be a string");
332
+ if (requestedDirectory.length > MAX_PATH_LENGTH)
333
+ throw new RangeError("directory exceeds 32768 code units");
334
+ if (requestedDirectory.includes("\0"))
335
+ throw new TypeError("directory must be a path without NUL bytes");
336
+ // Preserve one-argument Windows drive-relative resolution before reentrant option getters.
337
+ const directory = resolvePathPreservingWindowsRoot(requestedDirectory);
338
+ if (directory.length > MAX_PATH_LENGTH)
339
+ throw new RangeError("resolved directory exceeds 32768 code units");
340
+ const leftInput = options.left;
341
+ const rightInput = options.right;
342
+ const predicate = options.shouldProbeCaseVariants;
343
+ const left = suffixSegments(leftInput);
344
+ const right = suffixSegments(rightInput);
345
+ if (left.length !== right.length)
346
+ throw new TypeError("suffixes must have the same component count");
347
+ if (predicate !== undefined && typeof predicate !== "function") {
348
+ throw new TypeError("shouldProbeCaseVariants must be a function");
349
+ }
350
+ if (leftInput === rightInput)
351
+ return true;
352
+ let callbackFailure;
353
+ const shouldProbe = (first, second) => {
354
+ if (!predicate)
355
+ return true;
356
+ try {
357
+ const result = predicate(first, second);
358
+ if (typeof result !== "boolean") {
359
+ void Promise.resolve(result).catch(() => undefined);
360
+ throw new TypeError("shouldProbeCaseVariants must return a boolean synchronously");
361
+ }
362
+ return result;
363
+ }
364
+ catch (error) {
365
+ callbackFailure = { error };
366
+ throw error;
367
+ }
368
+ };
369
+ let owner;
370
+ let observed;
371
+ let cleaned = true;
372
+ try {
373
+ observed = observeSuffixes(() => owner ??= new ProbeDirectories(directory), left, right, shouldProbe);
374
+ owner?.assert(owner.root);
375
+ }
376
+ catch {
377
+ observed = undefined;
378
+ if (callbackFailure)
379
+ throw callbackFailure.error;
380
+ }
381
+ finally {
382
+ if (owner)
383
+ cleaned = owner.cleanup();
384
+ }
385
+ return cleaned ? observed : undefined;
386
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAOzB,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,yBAAyB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,GAChC,MAAM,kBAAkB,CAAC;AAM1B,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWvE;AAWD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAI1E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAA6B,GAAG,IAAI,CAIjG;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE3D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE1D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CA0ClE;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAExE;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAa/F;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAChE,OAAO,CAUT;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,IAAI,CAMhE;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAOrF"}
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAczB,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,yBAAyB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,GAChC,MAAM,kBAAkB,CAAC;AAM1B,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWvE;AAaD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAI1E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAA6B,GAAG,IAAI,CAIjG;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE3D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE1D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CA0ClE;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAExE;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAa/F;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAChE,OAAO,CAsBT;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,IAAI,CAMhE;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CA+BpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAWrF"}
package/dist/path.js CHANGED
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { FsSafeError } from "./errors.js";
4
4
  import { realpathSync } from "./realpath.js";
5
5
  import { isDriveRelativePath } from "./safe-path-segment.js";
6
+ import { assertNoWindowsPathAlias, hasWindowsPathAlias, pathForWindowsFilesystem, resolvePathFromBasePreservingWindowsRoot, resolvePathPreservingWindowsRoot, } from "./windows-path-alias.js";
6
7
  export { assertNoUnsafeDeviceReadPath, isUnsafeDeviceReadPath, matchUnsafeDeviceReadPath, } from "./device-path.js";
7
8
  const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
8
9
  const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
@@ -25,7 +26,7 @@ function resolveWindowsPathForComparison(input) {
25
26
  // retain Node's additional normalization rules before comparison.
26
27
  return resolved[1] === ":" && path.win32.isAbsolute(resolved)
27
28
  ? resolved.toLowerCase()
28
- : normalizeWindowsPathForComparison(resolved);
29
+ : normalizeWindowsPathForComparison(resolved.length === 6 ? resolvePathPreservingWindowsRoot(input) : resolved);
29
30
  }
30
31
  export function isNodeError(value) {
31
32
  return Boolean(value && typeof value === "object" && "code" in value);
@@ -95,7 +96,7 @@ export function safeRealpathSync(targetPath, cache) {
95
96
  return cached;
96
97
  }
97
98
  try {
98
- const resolved = realpathSync(targetPath);
99
+ const resolved = realpathSync(pathForWindowsFilesystem(targetPath));
99
100
  cache?.set(targetPath, resolved);
100
101
  cache?.set(resolved, resolved);
101
102
  return resolved;
@@ -105,11 +106,19 @@ export function safeRealpathSync(targetPath, cache) {
105
106
  }
106
107
  }
107
108
  export function isPathInsideWithRealpath(basePath, candidatePath, opts) {
109
+ if (hasWindowsPathAlias(basePath, "filesystem") ||
110
+ hasWindowsPathAlias(candidatePath, "filesystem")) {
111
+ return false;
112
+ }
108
113
  if (!isPathInside(basePath, candidatePath)) {
109
114
  return false;
110
115
  }
111
116
  const baseReal = safeRealpathSync(basePath, opts?.cache);
112
117
  const candidateReal = safeRealpathSync(candidatePath, opts?.cache);
118
+ if ((baseReal !== null && hasWindowsPathAlias(baseReal, "filesystem")) ||
119
+ (candidateReal !== null && hasWindowsPathAlias(candidateReal, "filesystem"))) {
120
+ return false;
121
+ }
113
122
  if (!baseReal || !candidateReal) {
114
123
  return opts?.requireRealpath === false;
115
124
  }
@@ -117,7 +126,7 @@ export function isPathInsideWithRealpath(basePath, candidatePath, opts) {
117
126
  }
118
127
  export function safeStatSync(targetPath) {
119
128
  try {
120
- return fs.statSync(targetPath);
129
+ return fs.statSync(pathForWindowsFilesystem(targetPath));
121
130
  }
122
131
  catch {
123
132
  return null;
@@ -145,11 +154,13 @@ export function splitSafeRelativePath(relativePath) {
145
154
  throw new FsSafeError("invalid-path", "relative path must not contain a drive letter");
146
155
  }
147
156
  }
157
+ assertNoWindowsPathAlias(relativePath, "relative", "relative path uses a Windows filesystem namespace alias");
148
158
  return segments;
149
159
  }
150
160
  export function resolveSafeRelativePath(rootDir, relativePath) {
151
- const root = path.resolve(rootDir);
152
- const target = path.resolve(root, ...splitSafeRelativePath(relativePath));
161
+ assertNoWindowsPathAlias(rootDir, "filesystem", "root dir uses a Windows filesystem namespace alias");
162
+ const root = resolvePathPreservingWindowsRoot(rootDir);
163
+ const target = resolvePathFromBasePreservingWindowsRoot(root, ...splitSafeRelativePath(relativePath));
153
164
  if (!isPathInside(root, target)) {
154
165
  throw new FsSafeError("outside-workspace", "relative path escapes root");
155
166
  }
@@ -1 +1 @@
1
- {"version":3,"file":"permissions-windows.d.ts","sourceRoot":"","sources":["../src/permissions-windows.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions-windows.d.ts","sourceRoot":"","sources":["../src/permissions-windows.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { safeStat } from "./permissions.js";
5
5
  import { normalizeLowercaseStringOrEmpty } from "./string-coerce.js";
6
6
  import { resolveWindowsSystemCommand } from "./windows-command.js";
7
7
  import { inspectWindowsOwner } from "./windows-owner.js";
8
+ import { hasWindowsPathAlias } from "./windows-path-alias.js";
8
9
  const INHERIT_FLAGS = new Set(["I", "OI", "CI", "IO", "NP"]);
9
10
  const WORLD_PRINCIPALS = new Set(["everyone", "users", "builtin\\users", "authenticated users", "nt authority\\authenticated users", "anonymous logon", "nt authority\\anonymous logon", "guests", "builtin\\guests", "interactive", "nt authority\\interactive", "network", "nt authority\\network", "local"]);
10
11
  const TRUSTED_BASE = new Set([
@@ -69,9 +70,6 @@ function inspectWindowsPermissionsNative(params) {
69
70
  }
70
71
  }
71
72
  export async function inspectWindowsPermissions(params) {
72
- const native = inspectWindowsPermissionsNative(params);
73
- if (native)
74
- return native;
75
73
  const unverified = {
76
74
  ok: true,
77
75
  isSymlink: params.stat.isSymlink,
@@ -84,6 +82,15 @@ export async function inspectWindowsPermissions(params) {
84
82
  worldReadable: false,
85
83
  groupReadable: false,
86
84
  };
85
+ if (hasWindowsPathAlias(params.targetPath, "filesystem", "win32")) {
86
+ return {
87
+ ...unverified,
88
+ error: "Path uses a Windows filesystem namespace alias",
89
+ };
90
+ }
91
+ const native = inspectWindowsPermissionsNative(params);
92
+ if (native)
93
+ return native;
87
94
  const owner = await inspectWindowsOwner({
88
95
  targetPath: params.targetPath,
89
96
  env: params.opts?.env,
@@ -270,6 +277,10 @@ export async function inspectWindowsAcl(targetPath, opts) {
270
277
  const error = new Error("Windows ACL principal SID translation failed");
271
278
  return summarizeWindowsOwnerAcl({ error: String(error), errorCause: error });
272
279
  }
280
+ if (hasWindowsPathAlias(targetPath, "filesystem", "win32")) {
281
+ const error = new Error("Path uses a Windows filesystem namespace alias");
282
+ return summarizeWindowsOwnerAcl({ error: String(error), errorCause: error });
283
+ }
273
284
  let owner;
274
285
  if (process.platform === "win32" && opts?.env === undefined && opts?.exec === undefined) {
275
286
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}