@openclaw/fs-safe 0.1.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 (260) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +390 -0
  4. package/SECURITY.md +12 -0
  5. package/dist/absolute-path.d.ts +19 -0
  6. package/dist/absolute-path.d.ts.map +1 -0
  7. package/dist/absolute-path.js +98 -0
  8. package/dist/advanced.d.ts +22 -0
  9. package/dist/advanced.d.ts.map +1 -0
  10. package/dist/advanced.js +24 -0
  11. package/dist/archive-entry.d.ts +13 -0
  12. package/dist/archive-entry.d.ts.map +1 -0
  13. package/dist/archive-entry.js +47 -0
  14. package/dist/archive-kind.d.ts +8 -0
  15. package/dist/archive-kind.d.ts.map +1 -0
  16. package/dist/archive-kind.js +58 -0
  17. package/dist/archive-limits.d.ts +40 -0
  18. package/dist/archive-limits.d.ts.map +1 -0
  19. package/dist/archive-limits.js +92 -0
  20. package/dist/archive-staging.d.ts +26 -0
  21. package/dist/archive-staging.d.ts.map +1 -0
  22. package/dist/archive-staging.js +171 -0
  23. package/dist/archive-tar.d.ts +14 -0
  24. package/dist/archive-tar.d.ts.map +1 -0
  25. package/dist/archive-tar.js +52 -0
  26. package/dist/archive-utils.d.ts +3 -0
  27. package/dist/archive-utils.d.ts.map +1 -0
  28. package/dist/archive-utils.js +26 -0
  29. package/dist/archive-zip-preflight.d.ts +7 -0
  30. package/dist/archive-zip-preflight.d.ts.map +1 -0
  31. package/dist/archive-zip-preflight.js +170 -0
  32. package/dist/archive.d.ts +24 -0
  33. package/dist/archive.d.ts.map +1 -0
  34. package/dist/archive.js +251 -0
  35. package/dist/async-lock.d.ts +2 -0
  36. package/dist/async-lock.d.ts.map +1 -0
  37. package/dist/async-lock.js +17 -0
  38. package/dist/atomic.d.ts +5 -0
  39. package/dist/atomic.d.ts.map +1 -0
  40. package/dist/atomic.js +4 -0
  41. package/dist/boundary-file-read.d.ts +44 -0
  42. package/dist/boundary-file-read.d.ts.map +1 -0
  43. package/dist/boundary-file-read.js +129 -0
  44. package/dist/boundary-path.d.ts +39 -0
  45. package/dist/boundary-path.d.ts.map +1 -0
  46. package/dist/boundary-path.js +598 -0
  47. package/dist/config.d.ts +2 -0
  48. package/dist/config.d.ts.map +1 -0
  49. package/dist/config.js +1 -0
  50. package/dist/errors.d.ts +11 -0
  51. package/dist/errors.d.ts.map +1 -0
  52. package/dist/errors.js +20 -0
  53. package/dist/file-identity.d.ts +6 -0
  54. package/dist/file-identity.d.ts.map +1 -0
  55. package/dist/file-identity.js +14 -0
  56. package/dist/file-lock.d.ts +20 -0
  57. package/dist/file-lock.d.ts.map +1 -0
  58. package/dist/file-lock.js +34 -0
  59. package/dist/file-store.d.ts +66 -0
  60. package/dist/file-store.d.ts.map +1 -0
  61. package/dist/file-store.js +436 -0
  62. package/dist/file-url.d.ts +2 -0
  63. package/dist/file-url.d.ts.map +1 -0
  64. package/dist/file-url.js +1 -0
  65. package/dist/filename.d.ts +2 -0
  66. package/dist/filename.d.ts.map +1 -0
  67. package/dist/filename.js +25 -0
  68. package/dist/fs-pinned-path-helper.d.ts +7 -0
  69. package/dist/fs-pinned-path-helper.d.ts.map +1 -0
  70. package/dist/fs-pinned-path-helper.js +182 -0
  71. package/dist/fs-pinned-write-helper.d.ts +21 -0
  72. package/dist/fs-pinned-write-helper.d.ts.map +1 -0
  73. package/dist/fs-pinned-write-helper.js +263 -0
  74. package/dist/fs.d.ts +13 -0
  75. package/dist/fs.d.ts.map +1 -0
  76. package/dist/fs.js +30 -0
  77. package/dist/hardlink-guards.d.ts +7 -0
  78. package/dist/hardlink-guards.d.ts.map +1 -0
  79. package/dist/hardlink-guards.js +30 -0
  80. package/dist/home-dir.d.ts +22 -0
  81. package/dist/home-dir.d.ts.map +1 -0
  82. package/dist/home-dir.js +107 -0
  83. package/dist/index.d.ts +4 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +3 -0
  86. package/dist/install-path.d.ts +20 -0
  87. package/dist/install-path.d.ts.map +1 -0
  88. package/dist/install-path.js +94 -0
  89. package/dist/install-safe-path.d.ts +20 -0
  90. package/dist/install-safe-path.d.ts.map +1 -0
  91. package/dist/install-safe-path.js +94 -0
  92. package/dist/json-document-store.d.ts +30 -0
  93. package/dist/json-document-store.d.ts.map +1 -0
  94. package/dist/json-document-store.js +68 -0
  95. package/dist/json-file.d.ts +3 -0
  96. package/dist/json-file.d.ts.map +1 -0
  97. package/dist/json-file.js +123 -0
  98. package/dist/json-files.d.ts +20 -0
  99. package/dist/json-files.d.ts.map +1 -0
  100. package/dist/json-files.js +153 -0
  101. package/dist/json-store.d.ts +9 -0
  102. package/dist/json-store.d.ts.map +1 -0
  103. package/dist/json-store.js +12 -0
  104. package/dist/json.d.ts +17 -0
  105. package/dist/json.d.ts.map +1 -0
  106. package/dist/json.js +198 -0
  107. package/dist/local-file-access.d.ts +8 -0
  108. package/dist/local-file-access.d.ts.map +1 -0
  109. package/dist/local-file-access.js +73 -0
  110. package/dist/local-roots.d.ts +26 -0
  111. package/dist/local-roots.d.ts.map +1 -0
  112. package/dist/local-roots.js +150 -0
  113. package/dist/mode.d.ts +2 -0
  114. package/dist/mode.d.ts.map +1 -0
  115. package/dist/mode.js +3 -0
  116. package/dist/move-path.d.ts +6 -0
  117. package/dist/move-path.d.ts.map +1 -0
  118. package/dist/move-path.js +18 -0
  119. package/dist/path-alias-guards.d.ts +19 -0
  120. package/dist/path-alias-guards.d.ts.map +1 -0
  121. package/dist/path-alias-guards.js +21 -0
  122. package/dist/path-guards.d.ts +7 -0
  123. package/dist/path-guards.d.ts.map +1 -0
  124. package/dist/path-guards.js +49 -0
  125. package/dist/path-policy.d.ts +25 -0
  126. package/dist/path-policy.d.ts.map +1 -0
  127. package/dist/path-policy.js +50 -0
  128. package/dist/path-safety.d.ts +12 -0
  129. package/dist/path-safety.d.ts.map +1 -0
  130. package/dist/path-safety.js +50 -0
  131. package/dist/path-scope.d.ts +2 -0
  132. package/dist/path-scope.d.ts.map +1 -0
  133. package/dist/path-scope.js +1 -0
  134. package/dist/path.d.ts +18 -0
  135. package/dist/path.d.ts.map +1 -0
  136. package/dist/path.js +123 -0
  137. package/dist/permissions-public.d.ts +2 -0
  138. package/dist/permissions-public.d.ts.map +1 -0
  139. package/dist/permissions-public.js +1 -0
  140. package/dist/permissions.d.ts +86 -0
  141. package/dist/permissions.d.ts.map +1 -0
  142. package/dist/permissions.js +435 -0
  143. package/dist/pinned-helper.d.ts +9 -0
  144. package/dist/pinned-helper.d.ts.map +1 -0
  145. package/dist/pinned-helper.js +19 -0
  146. package/dist/pinned-open.d.ts +24 -0
  147. package/dist/pinned-open.d.ts.map +1 -0
  148. package/dist/pinned-open.js +71 -0
  149. package/dist/pinned-path.d.ts +7 -0
  150. package/dist/pinned-path.d.ts.map +1 -0
  151. package/dist/pinned-path.js +21 -0
  152. package/dist/pinned-python-config.d.ts +9 -0
  153. package/dist/pinned-python-config.d.ts.map +1 -0
  154. package/dist/pinned-python-config.js +39 -0
  155. package/dist/pinned-python.d.ts +12 -0
  156. package/dist/pinned-python.d.ts.map +1 -0
  157. package/dist/pinned-python.js +599 -0
  158. package/dist/pinned-write.d.ts +33 -0
  159. package/dist/pinned-write.d.ts.map +1 -0
  160. package/dist/pinned-write.js +198 -0
  161. package/dist/private-file-store.d.ts +60 -0
  162. package/dist/private-file-store.d.ts.map +1 -0
  163. package/dist/private-file-store.js +233 -0
  164. package/dist/private-temp-workspace.d.ts +39 -0
  165. package/dist/private-temp-workspace.d.ts.map +1 -0
  166. package/dist/private-temp-workspace.js +185 -0
  167. package/dist/regular-file.d.ts +38 -0
  168. package/dist/regular-file.d.ts.map +1 -0
  169. package/dist/regular-file.js +239 -0
  170. package/dist/replace-directory.d.ts +7 -0
  171. package/dist/replace-directory.d.ts.map +1 -0
  172. package/dist/replace-directory.js +32 -0
  173. package/dist/replace-file.d.ts +41 -0
  174. package/dist/replace-file.d.ts.map +1 -0
  175. package/dist/replace-file.js +325 -0
  176. package/dist/root-file.d.ts +44 -0
  177. package/dist/root-file.d.ts.map +1 -0
  178. package/dist/root-file.js +129 -0
  179. package/dist/root-path.d.ts +39 -0
  180. package/dist/root-path.d.ts.map +1 -0
  181. package/dist/root-path.js +598 -0
  182. package/dist/root-paths.d.ts +92 -0
  183. package/dist/root-paths.d.ts.map +1 -0
  184. package/dist/root-paths.js +338 -0
  185. package/dist/root.d.ts +108 -0
  186. package/dist/root.d.ts.map +1 -0
  187. package/dist/root.js +1332 -0
  188. package/dist/safe-open-sync.d.ts +24 -0
  189. package/dist/safe-open-sync.d.ts.map +1 -0
  190. package/dist/safe-open-sync.js +71 -0
  191. package/dist/safe-root.d.ts +123 -0
  192. package/dist/safe-root.d.ts.map +1 -0
  193. package/dist/safe-root.js +1060 -0
  194. package/dist/secret-file.d.ts +17 -0
  195. package/dist/secret-file.d.ts.map +1 -0
  196. package/dist/secret-file.js +232 -0
  197. package/dist/secret.d.ts +2 -0
  198. package/dist/secret.d.ts.map +1 -0
  199. package/dist/secret.js +1 -0
  200. package/dist/secure-file.d.ts +32 -0
  201. package/dist/secure-file.d.ts.map +1 -0
  202. package/dist/secure-file.js +163 -0
  203. package/dist/secure-temp-dir.d.ts +27 -0
  204. package/dist/secure-temp-dir.d.ts.map +1 -0
  205. package/dist/secure-temp-dir.js +155 -0
  206. package/dist/secure-temp-workspace.d.ts +25 -0
  207. package/dist/secure-temp-workspace.d.ts.map +1 -0
  208. package/dist/secure-temp-workspace.js +136 -0
  209. package/dist/sibling-temp-file.d.ts +16 -0
  210. package/dist/sibling-temp-file.d.ts.map +1 -0
  211. package/dist/sibling-temp-file.js +73 -0
  212. package/dist/sibling-temp-write.d.ts +8 -0
  213. package/dist/sibling-temp-write.d.ts.map +1 -0
  214. package/dist/sibling-temp-write.js +40 -0
  215. package/dist/sibling-temp.d.ts +23 -0
  216. package/dist/sibling-temp.d.ts.map +1 -0
  217. package/dist/sibling-temp.js +119 -0
  218. package/dist/sidecar-lock.d.ts +50 -0
  219. package/dist/sidecar-lock.d.ts.map +1 -0
  220. package/dist/sidecar-lock.js +235 -0
  221. package/dist/store.d.ts +3 -0
  222. package/dist/store.d.ts.map +1 -0
  223. package/dist/store.js +2 -0
  224. package/dist/string-coerce.d.ts +14 -0
  225. package/dist/string-coerce.d.ts.map +1 -0
  226. package/dist/string-coerce.js +72 -0
  227. package/dist/symlink-parents.d.ts +12 -0
  228. package/dist/symlink-parents.d.ts.map +1 -0
  229. package/dist/symlink-parents.js +78 -0
  230. package/dist/temp-cleanup.d.ts +6 -0
  231. package/dist/temp-cleanup.d.ts.map +1 -0
  232. package/dist/temp-cleanup.js +42 -0
  233. package/dist/temp-target.d.ts +28 -0
  234. package/dist/temp-target.d.ts.map +1 -0
  235. package/dist/temp-target.js +84 -0
  236. package/dist/temp.d.ts +3 -0
  237. package/dist/temp.d.ts.map +1 -0
  238. package/dist/temp.js +2 -0
  239. package/dist/test-hooks.d.ts +9 -0
  240. package/dist/test-hooks.d.ts.map +1 -0
  241. package/dist/test-hooks.js +13 -0
  242. package/dist/text-atomic.d.ts +7 -0
  243. package/dist/text-atomic.d.ts.map +1 -0
  244. package/dist/text-atomic.js +13 -0
  245. package/dist/timing.d.ts +6 -0
  246. package/dist/timing.d.ts.map +1 -0
  247. package/dist/timing.js +24 -0
  248. package/dist/trash.d.ts +5 -0
  249. package/dist/trash.d.ts.map +1 -0
  250. package/dist/trash.js +127 -0
  251. package/dist/types.d.ts +23 -0
  252. package/dist/types.d.ts.map +1 -0
  253. package/dist/types.js +1 -0
  254. package/dist/walk.d.ts +26 -0
  255. package/dist/walk.d.ts.map +1 -0
  256. package/dist/walk.js +169 -0
  257. package/dist/write-queue.d.ts +2 -0
  258. package/dist/write-queue.d.ts.map +1 -0
  259. package/dist/write-queue.js +18 -0
  260. package/package.json +117 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"move-path.d.ts","sourceRoot":"","sources":["../src/move-path.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,+BAA+B,GAAG;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,IAAI,CAAC,CAef"}
