Skip to content

fix: KeyError: 'dependencies' with npm projects #3559

@perrinjerome

Description

@perrinjerome

Description

npm projects use package-lock.json, but in node_modules/.package-lock.json there is a file with similar (but different) format that confuses the javascript parser.

To reproduce

Steps to reproduce the behaviour:

  1. create a minimal nodejs project, using these commands:
mkdir package_json_lock_no_dependencies
cd package_json_lock_no_dependencies
npm init -y
npm add is-odd
  1. run cve-bin-tool .

Expected behaviour:

no error

Actual behaviour:

KeyError in

for i in data["dependencies"]:

This happens while parsing node_modules/.package-lock.json file (with a . at the beginning) which contains:

{
  "name": "package_json_lock_no_dependencies",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "node_modules/is-number": {
      "version": "6.0.0",
      "resolved": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz",
      "integrity": "sha512-Wu1VHeILBK8KAWJUAiSZQX94GmOE45Rg6/538fKwiloUu21KncEkYGPqob2oSZ5mUT73vLGrHQjKw3KMPwfDzg==",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/is-odd": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz",
      "integrity": "sha512-CQpnWPrDwmP1+SMHXZhtLtJv90yiyVfluGsX5iNCVkrhQtU3TQHsUWPG9wkdk9Lgd5yNpAg9jQEo90CBaXgWMA==",
      "dependencies": {
        "is-number": "^6.0.0"
      },
      "engines": {
        "node": ">=4"
      }
    }
  }
}

and unlike the package-lock.json does not have a dependency key.

I guess the fix for this immediate problem is something like this:

diff --git a/cve_bin_tool/parsers/javascript.py b/cve_bin_tool/parsers/javascript.py
index 730bb375..3d1ab3bc 100644
--- a/cve_bin_tool/parsers/javascript.py
+++ b/cve_bin_tool/parsers/javascript.py
@@ -24,7 +24,7 @@ class JavascriptParser(Parser):
             if vendor is not None:
                 yield from vendor
             # Now process dependencies
-            for i in data["dependencies"]:
+            for i in data.get("dependencies", ()):
                 # To handle @actions/<product>: lines, extract product name from line
                 product = i.split("/")[1] if "/" in i else i
                 # Handle different formats. Either <product> : <version> or

but it might be wrong that .package-lock.json is processed like a package-lock.json, in here:

valid_files = {
"pom.xml": JavaParser,
"package-lock.json": JavascriptParser,
"Cargo.lock": RustParser,
"renv.lock": RParser,
"requirements.txt": PythonRequirementsParser,
"go.mod": GoParser,
"PKG-INFO: ": PythonParser,
"METADATA: ": PythonParser,
"Gemfile.lock": RubyParser,
"Package.resolved": SwiftParser,
"composer.lock": PhpParser,
"cpanfile": PerlParser,
}
def parse(filename, output, cve_db, logger):
for file in list(valid_files.keys()):
if file in output:
parser = valid_files[file](cve_db, logger)
yield from parser.run_checker(filename)
it is configured that package-lock.json must be parsed with JavascriptParser, but since .package-lock.json is a partial match on the filename, it is also processed with JavascriptParser - this might not be intentional behaviour.

Version/platform info

Version of CVE-bin-tool( e.g. output of cve-bin-tool --version):
Installed from pypi or github?

current main branch ef38dba

The nodejs project from the example was created with

> npm version
{
  npm: '8.19.3',
  node: '16.19.0',
  v8: '9.4.146.26-node.24',
  uv: '1.43.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.18.1',
  modules: '93',
  nghttp2: '1.47.0',
  napi: '8',
  llhttp: '6.0.10',
  openssl: '1.1.1t',
  cldr: '41.0',
  icu: '71.1',
  tz: '2022f',
  unicode: '14.0'
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions