Replace abandoned exceljs dependency with @e965/xlsx - #6165
Open
jonnalley wants to merge 1 commit into
Open
Conversation
jonnalley
requested review from
Santi-3rd,
fpigeonjr,
josbell,
rajohnson90 and
weimiao67
as code owners
August 27, 2026 00:36
weimiao67
approved these changes
Aug 27, 2026
Santi-3rd
approved these changes
Aug 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Replaces the
exceljsnpm dependency (pinned at4.4.0) with@e965/xlsx(SheetJS Community Edition, republished to npm).exceljswas Snyk-flagged for several CVEs, and investigation confirmed the project is effectively abandoned: no commit tomastersince 2024-01-12, no stable release since 2023-10-19 (4.4.0 is still npm'slatest), 802 open issues dating back to 2015, and zero upstream response to 4 new CVEs disclosed— none of which have a fixed version.A codebase audit found
exceljswas only ever used write-only with app-trusted data (no.load()/parsing of untrusted input in shipped code), so there was no active exploit path today, but continuing to depend on an abandoned library was judged not worth the risk.@e965/xlsxwas chosen over plainxlsx(its npm build is 4+ years behind SheetJS's actual patched releases) and overwrite-excel-file/read-excel-file(two packages with no shared workbook model — a bigger structural change for no benefit given this app never loads-and-mutates an existing workbook).frontend/package.json/frontend/bun.lock: removedexceljs, added@e965/xlsxpinned to an exact version (0.20.3, no^/~), matching this repo's existing exact-pin convention.frontend/src/helpers/tableExport.helpers.js: rewroteexportTableToXlsxandexportMultiSheetToXlsxon SheetJS's API (XLSX.utils.aoa_to_sheet/book_new/book_append_sheet/write) instead of ExcelJS's workbook/worksheet object model. Extracted the per-cell currency-numFmt logic (previously duplicated in both functions) into a sharedapplyCurrencyFormathelper.frontend/src/helpers/tableExport.helpers.test.js: updated the read-back assertions to SheetJS equivalents (XLSX.read,wb.Sheets[name],cell.zinstead ofcell.numFmt). Also fixed two assertions that assumed ExcelJS's "no format" semantics (undefined/falsy) — SheetJS's default for an unformatted cell is the string"General", so those now assert.not.toBe(CURRENCY_FORMAT)instead of.toBeFalsy().Issue
N/A — no tracked ticket for this dependency swap.
How to test
cd frontend && bun run test --watch=false src/helpers/tableExport.helpers.test.js— all 8 tests pass.cd frontend && bun run test --watch=false— full suite passes (359/360 files, 4308 tests).cd frontend && bun run build— production Vite build succeeds with no bundling issues for@e965/xlsx..xlsxvia the same code path outside the test harness and inspected it at the byte/XML level —fileidentifies it as genuine "Microsoft Excel 2007+", andstyles.xml/sheet1.xmlshow the currencynumFmtcorrectly applied to the expected cells.docker compose up db data-import backend frontend --build, trigger any table export (e.g. Agreements list, Budget Line List), and confirm the downloaded.xlsxopens correctly with headers, data, and currency-formatted columns.A11y impact
Storybook
src/components/UI/Screenshots
N/A — dependency/library swap only, no visual or markup change.
Definition of Done Checklist
Links
N/A