@@ -0,0 +1,18 @@
1
+ import fs from "node:fs/promises";
2
+ export async function movePathWithCopyFallback(options) {
3
+ try {
4
+ await fs.rename(options.from, options.to);
5
+ return;
6
+ }
7
+ catch (error) {
8
+ if (error?.code !== "EXDEV") {
9
+ throw error;
10
+ }
11
+ }
12
+ await fs.cp(options.from, options.to, {
13
+ recursive: true,
14
+ force: true,
15
+ dereference: false,
16
+ });
17
+ await fs.rm(options.from, { recursive: true, force: true });
18
+ }
@@ -0,0 +1,19 @@
1
+ import { type RootPathAliasPolicy } from "./root-path.js";
2
+ export type PathAliasPolicy = RootPathAliasPolicy;
3
+ export declare const PATH_ALIAS_POLICIES: {
4
+ readonly strict: Readonly<{
5
+ allowFinalSymlinkForUnlink: false;
6
+ allowFinalHardlinkForUnlink: false;
7
+ }>;
8
+ readonly unlinkTarget: Readonly<{
9
+ allowFinalSymlinkForUnlink: true;
10
+ allowFinalHardlinkForUnlink: true;
11
+ }>;
12
+ };
13
+ export declare function assertNoPathAliasEscape(params: {
14
+ absolutePath: string;
15
+ rootPath: string;
16
+ boundaryLabel: string;
17
+ policy?: PathAliasPolicy;
18
+ }): Promise<void>;
19
+ //# sourceMappingURL=path-alias-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-alias-guards.d.ts","sourceRoot":"","sources":["../src/path-alias-guards.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAElD,eAAO,MAAM,mBAAmB;;;;;;;;;CAA2B,CAAC;AAE5D,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB"}
@@ -0,0 +1,21 @@
1
+ import { ROOT_PATH_ALIAS_POLICIES, resolveRootPath, } from "./root-path.js";
2
+ import { assertNoHardlinkedFinalPath } from "./hardlink-guards.js";
3
+ export const PATH_ALIAS_POLICIES = ROOT_PATH_ALIAS_POLICIES;
4
+ export async function assertNoPathAliasEscape(params) {
5
+ const resolved = await resolveRootPath({
6
+ absolutePath: params.absolutePath,
7
+ rootPath: params.rootPath,
8
+ boundaryLabel: params.boundaryLabel,
9
+ policy: params.policy,
10
+ });
11
+ const allowFinalSymlink = params.policy?.allowFinalSymlinkForUnlink === true;
12
+ if (allowFinalSymlink && resolved.kind === "symlink") {
13
+ return;
14
+ }
15
+ await assertNoHardlinkedFinalPath({
16
+ filePath: resolved.absolutePath,
17
+ root: resolved.rootPath,
18
+ boundaryLabel: params.boundaryLabel,
19
+ allowFinalHardlinkForUnlink: params.policy?.allowFinalHardlinkForUnlink,
20
+ });
21
+ }
@@ -0,0 +1,7 @@
1
+ export declare function normalizeWindowsPathForComparison(input: string): string;
2
+ export declare function isNodeError(value: unknown): value is NodeJS.ErrnoException;
3
+ export declare function hasNodeErrorCode(value: unknown, code: string): boolean;
4
+ export declare function isNotFoundPathError(value: unknown): boolean;
5
+ export declare function isSymlinkOpenError(value: unknown): boolean;
6
+ export declare function isPathInside(root: string, target: string): boolean;
7
+ //# sourceMappingURL=path-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-guards.d.ts","sourceRoot":"","sources":["../src/path-guards.ts"],"names":[],"mappings":"AAQA,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASvE;AAED,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,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,CA0BlE"}
@@ -0,0 +1,49 @@
1
+ import path from "node:path";
2
+ import { normalizeLowercaseStringOrEmpty } from "./string-coerce.js";
3
+ const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
4
+ const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
5
+ const PARENT_SEGMENT_PREFIX = /^\.\.(?:[\\/]|$)/u;
6
+ const POSIX_SEPARATOR_CHAR_CODE = 0x2f;
7
+ export function normalizeWindowsPathForComparison(input) {
8
+ let normalized = path.win32.normalize(input);
9
+ if (normalized.startsWith("\\\\?\\")) {
10
+ normalized = normalized.slice(4);
11
+ if (normalized.toUpperCase().startsWith("UNC\\")) {
12
+ normalized = `\\\\${normalized.slice(4)}`;
13
+ }
14
+ }
15
+ return normalizeLowercaseStringOrEmpty(normalized.replaceAll("/", "\\"));
16
+ }
17
+ export function isNodeError(value) {
18
+ return Boolean(value && typeof value === "object" && "code" in value);
19
+ }
20
+ export function hasNodeErrorCode(value, code) {
21
+ return isNodeError(value) && value.code === code;
22
+ }
23
+ export function isNotFoundPathError(value) {
24
+ return isNodeError(value) && typeof value.code === "string" && NOT_FOUND_CODES.has(value.code);
25
+ }
26
+ export function isSymlinkOpenError(value) {
27
+ return isNodeError(value) && typeof value.code === "string" && SYMLINK_OPEN_CODES.has(value.code);
28
+ }
29
+ export function isPathInside(root, target) {
30
+ if (process.platform === "win32") {
31
+ const rootForCompare = normalizeWindowsPathForComparison(path.win32.resolve(root));
32
+ const targetForCompare = normalizeWindowsPathForComparison(path.win32.resolve(target));
33
+ const relative = path.win32.relative(rootForCompare, targetForCompare);
34
+ return (relative === "" || (!PARENT_SEGMENT_PREFIX.test(relative) && !path.win32.isAbsolute(relative)));
35
+ }
36
+ if (root.length > 0 &&
37
+ root.charCodeAt(0) === POSIX_SEPARATOR_CHAR_CODE &&
38
+ target.length >= root.length &&
39
+ target.charCodeAt(0) === POSIX_SEPARATOR_CHAR_CODE &&
40
+ !target.includes("/..") &&
41
+ (target === root ||
42
+ (target.startsWith(root) && target.charCodeAt(root.length) === POSIX_SEPARATOR_CHAR_CODE))) {
43
+ return true;
44
+ }
45
+ const resolvedRoot = path.resolve(root);
46
+ const resolvedTarget = path.resolve(target);
47
+ const relative = path.relative(resolvedRoot, resolvedTarget);
48
+ return relative === "" || (!PARENT_SEGMENT_PREFIX.test(relative) && !path.isAbsolute(relative));
49
+ }
@@ -0,0 +1,25 @@
1
+ import { type RootPathAliasPolicy } from "./root-path.js";
2
+ export type PathAliasPolicy = RootPathAliasPolicy;
3
+ export declare const PATH_ALIAS_POLICIES: {
4
+ readonly strict: Readonly<{
5
+ allowFinalSymlinkForUnlink: false;
6
+ allowFinalHardlinkForUnlink: false;
7
+ }>;
8
+ readonly unlinkTarget: Readonly<{
9
+ allowFinalSymlinkForUnlink: true;
10
+ allowFinalHardlinkForUnlink: true;
11
+ }>;
12
+ };
13
+ export declare function assertNoPathAliasEscape(params: {
14
+ absolutePath: string;
15
+ rootPath: string;
16
+ boundaryLabel: string;
17
+ policy?: PathAliasPolicy;
18
+ }): Promise<void>;
19
+ export declare function assertNoHardlinkedFinalPath(params: {
20
+ filePath: string;
21
+ root: string;
22
+ boundaryLabel: string;
23
+ allowFinalHardlinkForUnlink?: boolean;
24
+ }): Promise<void>;
25
+ //# sourceMappingURL=path-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-policy.d.ts","sourceRoot":"","sources":["../src/path-policy.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAElD,eAAO,MAAM,mBAAmB;;;;;;;;;CAA2B,CAAC;AAE5D,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED,wBAAsB,2BAA2B,CAAC,MAAM,EAAE;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBhB"}
@@ -0,0 +1,50 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import { ROOT_PATH_ALIAS_POLICIES, resolveRootPath, } from "./root-path.js";
4
+ import { isNotFoundPathError } from "./path.js";
5
+ export const PATH_ALIAS_POLICIES = ROOT_PATH_ALIAS_POLICIES;
6
+ export async function assertNoPathAliasEscape(params) {
7
+ const resolved = await resolveRootPath({
8
+ absolutePath: params.absolutePath,
9
+ rootPath: params.rootPath,
10
+ boundaryLabel: params.boundaryLabel,
11
+ policy: params.policy,
12
+ });
13
+ const allowFinalSymlink = params.policy?.allowFinalSymlinkForUnlink === true;
14
+ if (allowFinalSymlink && resolved.kind === "symlink") {
15
+ return;
16
+ }
17
+ await assertNoHardlinkedFinalPath({
18
+ filePath: resolved.absolutePath,
19
+ root: resolved.rootPath,
20
+ boundaryLabel: params.boundaryLabel,
21
+ allowFinalHardlinkForUnlink: params.policy?.allowFinalHardlinkForUnlink,
22
+ });
23
+ }
24
+ export async function assertNoHardlinkedFinalPath(params) {
25
+ if (params.allowFinalHardlinkForUnlink) {
26
+ return;
27
+ }
28
+ let stat;
29
+ try {
30
+ stat = await fs.stat(params.filePath);
31
+ }
32
+ catch (err) {
33
+ if (isNotFoundPathError(err)) {
34
+ return;
35
+ }
36
+ throw err;
37
+ }
38
+ if (!stat.isFile()) {
39
+ return;
40
+ }
41
+ if (stat.nlink > 1) {
42
+ throw new Error(`Hardlinked path is not allowed under ${params.boundaryLabel} (${shortPath(params.root)}): ${shortPath(params.filePath)}`);
43
+ }
44
+ }
45
+ function shortPath(value) {
46
+ if (value.startsWith(os.homedir())) {
47
+ return `~${value.slice(os.homedir().length)}`;
48
+ }
49
+ return value;
50
+ }
@@ -0,0 +1,12 @@
1
+ import fs from "node:fs";
2
+ export declare function resolveSafeBaseDir(rootDir: string): string;
3
+ export declare function isWithinDir(rootDir: string, targetPath: string): boolean;
4
+ export declare function isPathInside(baseDir: string, targetPath: string): boolean;
5
+ export declare function safeRealpathSync(targetPath: string, cache?: Map<string, string>): string | null;
6
+ export declare function isPathInsideWithRealpath(basePath: string, candidatePath: string, opts?: {
7
+ requireRealpath?: boolean;
8
+ cache?: Map<string, string>;
9
+ }): boolean;
10
+ export declare function safeStatSync(targetPath: string): fs.Stats | null;
11
+ export declare function formatPosixMode(mode: number): string;
12
+ //# sourceMappingURL=path-safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-safety.d.ts","sourceRoot":"","sources":["../src/path-safety.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAIzB,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,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAEzE;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,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,50 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { isPathInside as isRootPathInside } from "./path-guards.js";
4
+ export function resolveSafeBaseDir(rootDir) {
5
+ const resolved = path.resolve(rootDir);
6
+ return resolved.endsWith(path.sep) ? resolved : `${resolved}${path.sep}`;
7
+ }
8
+ export function isWithinDir(rootDir, targetPath) {
9
+ return isRootPathInside(rootDir, targetPath);
10
+ }
11
+ export function isPathInside(baseDir, targetPath) {
12
+ return isRootPathInside(baseDir, targetPath);
13
+ }
14
+ export function safeRealpathSync(targetPath, cache) {
15
+ const cached = cache?.get(targetPath);
16
+ if (cached) {
17
+ return cached;
18
+ }
19
+ try {
20
+ const resolved = fs.realpathSync(targetPath);
21
+ cache?.set(targetPath, resolved);
22
+ cache?.set(resolved, resolved);
23
+ return resolved;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ export function isPathInsideWithRealpath(basePath, candidatePath, opts) {
30
+ if (!isPathInside(basePath, candidatePath)) {
31
+ return false;
32
+ }
33
+ const baseReal = safeRealpathSync(basePath, opts?.cache);
34
+ const candidateReal = safeRealpathSync(candidatePath, opts?.cache);
35
+ if (!baseReal || !candidateReal) {
36
+ return opts?.requireRealpath === false;
37
+ }
38
+ return isPathInside(baseReal, candidateReal);
39
+ }
40
+ export function safeStatSync(targetPath) {
41
+ try {
42
+ return fs.statSync(targetPath);
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ export function formatPosixMode(mode) {
49
+ return (mode & 0o777).toString(8).padStart(3, "0");
50
+ }
@@ -0,0 +1,2 @@
1
+ export { pathScope, type PathScope, type PathScopeOptions, type PathScopeResolveOptions, } from "./root-paths.js";
2
+ //# sourceMappingURL=path-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-scope.d.ts","sourceRoot":"","sources":["../src/path-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1 @@
1
+ export { pathScope, } from "./root-paths.js";
package/dist/path.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import fs from "node:fs";
2
+ export declare function normalizeWindowsPathForComparison(input: string): string;
3
+ export declare function isNodeError(value: unknown): value is NodeJS.ErrnoException;
4
+ export declare function hasNodeErrorCode(value: unknown, code: string): boolean;
5
+ export declare function isNotFoundPathError(value: unknown): boolean;
6
+ export declare function isSymlinkOpenError(value: unknown): boolean;
7
+ export declare function isPathInside(root: string, target: string): boolean;
8
+ export declare function resolveSafeBaseDir(rootDir: string): string;
9
+ export declare function isWithinDir(rootDir: string, targetPath: string): boolean;
10
+ export declare function safeRealpathSync(targetPath: string, cache?: Map<string, string>): string | null;
11
+ export declare function isPathInsideWithRealpath(basePath: string, candidatePath: string, opts?: {
12
+ requireRealpath?: boolean;
13
+ cache?: Map<string, string>;
14
+ }): boolean;
15
+ export declare function safeStatSync(targetPath: string): fs.Stats | null;
16
+ export declare function splitSafeRelativePath(relativePath: string): string[];
17
+ export declare function resolveSafeRelativePath(rootDir: string, relativePath: string): string;
18
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAWzB,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASvE;AAED,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,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,CA0BlE;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,CAyBpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAOrF"}
package/dist/path.js ADDED
@@ -0,0 +1,123 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { FsSafeError } from "./errors.js";
4
+ import { normalizeLowercaseStringOrEmpty } from "./string-coerce.js";
5
+ const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
6
+ const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
7
+ const PARENT_SEGMENT_PREFIX = /^\.\.(?:[\\/]|$)/u;
8
+ const POSIX_SEPARATOR_CHAR_CODE = 0x2f;
9
+ export function normalizeWindowsPathForComparison(input) {
10
+ let normalized = path.win32.normalize(input);
11
+ if (normalized.startsWith("\\\\?\\")) {
12
+ normalized = normalized.slice(4);
13
+ if (normalized.toUpperCase().startsWith("UNC\\")) {
14
+ normalized = `\\\\${normalized.slice(4)}`;
15
+ }
16
+ }
17
+ return normalizeLowercaseStringOrEmpty(normalized.replaceAll("/", "\\"));
18
+ }
19
+ export function isNodeError(value) {
20
+ return Boolean(value && typeof value === "object" && "code" in value);
21
+ }
22
+ export function hasNodeErrorCode(value, code) {
23
+ return isNodeError(value) && value.code === code;
24
+ }
25
+ export function isNotFoundPathError(value) {
26
+ return isNodeError(value) && typeof value.code === "string" && NOT_FOUND_CODES.has(value.code);
27
+ }
28
+ export function isSymlinkOpenError(value) {
29
+ return isNodeError(value) && typeof value.code === "string" && SYMLINK_OPEN_CODES.has(value.code);
30
+ }
31
+ export function isPathInside(root, target) {
32
+ if (process.platform === "win32") {
33
+ const rootForCompare = normalizeWindowsPathForComparison(path.win32.resolve(root));
34
+ const targetForCompare = normalizeWindowsPathForComparison(path.win32.resolve(target));
35
+ const relative = path.win32.relative(rootForCompare, targetForCompare);
36
+ return (relative === "" || (!PARENT_SEGMENT_PREFIX.test(relative) && !path.win32.isAbsolute(relative)));
37
+ }
38
+ if (root.length > 0 &&
39
+ root.charCodeAt(0) === POSIX_SEPARATOR_CHAR_CODE &&
40
+ target.length >= root.length &&
41
+ target.charCodeAt(0) === POSIX_SEPARATOR_CHAR_CODE &&
42
+ !target.includes("/..") &&
43
+ (target === root ||
44
+ (target.startsWith(root) && target.charCodeAt(root.length) === POSIX_SEPARATOR_CHAR_CODE))) {
45
+ return true;
46
+ }
47
+ const resolvedRoot = path.resolve(root);
48
+ const resolvedTarget = path.resolve(target);
49
+ const relative = path.relative(resolvedRoot, resolvedTarget);
50
+ return relative === "" || (!PARENT_SEGMENT_PREFIX.test(relative) && !path.isAbsolute(relative));
51
+ }
52
+ export function resolveSafeBaseDir(rootDir) {
53
+ const resolved = path.resolve(rootDir);
54
+ return resolved.endsWith(path.sep) ? resolved : `${resolved}${path.sep}`;
55
+ }
56
+ export function isWithinDir(rootDir, targetPath) {
57
+ return isPathInside(rootDir, targetPath);
58
+ }
59
+ export function safeRealpathSync(targetPath, cache) {
60
+ const cached = cache?.get(targetPath);
61
+ if (cached) {
62
+ return cached;
63
+ }
64
+ try {
65
+ const resolved = fs.realpathSync(targetPath);
66
+ cache?.set(targetPath, resolved);
67
+ cache?.set(resolved, resolved);
68
+ return resolved;
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ export function isPathInsideWithRealpath(basePath, candidatePath, opts) {
75
+ if (!isPathInside(basePath, candidatePath)) {
76
+ return false;
77
+ }
78
+ const baseReal = safeRealpathSync(basePath, opts?.cache);
79
+ const candidateReal = safeRealpathSync(candidatePath, opts?.cache);
80
+ if (!baseReal || !candidateReal) {
81
+ return opts?.requireRealpath === false;
82
+ }
83
+ return isPathInside(baseReal, candidateReal);
84
+ }
85
+ export function safeStatSync(targetPath) {
86
+ try {
87
+ return fs.statSync(targetPath);
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ export function splitSafeRelativePath(relativePath) {
94
+ if (relativePath.length === 0 || relativePath === ".") {
95
+ return [];
96
+ }
97
+ if (relativePath.includes("\0")) {
98
+ throw new FsSafeError("invalid-path", "relative path contains a NUL byte");
99
+ }
100
+ if (relativePath.includes("\\")) {
101
+ throw new FsSafeError("invalid-path", "relative path must use forward slashes");
102
+ }
103
+ if (path.posix.isAbsolute(relativePath) ||
104
+ path.win32.isAbsolute(relativePath) ||
105
+ relativePath.startsWith("//")) {
106
+ throw new FsSafeError("invalid-path", "relative path must not be absolute");
107
+ }
108
+ const segments = relativePath.split("/").filter((segment) => segment.length > 0 && segment !== ".");
109
+ for (const segment of segments) {
110
+ if (segment === "..") {
111
+ throw new FsSafeError("invalid-path", "relative path must not contain '..'");
112
+ }
113
+ }
114
+ return segments;
115
+ }
116
+ export function resolveSafeRelativePath(rootDir, relativePath) {
117
+ const root = path.resolve(rootDir);
118
+ const target = path.resolve(root, ...splitSafeRelativePath(relativePath));
119
+ if (target !== root && !target.startsWith(root + path.sep)) {
120
+ throw new FsSafeError("outside-workspace", "relative path escapes root");
121
+ }
122
+ return target;
123
+ }
@@ -0,0 +1,2 @@
1
+ export { formatOctal, formatPermissionDetail, formatPermissionRemediation, inspectPathPermissions, isGroupReadable, isGroupWritable, isWorldReadable, isWorldWritable, modeBits, safeStat, type PermissionCheck, type PermissionCheckOptions, type SafeStatResult, } from "./permissions.js";
2
+ //# sourceMappingURL=permissions-public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-public.d.ts","sourceRoot":"","sources":["../src/permissions-public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,eAAe,EACf,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1 @@
1
+ export { formatOctal, formatPermissionDetail, formatPermissionRemediation, inspectPathPermissions, isGroupReadable, isGroupWritable, isWorldReadable, isWorldWritable, modeBits, safeStat, } from "./permissions.js";
@@ -0,0 +1,86 @@
1
+ export type PermissionExec = (command: string, args: string[]) => Promise<{
2
+ stdout: string;
3
+ stderr: string;
4
+ }>;
5
+ export type PermissionCheck = {
6
+ ok: boolean;
7
+ isSymlink: boolean;
8
+ isDir: boolean;
9
+ mode: number | null;
10
+ bits: number | null;
11
+ source: "posix" | "windows-acl" | "unknown";
12
+ worldWritable: boolean;
13
+ groupWritable: boolean;
14
+ worldReadable: boolean;
15
+ groupReadable: boolean;
16
+ aclSummary?: string;
17
+ error?: string;
18
+ };
19
+ export type PermissionCheckOptions = {
20
+ platform?: NodeJS.Platform;
21
+ env?: NodeJS.ProcessEnv;
22
+ exec?: PermissionExec;
23
+ };
24
+ export type SafeStatResult = {
25
+ ok: boolean;
26
+ isSymlink: boolean;
27
+ isDir: boolean;
28
+ mode: number | null;
29
+ uid: number | null;
30
+ gid: number | null;
31
+ error?: string;
32
+ };
33
+ export type WindowsAclEntry = {
34
+ principal: string;
35
+ rights: string[];
36
+ rawRights: string;
37
+ canRead: boolean;
38
+ canWrite: boolean;
39
+ };
40
+ export type WindowsAclSummary = {
41
+ ok: boolean;
42
+ entries: WindowsAclEntry[];
43
+ untrustedWorld: WindowsAclEntry[];
44
+ untrustedGroup: WindowsAclEntry[];
45
+ trusted: WindowsAclEntry[];
46
+ error?: string;
47
+ };
48
+ export type WindowsUserInfoProvider = () => {
49
+ username?: string | null;
50
+ };
51
+ export type IcaclsResetCommandOptions = {
52
+ isDir: boolean;
53
+ env?: NodeJS.ProcessEnv;
54
+ userInfo?: WindowsUserInfoProvider;
55
+ };
56
+ export declare function safeStat(targetPath: string): Promise<SafeStatResult>;
57
+ export declare function inspectPathPermissions(targetPath: string, opts?: PermissionCheckOptions): Promise<PermissionCheck>;
58
+ export declare function formatPermissionDetail(targetPath: string, perms: PermissionCheck): string;
59
+ export declare function formatPermissionRemediation(params: {
60
+ targetPath: string;
61
+ perms: PermissionCheck;
62
+ isDir: boolean;
63
+ posixMode: number;
64
+ env?: NodeJS.ProcessEnv;
65
+ }): string;
66
+ export declare function modeBits(mode: number | null): number | null;
67
+ export declare function formatOctal(bits: number | null): string;
68
+ export declare function isWorldWritable(bits: number | null): boolean;
69
+ export declare function isGroupWritable(bits: number | null): boolean;
70
+ export declare function isWorldReadable(bits: number | null): boolean;
71
+ export declare function isGroupReadable(bits: number | null): boolean;
72
+ export declare function resolveWindowsUserPrincipal(env?: NodeJS.ProcessEnv, userInfo?: WindowsUserInfoProvider): string | null;
73
+ export declare function parseIcaclsOutput(output: string, targetPath: string): WindowsAclEntry[];
74
+ export declare function summarizeWindowsAcl(entries: WindowsAclEntry[], env?: NodeJS.ProcessEnv): Pick<WindowsAclSummary, "trusted" | "untrustedWorld" | "untrustedGroup">;
75
+ export declare function inspectWindowsAcl(targetPath: string, opts?: {
76
+ env?: NodeJS.ProcessEnv;
77
+ exec?: PermissionExec;
78
+ }): Promise<WindowsAclSummary>;
79
+ export declare function formatWindowsAclSummary(summary: WindowsAclSummary): string;
80
+ export declare function formatIcaclsResetCommand(targetPath: string, opts: IcaclsResetCommandOptions): string;
81
+ export declare function createIcaclsResetCommand(targetPath: string, opts: IcaclsResetCommandOptions): {
82
+ command: string;
83
+ args: string[];
84
+ display: string;
85
+ } | null;
86
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}