Skip to content

Commit 1b99143

Browse files
committed
fix: enhance ZIP entry name validation to reject Windows-style absolute paths
Updated the _isSafeZipEntryName function to explicitly reject Windows-style absolute paths and drive-letter prefixes, ensuring consistent security across all platforms. Added corresponding test cases to validate these changes.
1 parent 83da394 commit 1b99143

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

src/cbusProjectParser.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ const MAX_DECOMPRESSED_BYTES = 100 * 1024 * 1024; // 100MB
1616
// names on write, so we can't reach this path from a JS-built archive.
1717
function _isSafeZipEntryName(name) {
1818
if (typeof name !== 'string' || name.length === 0) return false;
19-
if (path.isAbsolute(name)) return false;
19+
// ZIP entry names use forward slashes regardless of platform, and a
20+
// malicious archive can embed any separator or drive letter. `path.isAbsolute`
21+
// is host-OS specific (e.g. on POSIX it misses `C:\...` and `\\server\...`),
22+
// so test both conventions and reject any drive-letter prefix explicitly.
23+
if (path.posix.isAbsolute(name) || path.win32.isAbsolute(name)) return false;
24+
if (/^[A-Za-z]:/.test(name)) return false;
2025
const parts = name.split(/[/\\]/);
2126
return !parts.includes('..');
2227
}

tests/cbusProjectParser.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,14 @@ describe('CbusProjectParser', () => {
265265
expect(_isSafeZipEntryName('foo/../../etc/passwd')).toBe(false);
266266
expect(_isSafeZipEntryName('/etc/passwd')).toBe(false);
267267
expect(_isSafeZipEntryName('foo\\..\\..\\bar')).toBe(false);
268+
// Windows-style absolute paths must be rejected on every host OS,
269+
// not just Windows: path.isAbsolute() is platform-specific and a
270+
// POSIX host would otherwise let these through.
271+
expect(_isSafeZipEntryName('C:\\Windows\\system32')).toBe(false);
272+
expect(_isSafeZipEntryName('C:/Windows/system32')).toBe(false);
273+
expect(_isSafeZipEntryName('\\\\server\\share\\file')).toBe(false);
274+
expect(_isSafeZipEntryName('\\foo')).toBe(false);
275+
expect(_isSafeZipEntryName('D:relative')).toBe(false);
268276
expect(_isSafeZipEntryName('')).toBe(false);
269277
expect(_isSafeZipEntryName(undefined)).toBe(false);
270278
});

0 commit comments

Comments
 (0)