fix(deps): bump adm-zip to 0.6.0 and override qs to 6.16.0 (+Claude) - #227
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
There was a problem hiding this comment.
🟡 Changes recommended
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Automated dependency-vulnerability remediation for the Node.js CLI by upgrading adm-zip (with a small TypeScript adaptation) and raising an existing qs override floor to a patched version.
Changes:
- Bumped
adm-zipto^0.6.0and updatedarchive()to handlewriteZipPromise()’svoidreturn type. - Raised the
qsoverride to^6.16.0and updated the lockfile accordingly. - Removed
@types/adm-zip(now bundled withadm-zip@0.6.0) and updated Talisman ignore config.
File summaries
| File | Description |
|---|---|
| src/adapters/file-upload.ts | Adjusts ZIP creation error handling to match adm-zip@0.6.0 typings/contract. |
| package.json | Updates dependency versions (adm-zip, qs override) and removes @types/adm-zip. |
| package-lock.json | Locks updated adm-zip/qs resolutions and removes @types/adm-zip entries. |
| .talismanrc | Adds a new ignore entry for src/adapters/file-upload.ts (needs reconsideration). |
Review details
- Files reviewed: 3/4 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
…g lines (+Claude)
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
There was a problem hiding this comment.
🟡 Changes recommended
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
src/adapters/file-upload.ts:343
- The new
zippedflag +.catch()indirection makes this error path harder to follow and relies on mutable state. A simpletry/catcharoundwriteZipPromiseis clearer and keeps the “single log + exit(1)” behavior without needing a sentinel boolean.
let zipped = true;
await zip.writeZipPromise(zipPath).catch(() => {
zipped = false;
});
.talismanrc:24
- PR description says the
.talismanrcchange forsrc/adapters/file-upload.tsis achecksumentry that “fails closed”, but the diff addsallowed_patternsinstead.allowed_patternsdoes not fail-closed (it can continue suppressing findings after future edits) and is a materially different risk profile—either update the description or switch this entry to a checksum-based ignore.
- filename: src/adapters/file-upload.ts
allowed_patterns:
- "const \\{ formFieldKey, formFieldValue \\} of fields"
- "formData\\.append\\(formFieldKey, formFieldValue\\)"
- Files reviewed: 4/5 changed files
- Comments generated: 1
- Review effort level: Lite
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
🔒 Security Scan Results
⏱️ SLA Breach Summary
ℹ️ Vulnerabilities Without Available Fixes (Informational Only)The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:
✅ BUILD PASSED - All security checks passed |
Snyk fix routine — 31-Aug-2026
Automated dependency-vulnerability remediation pass. Surface in scope: Node.js.
Fix summary
Buffer.alloc(4GB allocation → OOM)adm-zip(direct dependency)^0.5.18→^0.6.0qs(override)^6.15.2→^6.16.0>=6.14.2 <6.16.0; the whole 6 major is patched at that floor, so^6.16.0. Reached viaexpress@4.22.2 › qs.@types/adm-zip(devDependency)^0.5.7→ removedadm-zip@0.6.0ships its owntypes.d.ts, which takes precedence. Leaving the stale@typespackage at 0.5.x meant two competing declarations for the same module.Application-code change — please review closely
src/adapters/file-upload.ts,archive()— one adaptation was required by theadm-zipmajor.In 0.6.0 the bundled types declare
writeZipPromise(): Promise<void>(0.5.x's@typessaidPromise<boolean>), so the old truthiness check no longer compiled:error TS1345: An expression of type 'void' cannot be tested for truthiness.Why this preserves behavior: the type changed, the runtime contract did not — 0.6.0's implementation still
resolve(done)on success andrejects on failure. Failure therefore still reaches exactly onelog+exit(1), and success still falls through. The rewrite tracks failure through the.catch()(the actual signal) instead of a return value the types no longer expose. Incidentally it also removes the old double-log: the previous code logged in.catch()and again in theif (!status)branch on the same failure.Now covered by tests.
src/adapters/file-upload.test.tsgains anarchivedescribe block with two cases:writeZipPromiserejecting (asserts the message is logged exactly once andexit(1)fires) and resolving (asserts the returned zip details, and that neitherlognorexitis called). Suite is 137 passed, up from 135. Verified they fail for the right reason: injecting a swallowed-rejection regression fails the first test while the second still passes. The failure path also moved from azippedflag to a plaintry/catchon review feedback — simpler, and the tests passed unchanged across that refactor, which is itself evidence they assert behaviour rather than implementation.Why the
adm-zipmajor is safe hereThe 0.6.0 release notes list exactly two behavior changes, both in extraction:
extractEntryTo(...)now preserves subdirectories instead of flattening by basename.utimesis best-effort).This repo is write-only: the sole usage is
new AdmZip()plusaddLocalFolder/addLocalFile/writeZipPromise. Greppingsrc/andtest/finds noextractEntryTo,extractAllTo, orgetEntriescall anywhere — so neither breaking change is reachable. The third note (minimum Node raised to 14) is moot:enginesalready requires>=22.0.0.Full scope of this PR —
.talismanrcis also changedThis PR also changes
.talismanrc(secrets-scanner config). Talisman flagssrc/adapters/file-upload.tsandsrc/adapters/file-upload.test.tswith low-severity matches onpre-existing lines this diff never touches — it re-scans each whole file because the checksum
changed, and both prior entries were checksum-based, so editing either file invalidated them.
Both are now per-pattern
allowed_patterns, so thefilecontentdetector stays active on bothfiles and only these specific lines are exempt:
file-upload.tsformFieldKey/formFieldValuedestructuring +formData.append(388-389); theheaderstype andheaders?.reduce(426, 433); the({ key, value }) => ({ key, value }))map callback (142);const { token, apiKey } = configHandler.get(189)file-upload.test.tsEvery pattern matches an identifier or destructuring shape, never a value, so a real leaked
credential in either file would still be caught.
On fail-closed vs. pattern-based — a reviewer fairly noted
allowed_patternskeeps suppressingacross future edits, whereas a checksum invalidates itself. That is the trade-off, and it cuts both
ways: the checksum form is what produced this failure in the first place, because it re-breaks on
every unrelated edit to the file (the
secrets-scanfailures across this whole fleet of PRs wereexactly that). The patterns here are narrow enough that genuinely new content is still scanned.
If the team prefers strict fail-closed behaviour on production source, a checksum entry is a
reasonable alternative — happy to switch.
Note
.talismanrcitself now trips the detector as warnings (non-fatal) — inherent to theper-pattern approach, since the exemptions must quote the strings they exempt.
Ecosystem-native audit pass (step 1.5)
npm audit: 1 high → 0.npm audit fix(non---force) correctly declined theadm-zipfix, reportingfix available via npm audit fix --force ... which is a breaking change, and left the tree untouched —--forceis prohibited by this routine. The bump was therefore taken through the deliberate Snyk path above, with changelog review and the adaptation documented, rather than applied blindly.Snyk scan
1 project scanned (
package-lock.json, 463 deps), matching the one manifest on disk. 3 issues → 1 (the remaining one is unfixable — below).Self code review
2 rounds.
package.jsonadded a trailing newline the file didn't have, producing unrelated whitespace noise. Restored the original formatting so the manifest diff is exactly the intended lines.adm-zipbump, theqsresolution, and the@types/adm-zipremoval.Needs human review — NOT yet resolved
adm-zip— CVE-2026-76845, Symlink Attack (high). No fix exists. The advisory range is>=0.5.9, which includes 0.6.0, so this is pre-existing — 0.5.18 was affected too and this PR neither introduces nor worsens it. The vulnerable code paths areextractAllTo,extractAllToAsyncandextractEntryToinutil/utils.js; as established above, this repo never extracts archives, so the paths are unreachable here. Left for a maintainer to track until upstream ships a fix (or to ignore on the dashboard citing non-reachability).Validation
npm install— pass, no errorsnpm run build(tsc -b+ patch step) — passnpm test— pass (8 suites, 135 passed)npm audit— 1 high → 0snyk test --all-projectsre-scan — theadm-zipDoS and bothqsadvisories are gone; only the unfixable symlink advisory remains