@openclaw/fs-safe 0.5.1 → 0.5.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.
- package/CHANGELOG.md +66 -0
- package/README.md +18 -6
- package/dist/absolute-path.d.ts.map +1 -1
- package/dist/absolute-path.js +20 -12
- package/dist/archive-entry.d.ts +1 -0
- package/dist/archive-entry.d.ts.map +1 -1
- package/dist/archive-entry.js +25 -5
- package/dist/archive-input.d.ts +7 -0
- package/dist/archive-input.d.ts.map +1 -1
- package/dist/archive-input.js +11 -1
- package/dist/archive-limits.js +1 -1
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +6 -3
- package/dist/archive-policy.d.ts.map +1 -1
- package/dist/archive-policy.js +2 -1
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +30 -12
- package/dist/archive-staging.d.ts.map +1 -1
- package/dist/archive-staging.js +3 -2
- package/dist/archive-tar-meta.d.ts.map +1 -1
- package/dist/archive-tar-meta.js +7 -1
- package/dist/archive-tar.d.ts.map +1 -1
- package/dist/archive-tar.js +7 -4
- package/dist/archive-zip-entry.d.ts +1 -0
- package/dist/archive-zip-entry.d.ts.map +1 -1
- package/dist/archive-zip-integrity.d.ts +4 -0
- package/dist/archive-zip-integrity.d.ts.map +1 -0
- package/dist/archive-zip-integrity.js +44 -0
- package/dist/archive-zip-preflight.d.ts.map +1 -1
- package/dist/archive-zip-preflight.js +6 -1
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +5 -2
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +13 -2
- package/dist/deny-mutations.d.ts +1 -0
- package/dist/deny-mutations.d.ts.map +1 -1
- package/dist/deny-mutations.js +6 -39
- package/dist/device-path.d.ts +1 -0
- package/dist/device-path.d.ts.map +1 -1
- package/dist/device-path.js +6 -6
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-guard.js +5 -4
- package/dist/error-detail.d.ts +2 -0
- package/dist/error-detail.d.ts.map +1 -0
- package/dist/error-detail.js +4 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -0
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +4 -1
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +88 -35
- package/dist/file-store-boundary.d.ts +6 -0
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +20 -5
- package/dist/file-store-sync-write.d.ts +9 -0
- package/dist/file-store-sync-write.d.ts.map +1 -0
- package/dist/file-store-sync-write.js +97 -0
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +36 -128
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +27 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +5 -6
- package/dist/install-path.js +1 -1
- package/dist/json-document-store.d.ts.map +1 -1
- package/dist/json-document-store.js +19 -13
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +1 -3
- package/dist/local-file-access.d.ts +3 -2
- package/dist/local-file-access.d.ts.map +1 -1
- package/dist/local-file-access.js +12 -6
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +35 -30
- package/dist/move-path.d.ts.map +1 -1
- package/dist/move-path.js +51 -12
- package/dist/native/darwin-arm64/fs-safe-native.node +0 -0
- package/dist/native/darwin-x64/fs-safe-native.node +0 -0
- package/dist/native/linux-arm64-gnu/fs-safe-native.node +0 -0
- package/dist/native/linux-arm64-musl/fs-safe-native.node +0 -0
- package/dist/native/linux-x64-gnu/fs-safe-native.node +0 -0
- package/dist/native/linux-x64-musl/fs-safe-native.node +0 -0
- package/dist/native/win32-x64-msvc/fs-safe-native.node +0 -0
- package/dist/native-binding.d.ts +1 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +14 -1
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +44 -17
- package/dist/output-sibling.d.ts.map +1 -1
- package/dist/output-sibling.js +6 -5
- package/dist/path-policy.d.ts.map +1 -1
- package/dist/path-policy.js +1 -7
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +4 -0
- package/dist/permission-exec.d.ts +6 -0
- package/dist/permission-exec.d.ts.map +1 -0
- package/dist/permission-exec.js +28 -0
- package/dist/permissions-windows.d.ts +56 -0
- package/dist/permissions-windows.d.ts.map +1 -0
- package/dist/permissions-windows.js +285 -0
- package/dist/permissions.d.ts +3 -46
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +17 -328
- package/dist/pinned-write.js +2 -1
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +21 -2
- package/dist/replace-directory.d.ts.map +1 -1
- package/dist/replace-directory.js +10 -1
- package/dist/replace-file-copy-fallback.d.ts +3 -0
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +18 -11
- package/dist/replace-file-descriptor.d.ts +33 -0
- package/dist/replace-file-descriptor.d.ts.map +1 -0
- package/dist/replace-file-descriptor.js +96 -0
- package/dist/replace-file.d.ts +9 -2
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +64 -72
- package/dist/root-context.d.ts +8 -0
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +43 -2
- package/dist/root-errors.d.ts +7 -0
- package/dist/root-errors.d.ts.map +1 -1
- package/dist/root-errors.js +46 -1
- package/dist/root-file.d.ts +1 -0
- package/dist/root-file.d.ts.map +1 -1
- package/dist/root-file.js +2 -0
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +213 -168
- package/dist/root-path-symlink.d.ts +3 -0
- package/dist/root-path-symlink.d.ts.map +1 -0
- package/dist/root-path-symlink.js +35 -0
- package/dist/root-path.d.ts +1 -0
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +129 -190
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +15 -0
- package/dist/safe-path-segment.d.ts +2 -0
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +12 -0
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +19 -3
- package/dist/secure-temp-dir.d.ts.map +1 -1
- package/dist/secure-temp-dir.js +6 -1
- package/dist/short-path.d.ts +2 -0
- package/dist/short-path.d.ts.map +1 -0
- package/dist/short-path.js +7 -0
- package/dist/sidecar-lock-acquire.d.ts +30 -0
- package/dist/sidecar-lock-acquire.d.ts.map +1 -0
- package/dist/sidecar-lock-acquire.js +260 -0
- package/dist/sidecar-lock-policy.d.ts +3 -0
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +20 -3
- package/dist/sidecar-lock-reclaim.d.ts +5 -1
- package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
- package/dist/sidecar-lock-reclaim.js +59 -9
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +27 -226
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +15 -4
- package/dist/test-hooks.d.ts +1 -0
- package/dist/test-hooks.d.ts.map +1 -1
- package/dist/timing.d.ts +2 -0
- package/dist/timing.d.ts.map +1 -1
- package/dist/timing.js +9 -0
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +15 -0
- package/docs/advanced.md +1 -1
- package/docs/archive.md +27 -20
- package/docs/assets/readme-banner.jpg +0 -0
- package/docs/atomic.md +48 -19
- package/docs/errors.md +31 -7
- package/docs/file-store.md +10 -1
- package/docs/filename.md +17 -16
- package/docs/index.md +1 -0
- package/docs/install-path.md +9 -6
- package/docs/json.md +8 -2
- package/docs/local-roots.md +79 -103
- package/docs/native-helper.md +11 -5
- package/docs/native.md +2 -2
- package/docs/output.md +8 -3
- package/docs/path-scope.md +4 -1
- package/docs/path.md +7 -3
- package/docs/permissions.md +8 -0
- package/docs/public-api.md +109 -0
- package/docs/quickstart.md +6 -2
- package/docs/reading.md +13 -10
- package/docs/root.md +26 -4
- package/docs/secret-file.md +17 -4
- package/docs/security-model.md +21 -4
- package/docs/sidecar-lock.md +15 -5
- package/docs/temp.md +37 -5
- package/docs/test-hooks.md +2 -0
- package/docs/types.md +32 -15
- package/docs/writing.md +25 -12
- package/package.json +7 -3
- package/dist/archive-file-io.d.ts +0 -9
- package/dist/archive-file-io.d.ts.map +0 -1
- package/dist/archive-file-io.js +0 -11
- package/dist/file-store-source.d.ts +0 -5
- package/dist/file-store-source.d.ts.map +0 -1
- package/dist/file-store-source.js +0 -30
- package/dist/file-url.d.ts +0 -2
- package/dist/file-url.d.ts.map +0 -1
- package/dist/file-url.js +0 -1
- package/dist/path-stat.d.ts +0 -4
- package/dist/path-stat.d.ts.map +0 -1
- package/dist/path-stat.js +0 -15
- package/dist/windows-permissions-native.d.ts +0 -9
- package/dist/windows-permissions-native.d.ts.map +0 -1
- package/dist/windows-permissions-native.js +0 -31
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-tar.d.ts","sourceRoot":"","sources":["../src/archive-tar.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"archive-tar.d.ts","sourceRoot":"","sources":["../src/archive-tar.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAChC,MAAM,qBAAqB,CAAC;AAI7B,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAWvF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAyB7D;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,UAAU,CAAC,EAAE,0BAA0B,CAAC;CACzC,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CA+CnC"}
|
package/dist/archive-tar.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { resolveArchiveOutputPath, stripArchivePath, validateArchiveEntryPath, } from "./archive-entry.js";
|
|
1
|
+
import { createArchiveOutputPathTracker, resolveArchiveOutputPath, stripArchivePath, validateArchiveEntryPath, } from "./archive-entry.js";
|
|
2
2
|
import { assertArchiveEntryCountWithinLimit, assertArchiveEntryPathComponentsWithinLimit, createByteBudgetTracker, resolveExtractLimits, } from "./archive-limits.js";
|
|
3
3
|
import { archiveEntryKindFromTarType, shouldExtractArchiveEntry, } from "./archive-policy.js";
|
|
4
4
|
import { ArchiveSecurityError } from "./archive-errors.js";
|
|
5
|
+
import { formatErrorDetail } from "./error-detail.js";
|
|
5
6
|
const BLOCKED_TAR_ENTRY_TYPES = new Set([
|
|
6
7
|
"SymbolicLink",
|
|
7
8
|
"Link",
|
|
@@ -37,7 +38,10 @@ export function createTarEntryPreflightChecker(params) {
|
|
|
37
38
|
const limits = resolveExtractLimits(params.limits);
|
|
38
39
|
let entryCount = 0;
|
|
39
40
|
const budget = createByteBudgetTracker(limits);
|
|
41
|
+
const trackOutputPath = createArchiveOutputPathTracker();
|
|
40
42
|
return (entry) => {
|
|
43
|
+
entryCount += 1;
|
|
44
|
+
assertArchiveEntryCountWithinLimit(entryCount, limits);
|
|
41
45
|
validateArchiveEntryPath(entry.path, { escapeLabel: params.escapeLabel });
|
|
42
46
|
const relPath = stripArchivePath(entry.path, strip);
|
|
43
47
|
if (!relPath) {
|
|
@@ -45,14 +49,13 @@ export function createTarEntryPreflightChecker(params) {
|
|
|
45
49
|
}
|
|
46
50
|
validateArchiveEntryPath(relPath, { escapeLabel: params.escapeLabel });
|
|
47
51
|
assertArchiveEntryPathComponentsWithinLimit(relPath, limits);
|
|
52
|
+
trackOutputPath(relPath, entry.path);
|
|
48
53
|
resolveArchiveOutputPath({
|
|
49
54
|
rootDir: params.rootDir,
|
|
50
55
|
relPath,
|
|
51
56
|
originalPath: entry.path,
|
|
52
57
|
escapeLabel: params.escapeLabel,
|
|
53
58
|
});
|
|
54
|
-
entryCount += 1;
|
|
55
|
-
assertArchiveEntryCountWithinLimit(entryCount, limits);
|
|
56
59
|
const kind = archiveEntryKindFromTarType(entry.type);
|
|
57
60
|
if (!shouldExtractArchiveEntry({
|
|
58
61
|
filter: params.entryFilter,
|
|
@@ -62,7 +65,7 @@ export function createTarEntryPreflightChecker(params) {
|
|
|
62
65
|
return false;
|
|
63
66
|
}
|
|
64
67
|
if (BLOCKED_TAR_ENTRY_TYPES.has(entry.type)) {
|
|
65
|
-
throw new ArchiveSecurityError("entry-link", `tar entry is a link: ${entry.path}`);
|
|
68
|
+
throw new ArchiveSecurityError("entry-link", `tar entry is a link: ${formatErrorDetail(entry.path)}`);
|
|
66
69
|
}
|
|
67
70
|
budget.addEntrySize(entry.size);
|
|
68
71
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-zip-entry.d.ts","sourceRoot":"","sources":["../src/archive-zip-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"archive-zip-entry.d.ts","sourceRoot":"","sources":["../src/archive-zip-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC,cAAc,CAAC;IACzC,KAAK,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAChD,CAAC;AAKF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAK1D;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,sBAAsB,GAAG,SAAS,GACzC,MAAM,CAMR;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAE5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-zip-integrity.d.ts","sourceRoot":"","sources":["../src/archive-zip-integrity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAkBvD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CA8BtE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Transform } from "node:stream";
|
|
2
|
+
import { ArchiveFormatError } from "./archive-errors.js";
|
|
3
|
+
const CRC32_TABLE = Array.from({ length: 256 }, (_, index) => {
|
|
4
|
+
let value = index;
|
|
5
|
+
for (let bit = 0; bit < 8; bit += 1) {
|
|
6
|
+
value = (value & 1) !== 0 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;
|
|
7
|
+
}
|
|
8
|
+
return value >>> 0;
|
|
9
|
+
});
|
|
10
|
+
function updateCrc32(previous, buffer) {
|
|
11
|
+
let crc = previous ^ -1;
|
|
12
|
+
for (const byte of buffer) {
|
|
13
|
+
crc = (crc >>> 8) ^ (CRC32_TABLE[(crc ^ byte) & 0xff] ?? 0);
|
|
14
|
+
}
|
|
15
|
+
return (crc ^ -1) >>> 0;
|
|
16
|
+
}
|
|
17
|
+
export function createZipIntegrityTransform(entry) {
|
|
18
|
+
const expectedCrc32 = entry._data?.crc32;
|
|
19
|
+
const expectedSize = entry._data?.uncompressedSize;
|
|
20
|
+
if (typeof expectedCrc32 !== "number" ||
|
|
21
|
+
!Number.isInteger(expectedCrc32) ||
|
|
22
|
+
typeof expectedSize !== "number" ||
|
|
23
|
+
!Number.isSafeInteger(expectedSize) ||
|
|
24
|
+
expectedSize < 0) {
|
|
25
|
+
throw new ArchiveFormatError(`zip entry has invalid integrity metadata: ${entry.name}`);
|
|
26
|
+
}
|
|
27
|
+
let actualCrc32 = 0;
|
|
28
|
+
let actualSize = 0;
|
|
29
|
+
return new Transform({
|
|
30
|
+
transform(chunk, _encoding, callback) {
|
|
31
|
+
const buffer = chunk instanceof Buffer ? chunk : Buffer.from(chunk);
|
|
32
|
+
actualCrc32 = updateCrc32(actualCrc32, buffer);
|
|
33
|
+
actualSize += buffer.byteLength;
|
|
34
|
+
callback(null, buffer);
|
|
35
|
+
},
|
|
36
|
+
flush(callback) {
|
|
37
|
+
if (actualSize !== expectedSize || actualCrc32 !== (expectedCrc32 >>> 0)) {
|
|
38
|
+
callback(new ArchiveFormatError(`zip entry integrity check failed: ${entry.name}`));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
callback();
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive-zip-preflight.d.ts","sourceRoot":"","sources":["../src/archive-zip-preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"archive-zip-preflight.d.ts","sourceRoot":"","sources":["../src/archive-zip-preflight.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAiLF,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,IAAI,CAU5F;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,MAAM,GAAG,UAAU,EAC3B,MAAM,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAkB9B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ARCHIVE_LIMIT_ERROR_CODE, ArchiveLimitError, assertArchiveEntryCountWithinLimit, resolveExtractLimits, } from "./archive-limits.js";
|
|
2
|
+
import { ArchiveSecurityError } from "./archive-errors.js";
|
|
2
3
|
const ZIP_EOCD_SIGNATURE = 0x06054b50;
|
|
3
4
|
const ZIP64_EOCD_SIGNATURE = 0x06064b50;
|
|
4
5
|
const ZIP64_EOCD_LOCATOR_SIGNATURE = 0x07064b50;
|
|
@@ -148,7 +149,11 @@ export async function loadZipArchiveWithPreflight(buffer, limits) {
|
|
|
148
149
|
assertArchiveEntryCountWithinLimit(entryCount, resolvedLimits);
|
|
149
150
|
}
|
|
150
151
|
const JSZip = await importOptionalJsZip();
|
|
151
|
-
|
|
152
|
+
const archive = await JSZip.loadAsync(buffer);
|
|
153
|
+
if (entryCount !== null && Object.keys(archive.files).length !== entryCount) {
|
|
154
|
+
throw new ArchiveSecurityError("entry-path", "zip archive contains duplicate or colliding entry names");
|
|
155
|
+
}
|
|
156
|
+
return archive;
|
|
152
157
|
}
|
|
153
158
|
async function importOptionalJsZip() {
|
|
154
159
|
try {
|
package/dist/archive.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACjF,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,6BAA6B,EAC7B,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,iCAAiC,EACjC,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EACL,kCAAkC,EAClC,iCAAiC,EACjC,4BAA4B,EAC5B,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,8BAA8B,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AAoNpC,wBAAsB,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiKjF"}
|
package/dist/archive.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { Readable } from "node:stream";
|
|
5
5
|
import { pipeline } from "node:stream/promises";
|
|
6
|
-
import { resolveArchiveOutputPath, stripArchivePath, validateArchiveEntryPath, } from "./archive-entry.js";
|
|
6
|
+
import { createArchiveOutputPathTracker, resolveArchiveOutputPath, stripArchivePath, validateArchiveEntryPath, } from "./archive-entry.js";
|
|
7
7
|
import { createPipelineTimeoutError, waitForDeadline, withExtractionDeadline, } from "./archive-deadline.js";
|
|
8
8
|
import { assertArchiveEntryCountWithinLimit, assertArchiveEntryPathComponentsWithinLimit, createByteBudgetTracker, createExtractBudgetTransform, resolveExtractLimits, } from "./archive-limits.js";
|
|
9
9
|
import { resolveArchiveKind } from "./archive-kind.js";
|
|
@@ -11,6 +11,7 @@ import { mergeExtractedTreeIntoDestination, prepareArchiveDestinationDir, prepar
|
|
|
11
11
|
import { createTarEntryPreflightChecker, readTarEntryInfo, } from "./archive-tar.js";
|
|
12
12
|
import { loadZipArchiveWithPreflight } from "./archive-zip-preflight.js";
|
|
13
13
|
import { isZipSymlinkEntry, zipEntryDeclaredSize, zipEntryMode, } from "./archive-zip-entry.js";
|
|
14
|
+
import { createZipIntegrityTransform } from "./archive-zip-integrity.js";
|
|
14
15
|
import { FsSafeError } from "./errors.js";
|
|
15
16
|
import { ArchiveSecurityError } from "./archive-errors.js";
|
|
16
17
|
import { extractNativeArchive } from "./archive-native.js";
|
|
@@ -81,7 +82,7 @@ async function writeZipFileEntry(params) {
|
|
|
81
82
|
handleClosedByStream = true;
|
|
82
83
|
});
|
|
83
84
|
try {
|
|
84
|
-
await pipeline(readable, createExtractBudgetTransform({ onChunkBytes: params.budget.addBytes }), writable, { signal: params.deadline.signal });
|
|
85
|
+
await pipeline(readable, createExtractBudgetTransform({ onChunkBytes: params.budget.addBytes }), createZipIntegrityTransform(params.entry), writable, { signal: params.deadline.signal });
|
|
85
86
|
}
|
|
86
87
|
catch (err) {
|
|
87
88
|
throw createPipelineTimeoutError(err, params.deadline);
|
|
@@ -127,6 +128,7 @@ async function extractZip(params) {
|
|
|
127
128
|
const strip = Math.max(0, Math.floor(params.stripComponents ?? 0));
|
|
128
129
|
assertArchiveEntryCountWithinLimit(entries.length, limits);
|
|
129
130
|
const budget = createByteBudgetTracker(limits);
|
|
131
|
+
const trackOutputPath = createArchiveOutputPathTracker();
|
|
130
132
|
await withStagedArchiveDestination({
|
|
131
133
|
destinationRealDir,
|
|
132
134
|
run: async (stagingDir) => {
|
|
@@ -142,6 +144,7 @@ async function extractZip(params) {
|
|
|
142
144
|
continue;
|
|
143
145
|
}
|
|
144
146
|
assertArchiveEntryPathComponentsWithinLimit(output.relPath, limits);
|
|
147
|
+
trackOutputPath(output.relPath, entry.name);
|
|
145
148
|
const isSymlink = isZipSymlinkEntry(entry);
|
|
146
149
|
const entryKind = isSymlink ? "symlink" : entry.dir ? "directory" : "file";
|
|
147
150
|
const entrySize = zipEntryDeclaredSize(entry);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bounded-read-stream.d.ts","sourceRoot":"","sources":["../src/bounded-read-stream.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"bounded-read-stream.d.ts","sourceRoot":"","sources":["../src/bounded-read-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,MAAM,aAAa,CAAC;AAGlD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAwBnE;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE;IAAE,MAAM,EAAE;QAAE,gBAAgB,IAAI,MAAM,CAAC,cAAc,CAAA;KAAE,CAAA;CAAE,EACjE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,CAAC,cAAc,CAWvB"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { Transform } from "node:stream";
|
|
1
|
+
import { pipeline, Transform } from "node:stream";
|
|
2
2
|
import { FsSafeError } from "./errors.js";
|
|
3
3
|
export function createMaxBytesTransform(maxBytes) {
|
|
4
|
+
if (maxBytes !== Number.POSITIVE_INFINITY &&
|
|
5
|
+
(!Number.isSafeInteger(maxBytes) || maxBytes < 0)) {
|
|
6
|
+
throw new RangeError("maxBytes must be a non-negative safe integer or Infinity");
|
|
7
|
+
}
|
|
4
8
|
let bytes = 0;
|
|
5
9
|
return new Transform({
|
|
6
10
|
transform(chunk, _encoding, callback) {
|
|
@@ -16,5 +20,12 @@ export function createMaxBytesTransform(maxBytes) {
|
|
|
16
20
|
}
|
|
17
21
|
export function createBoundedReadStream(opened, maxBytes) {
|
|
18
22
|
const stream = opened.handle.createReadStream();
|
|
19
|
-
|
|
23
|
+
if (maxBytes === undefined) {
|
|
24
|
+
return stream;
|
|
25
|
+
}
|
|
26
|
+
const bounded = createMaxBytesTransform(maxBytes);
|
|
27
|
+
// pipeline couples teardown in both directions: source failures reach the
|
|
28
|
+
// returned stream, and an early consumer close destroys the file stream.
|
|
29
|
+
pipeline(stream, bounded, () => undefined);
|
|
30
|
+
return bounded;
|
|
20
31
|
}
|
package/dist/deny-mutations.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deny-mutations.d.ts","sourceRoot":"","sources":["../src/deny-mutations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deny-mutations.d.ts","sourceRoot":"","sources":["../src/deny-mutations.ts"],"names":[],"mappings":"AAKA,wBAAsB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAI1F;AAMD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAqBF,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,GAAG,SAAS,EACtC,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,kBAAkB,GAAG,SAAS,EAC7C,UAAU,EAAE,kBAAkB,GAAG,SAAS,GACzC,kBAAkB,GAAG,SAAS,CAWhC"}
|
package/dist/deny-mutations.js
CHANGED
|
@@ -1,41 +1,8 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import { FsSafeError } from "./errors.js";
|
|
4
|
-
import { assertNoNulPathInput,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
await fs.lstat(filePath);
|
|
8
|
-
return true;
|
|
9
|
-
}
|
|
10
|
-
catch (err) {
|
|
11
|
-
if (!isNotFoundPathError(err)) {
|
|
12
|
-
throw err;
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
async function resolvePathViaExistingAncestor(targetPath) {
|
|
18
|
-
const normalized = path.resolve(targetPath);
|
|
19
|
-
let cursor = normalized;
|
|
20
|
-
const missingSuffix = [];
|
|
21
|
-
while (path.dirname(cursor) !== cursor && !(await pathExists(cursor))) {
|
|
22
|
-
missingSuffix.unshift(path.basename(cursor));
|
|
23
|
-
cursor = path.dirname(cursor);
|
|
24
|
-
}
|
|
25
|
-
if (!(await pathExists(cursor))) {
|
|
26
|
-
return normalized;
|
|
27
|
-
}
|
|
28
|
-
try {
|
|
29
|
-
const resolvedAncestor = path.resolve(await fs.realpath(cursor));
|
|
30
|
-
return missingSuffix.length === 0
|
|
31
|
-
? resolvedAncestor
|
|
32
|
-
: path.resolve(resolvedAncestor, ...missingSuffix);
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return normalized;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
async function comparablePaths(rawPath) {
|
|
3
|
+
import { assertNoNulPathInput, isPathInside } from "./path.js";
|
|
4
|
+
import { resolvePathViaExistingAncestor } from "./root-path-existing.js";
|
|
5
|
+
export async function resolveMutationComparablePaths(rawPath) {
|
|
39
6
|
assertNoNulPathInput(rawPath, "path contains a NUL byte");
|
|
40
7
|
const resolved = path.resolve(rawPath);
|
|
41
8
|
return new Set([resolved, await resolvePathViaExistingAncestor(resolved)]);
|
|
@@ -64,9 +31,9 @@ export async function assertMutationNotDenied(filePath, policy, options = {}) {
|
|
|
64
31
|
if (!hasPolicyEntries(policy)) {
|
|
65
32
|
return;
|
|
66
33
|
}
|
|
67
|
-
const targetPaths = await
|
|
34
|
+
const targetPaths = await resolveMutationComparablePaths(filePath);
|
|
68
35
|
for (const deniedPath of policyPathEntries(policy.paths)) {
|
|
69
|
-
const deniedPaths = await
|
|
36
|
+
const deniedPaths = await resolveMutationComparablePaths(deniedPath);
|
|
70
37
|
for (const target of targetPaths) {
|
|
71
38
|
for (const denied of deniedPaths) {
|
|
72
39
|
if (isSamePath(denied, target) ||
|
|
@@ -77,7 +44,7 @@ export async function assertMutationNotDenied(filePath, policy, options = {}) {
|
|
|
77
44
|
}
|
|
78
45
|
}
|
|
79
46
|
for (const deniedPrefix of policyPathEntries(policy.prefixes)) {
|
|
80
|
-
const deniedPaths = await
|
|
47
|
+
const deniedPaths = await resolveMutationComparablePaths(deniedPrefix);
|
|
81
48
|
for (const target of targetPaths) {
|
|
82
49
|
for (const denied of deniedPaths) {
|
|
83
50
|
if (isPathInside(denied, target) ||
|
package/dist/device-path.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type UnsafeDeviceReadPathOptions = {
|
|
|
7
7
|
cwd?: string;
|
|
8
8
|
platform?: NodeJS.Platform;
|
|
9
9
|
};
|
|
10
|
+
export declare const WINDOWS_RESERVED_DEVICE_NAMES: ReadonlySet<string>;
|
|
10
11
|
export declare function matchUnsafeDeviceReadPath(filePath: string, options?: UnsafeDeviceReadPathOptions): UnsafeDeviceReadPathMatch | undefined;
|
|
11
12
|
export declare function isUnsafeDeviceReadPath(filePath: string, options?: UnsafeDeviceReadPathOptions): boolean;
|
|
12
13
|
export declare function assertNoUnsafeDeviceReadPath(filePath: string, options?: UnsafeDeviceReadPathOptions): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-path.d.ts","sourceRoot":"","sources":["../src/device-path.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,0BAA0B,GAClC,cAAc,GACd,UAAU,GACV,gBAAgB,CAAC;AAErB,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,CAAC;
|
|
1
|
+
{"version":3,"file":"device-path.d.ts","sourceRoot":"","sources":["../src/device-path.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,0BAA0B,GAClC,cAAc,GACd,UAAU,GACV,gBAAgB,CAAC;AAErB,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC5B,CAAC;AAcF,eAAO,MAAM,6BAA6B,EAAE,WAAW,CAAC,MAAM,CAgC5D,CAAC;AAkFH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,2BAAgC,GACxC,yBAAyB,GAAG,SAAS,CAWvC;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAET;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,2BAA2B,GACpC,IAAI,CAON"}
|
package/dist/device-path.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { FsSafeError } from "./errors.js";
|
|
3
|
-
import { trySafeFileURLToPath } from "./local-file-access.js";
|
|
3
|
+
import { isFileUrl, trySafeFileURLToPath } from "./local-file-access.js";
|
|
4
4
|
const POSIX_BLOCKED_DEVICE_PATHS = new Set([
|
|
5
5
|
"/dev/zero",
|
|
6
6
|
"/dev/random",
|
|
@@ -12,7 +12,7 @@ const POSIX_BLOCKED_DEVICE_PATHS = new Set([
|
|
|
12
12
|
"/dev/tty",
|
|
13
13
|
"/dev/console",
|
|
14
14
|
]);
|
|
15
|
-
const WINDOWS_RESERVED_DEVICE_NAMES = new Set([
|
|
15
|
+
export const WINDOWS_RESERVED_DEVICE_NAMES = new Set([
|
|
16
16
|
"CON",
|
|
17
17
|
"PRN",
|
|
18
18
|
"AUX",
|
|
@@ -67,11 +67,11 @@ function trimTrailingWindowsIgnoredChars(value) {
|
|
|
67
67
|
}
|
|
68
68
|
return end === value.length ? value : value.slice(0, end);
|
|
69
69
|
}
|
|
70
|
-
function candidateReadPaths(filePath) {
|
|
71
|
-
if (!filePath
|
|
70
|
+
function candidateReadPaths(filePath, platform) {
|
|
71
|
+
if (!isFileUrl(filePath)) {
|
|
72
72
|
return [filePath];
|
|
73
73
|
}
|
|
74
|
-
const parsed = trySafeFileURLToPath(filePath);
|
|
74
|
+
const parsed = trySafeFileURLToPath(filePath, platform);
|
|
75
75
|
return parsed === undefined ? [filePath] : [filePath, parsed];
|
|
76
76
|
}
|
|
77
77
|
function normalizePosixPath(filePath, cwd) {
|
|
@@ -114,7 +114,7 @@ function matchWindowsDeviceReadPath(filePath) {
|
|
|
114
114
|
}
|
|
115
115
|
export function matchUnsafeDeviceReadPath(filePath, options = {}) {
|
|
116
116
|
const platform = options.platform ?? process.platform;
|
|
117
|
-
for (const candidate of candidateReadPaths(filePath)) {
|
|
117
|
+
for (const candidate of candidateReadPaths(filePath, platform)) {
|
|
118
118
|
const match = platform === "win32"
|
|
119
119
|
? matchWindowsDeviceReadPath(candidate)
|
|
120
120
|
: matchPosixDeviceReadPath(candidate, options.cwd);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-guard.d.ts","sourceRoot":"","sources":["../src/directory-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"directory-guard.d.ts","sourceRoot":"","sources":["../src/directory-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AASrC,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAMzF;AAED,wBAAsB,yBAAyB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzF;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAMxE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAQxE;AAED,wBAAsB,mCAAmC,CACvD,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAc9B;AAED,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,kBAAkB,CAcpB"}
|
package/dist/directory-guard.js
CHANGED
|
@@ -4,17 +4,18 @@ import path from "node:path";
|
|
|
4
4
|
import { FsSafeError } from "./errors.js";
|
|
5
5
|
import { sameFileIdentity } from "./file-identity.js";
|
|
6
6
|
import { isNotFoundPathError } from "./path.js";
|
|
7
|
+
import { directoryComponentNotDirectoryError } from "./root-errors.js";
|
|
7
8
|
export async function createAsyncDirectoryGuard(dir) {
|
|
8
9
|
const stat = await fs.lstat(dir);
|
|
9
10
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
10
|
-
throw
|
|
11
|
+
throw directoryComponentNotDirectoryError();
|
|
11
12
|
}
|
|
12
13
|
return { dir, realPath: await fs.realpath(dir), stat };
|
|
13
14
|
}
|
|
14
15
|
export async function assertAsyncDirectoryGuard(guard) {
|
|
15
16
|
const stat = await fs.lstat(guard.dir);
|
|
16
17
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
17
|
-
throw
|
|
18
|
+
throw directoryComponentNotDirectoryError();
|
|
18
19
|
}
|
|
19
20
|
if (!sameFileIdentity(stat, guard.stat) || (await fs.realpath(guard.dir)) !== guard.realPath) {
|
|
20
21
|
throw new FsSafeError("path-mismatch", "directory changed during operation");
|
|
@@ -23,14 +24,14 @@ export async function assertAsyncDirectoryGuard(guard) {
|
|
|
23
24
|
export function createSyncDirectoryGuard(dir) {
|
|
24
25
|
const stat = fsSync.lstatSync(dir);
|
|
25
26
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
26
|
-
throw
|
|
27
|
+
throw directoryComponentNotDirectoryError();
|
|
27
28
|
}
|
|
28
29
|
return { dir, realPath: fsSync.realpathSync(dir), stat };
|
|
29
30
|
}
|
|
30
31
|
export function assertSyncDirectoryGuard(guard) {
|
|
31
32
|
const stat = fsSync.lstatSync(guard.dir);
|
|
32
33
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
33
|
-
throw
|
|
34
|
+
throw directoryComponentNotDirectoryError();
|
|
34
35
|
}
|
|
35
36
|
if (!sameFileIdentity(stat, guard.stat) || fsSync.realpathSync(guard.dir) !== guard.realPath) {
|
|
36
37
|
throw new FsSafeError("path-mismatch", "directory changed during operation");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-detail.d.ts","sourceRoot":"","sources":["../src/error-detail.ts"],"names":[],"mappings":"AAGA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIvD"}
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,gBAAgB,GAChB,aAAa,GACb,aAAa,GACb,UAAU,GACV,eAAe,GACf,oBAAoB,GACpB,cAAc,GACd,sBAAsB,GACtB,WAAW,GACX,UAAU,GACV,WAAW,GACX,WAAW,GACX,eAAe,GACf,mBAAmB,GACnB,YAAY,GACZ,eAAe,GACf,uBAAuB,GACvB,eAAe,GACf,wBAAwB,GACxB,SAAS,GACT,SAAS,GACT,WAAW,GACX,sBAAsB,CAAC;AAE3B,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,aAAa,CAAC;AAC3D,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,gBAAgB,GAChB,aAAa,GACb,aAAa,GACb,UAAU,GACV,eAAe,GACf,oBAAoB,GACpB,cAAc,GACd,sBAAsB,GACtB,WAAW,GACX,UAAU,GACV,WAAW,GACX,WAAW,GACX,eAAe,GACf,mBAAmB,GACnB,YAAY,GACZ,eAAe,GACf,uBAAuB,GACvB,eAAe,GACf,wBAAwB,GACxB,SAAS,GACT,SAAS,GACT,WAAW,GACX,sBAAsB,CAAC;AAE3B,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,aAAa,CAAC;AAC3D,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAanE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,eAAe,GAAG,mBAAmB,CAEhF;AAED,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAEtC,YACE,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;KAAO,EAOhE;CACF"}
|
package/dist/errors.js
CHANGED
package/dist/file-hash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-hash.d.ts","sourceRoot":"","sources":["../src/file-hash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAcF,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,aAAa,GAAG,SAA8B,GACrD,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;
|
|
1
|
+
{"version":3,"file":"file-hash.d.ts","sourceRoot":"","sources":["../src/file-hash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAcF,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,aAAa,GAAG,SAA8B,GACrD,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;AA2CD,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAElF"}
|
package/dist/file-hash.js
CHANGED
|
@@ -59,7 +59,10 @@ async function hashPath(filePath) {
|
|
|
59
59
|
if (!opened.isFile()) {
|
|
60
60
|
throw new FsSafeError("not-file", "SHA-256 path is not a regular file");
|
|
61
61
|
}
|
|
62
|
-
if (current.isSymbolicLink() ||
|
|
62
|
+
if (current.isSymbolicLink() ||
|
|
63
|
+
!current.isFile() ||
|
|
64
|
+
!sameFileIdentity(before, opened) ||
|
|
65
|
+
!sameFileIdentity(opened, current)) {
|
|
63
66
|
throw new FsSafeError("path-mismatch", "SHA-256 path changed while opening");
|
|
64
67
|
}
|
|
65
68
|
return await hashFileHandle(handle);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-lock-sync.d.ts","sourceRoot":"","sources":["../src/file-lock-sync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAOL,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"file-lock-sync.d.ts","sourceRoot":"","sources":["../src/file-lock-sync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAOL,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,0BAA0B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,QAAQ,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,iBAAiB,EAAE,KAAK,CAAC;KAC1B,KAAK,OAAO,CAAC;IACd,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,wBAAwB,KAAK,OAAO,CAAC;IACxE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC3D,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,IAAI,OAAO,CAAC;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B,CAAC;AA0IF,wBAAgB,mBAAmB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAC5C,kBAAkB,CAuJpB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,EAC7C,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAOH"}
|