Skip to content

download@8 dependency chain carries unfixable advisories (including a critical) #263

Description

@taylortom

Summary

adapt-cli@3.4.0 depends on download@8, whose dependency chain carries several advisories — including one critical with no patched version in any release, so consumers cannot resolve it with an overrides entry. Retiring download would clear the whole cluster, and most of the replacement is already a dependency of this package.

Reproducible with:

npm i adapt-cli@3.4.0 && npm audit

The chain

Severity Package Installed Reaches via Fixed in
critical decompress 4.2.1 downloaddecompress no fixed release (advisory covers <=4.2.1, and 4.2.1 is latest)
high http-cache-semantics 3.8.1 downloadgot@8cacheable-request@2 4.1.1
high cacheable-request 2.1.4 downloadgot@8 6.0.0
high got 8.3.2 download 11.8.5
high tmp 0.0.33 inquirer@7external-editor 0.2.6
moderate uuid 8.3.2 direct dependency 11.1.1

decompress is the blocking one: the advisory (archive extraction can create files and links outside the target directory — "zip slip") applies to every published version, so there is no version to bump or override to. The only fix is not depending on it.

Where download is actually used

As far as I can tell it has a single consumer, lib/util/download.js, which does one thing:

import fetch from 'download'
// …
fetch(url, tmp, { extract: true })
  .on('response', response => { /* read content-disposition for the filename */ })

That is: GET a repository archive .zip and unpack it. It's reached from lib/integration/AdaptFramework/download.js (framework install/update) and lib/commands/create/component.js.

The fetch half needs no new dependency. node-fetch@3 is already in dependencies and already used across lib/integration/PluginManagement/* (authenticate.js, register.js, rename.js, unregister.js, search.js), so the HTTP portion could move onto it — or onto Node's built-in fetch, given the archive download is a plain GET. Only the unpack step needs a maintained extractor (e.g. yauzl, or tar's zip support), and it's needed in exactly one place.

Doing that would drop download, decompress, got, cacheable-request and http-cache-semantics from the tree in one change — 5 of the 6 rows above.

Two smaller things in the same area

  • decompress is also a direct dependency, and appears to be unused. Its only importer is lib/util/extract.js, and nothing in the published package imports that — the only other occurrence of the string extract is the extract: true option passed to download. If lib/util/extract.js is indeed dead code, the direct decompress dependency can be dropped on its own, independently of the download work.
  • inquirer@7external-editortmp@0.0.33 and uuid@8.3.2 are both straightforward bumps (uuid keeps the named v4 export used in lib/util/download.js and lib/util/extract.js), clearing the remaining two rows.

Why consumers can't just paper over it

For anyone reaching for overrides as a stopgap, two of these don't work:

  • decompress has no fixed version to point at.
  • Forcing http-cache-semantics@4 onto cacheable-request@2 is not safe: cacheable-request calls CachePolicy.fromObject(…).revalidatedPolicy(…), whose return shape changed between 3.x and 4.x.

So the fix does need to happen here rather than downstream.

Suggested order

The lib/util/extract.js removal and the inquirer/uuid bumps are small and independent of each other, so they could land first for a quick reduction. The download replacement is the substantive one — worth treating separately, since it touches the framework install path and would want checking on Windows (the current code carries \\-handling, so path behaviour there matters).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions