Skip to content

KeyError thrown due to missing versions in uninstalled platform-specific NPM dependencies #182

@orzechowskid

Description

@orzechowskid

hi there! I'm investigating the integration of scfw into our toolchain and am coming across some behavior which i didn't expect.

running scfw audit npm, in my git repository containing a project managed by npm 10.9.3, gives me this error message:

[SCFW] ERROR: Malformed installed package report

even though as far as I could tell npm list --all --json returned a well-formed JSON object containing the expected properties.

while debugging this issue I noticed that npm.py assumes a "package" key is always present in dependency dictionaries (https://github.com/DataDog/supply-chain-firewall/blob/main/scfw/package_managers/npm.py#L181 ), but I don't think that's guaranteed to be true. for instance, one of this webapp's transitive dependencies is esbuild, which has its own dependencies which are platform-specific. on my mac, npm list --all --json | jq '.dependencies["vite"]' gives me the following (truncated for clarity):

{
  "version": "4.5.14",
  "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz",
  "overridden": false,
  "dependencies": {
    "@types/node": {
      "version": "24.9.2"
    },
    "esbuild": {
      "version": "0.18.20",
      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
      "overridden": false,
      "dependencies": {
        "@esbuild/android-arm": {},
        "@esbuild/android-arm64": {},
        "@esbuild/android-x64": {},
        "@esbuild/darwin-arm64": {
          "version": "0.18.20",
          "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
          "overridden": false
        },
        "@esbuild/darwin-x64": {},
        "@esbuild/freebsd-arm64": {},
        "@esbuild/freebsd-x64": {},
        "@esbuild/linux-arm": {},
        <...>
      }
    },
<...>

a potential fix would be simple, looking something like this:

+              if package_data.get("version", None) is not None:
                  packages.add(Package(ECOSYSTEM.Npm, name, package_data["version"]))

but I wasn't sure if it was an explicit decision to throw a KeyError when no version info could be found, in the spirit of blocking 100% of attempted installations of known-vulnerable packages.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions