fix(preview): normalize entry names the way ExcelJS sees them, skip defined names, pin fflate 0.8.3

Admission checked ZIP entry names as stored, but JSZip (inside ExcelJS)
resolves `.`, `..` and empty segments on load, and ExcelJS strips one
leading `/` and matches worksheets with an unanchored pattern. Names like
`/xl/worksheets/sheet1.xml` or `xl/worksheets/sheet1.xml.x` skipped every
counter. Admission now computes the name ExcelJS will see for each entry,
refuses two entries that resolve to the same name, keys the rebuilt
archive on it, and picks the worksheet/styles counters from it.

ExcelJS's DefinedNames model setter expands every range into one object
per cell. The preview never shows defined names, so the worker stubs
`_definedNames.model` before load.

Pin fflate to 0.8.3 (GHSA-px8p-9vwx-vf98) and refresh
SPREADSHEET_ASSET_VERSION.
This commit is contained in:
Aamer Akhter
2026-10-03 08:21:54 -04:00
parent d65ee4f89d
commit 2d0ffb71aa
12 changed files with 195 additions and 18 deletions
+4
View File
@@ -160,6 +160,10 @@ describe('dependency security policy', () => {
expectEveryLockedVersionAtLeast(lock, 'find-my-way', '9.7.0');
expectEveryLockedVersionAtLeast(lock, 'basic-ftp', '5.3.1');
expectEveryLockedVersionAtLeast(lock, 'flatted', '3.4.2');
// GHSA-px8p-9vwx-vf98 (unbounded loop on a ZIP64 marker in a local header)
// covers <=0.8.2. The XLSX preview worker streams untrusted files through
// fflate's Unzip before any admission callback runs.
expectEveryLockedVersionAtLeast(lock, 'fflate', '0.8.3');
expectNoVulnerableBraceExpansion(lock);
expectNoVulnerableVite(lock);
expectNoVulnerablePicomatch(lock);