Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NodeJS package-lock.json SBOM libraries list inconsistent #5532

Closed
1 of 2 tasks
DmitriyLewen opened this issue Nov 7, 2023 Discussed in #5522 · 11 comments
Closed
1 of 2 tasks

NodeJS package-lock.json SBOM libraries list inconsistent #5532

DmitriyLewen opened this issue Nov 7, 2023 Discussed in #5522 · 11 comments
Assignees
Labels
kind/bug Categorizes issue or PR as related to a bug. scan/vulnerability Issues relating to vulnerability scanning
Milestone

Comments

@DmitriyLewen
Copy link
Contributor

Discussed in #5522

Originally posted by OfirSandak November 6, 2023

Description

I want to report an issue related to Trivy filesystem scan when generating CycloneDX SBOM from package-lock.json. The problem arises when running the scan multiple times, as it returns different libraries with each run.

Upon investigation, the root cause of this inconsistency appears to be the presence of two instances of a library in package-lock.json, one with "dev": true and another without. The issue lies within the go-dep-parser package. In the Node.js npm parser, the dependencies map in package-lock.json is unmarshaled into a slice. During this process, any duplicate libraries are removed. However, the first instance of a library is kept after deduplication. Since the map unmarshaling is not in order, the first instance of the library can be either with or without "dev": true.

In the Trivy local scan, the dev libraries are removed at the excludeDevDeps function in pkg/scanner/local/scan.go. Consequently, this leads to different results for the same package-lock.json file.

Desired Behavior

Runs should be consistent, ensuring that libraries with an instance of "dev": false always supersede any instance with "dev": true.

Actual Behavior

The inconsistency arises because each run produces different results, depending on which library instance is first unmarshaled from the package-lock.json file

Reproduction Steps

Running this command:

trivy fs --scanners license --license-full --license-confidence-level 0.4 --format cyclonedx package-lock.json

Example package-lock.json:
{
  "name": "store",
  "version": "1.13.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "rs": {
      "version": "3.0.0",
      "resolved": "https://someothersite.com/repository/rs-npm-group/rs/-/rs-3.0.0.tgz",
      "integrity": "sha512-EUAyP5UHU5hxF8VPT0LKfW8gjYLshq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==",
      "dev": true,
      "requires": {
        "readable-stream": "^3.0.1"
      },
      "dependencies": {
        "readable-stream": {
          "version": "3.6.0",
          "resolved": "https://someothersite.com/repository/ps-npm-group/readable-stream/-/readable-stream-3.6.0.tgz",
          "integrity": "sha512-BViHy7LKeVz4oNnkcLJ+lVSL6dvpiFeX6/d3oSH8zCW7UxP2oncdhk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
          "dev": true,
          "requires": {
            "inherits": "^2.0.3",
            "string_decoder": "^1.1.1",
            "util-deprecate": "^1.0.1"
          }
        },
        "safe-buffer": {
          "version": "5.2.0",
          "resolved": "https://someothersite.com/repository/ps-npm-group/safe-buffer/-/safe-buffer-5.2.0.tgz",
          "integrity": "sha512-fZEwUGbVV7kouZs1jCdMfLdt95hdIv0ZeHg6L7qPeciMZhsZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
          "dev": true
        },
        "string_decoder": {
          "version": "1.3.0",
          "resolved": "https://someothersite.com/repository/ps-npm-group/string_decoder/-/string_decoder-1.3.0.tgz",
          "integrity": "sha512-hkRX8U1WjJFd8LVDJ2yQ/wWgWxaopEsABU1XfkM8A+j0s+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
          "dev": true,
          "requires": {
            "safe-buffer": "~5.2.0"
          }
        }
      }
    },
    "sorted-union-stream": {
      "version": "2.1.3",
      "bundled": true,
      "dev": true,
      "requires": {
        "from2": "^1.3.0",
        "stream-iterate": "^1.1.0"
      },
      "dependencies": {
        "from2": {
          "version": "1.3.0",
          "bundled": true,
          "dev": true,
          "requires": {
            "inherits": "~2.0.1",
            "readable-stream": "~1.1.10"
          }
        },
        "isarray": {
          "version": "0.0.1",
          "bundled": true,
          "dev": true
        },
        "readable-stream": {
          "version": "1.1.14",
          "bundled": true,
          "dev": true,
          "requires": {
            "core-util-is": "~1.0.0",
            "inherits": "~2.0.1",
            "isarray": "0.0.1",
            "string_decoder": "~0.10.x"
          }
        },
        "string_decoder": {
          "version": "0.10.31",
          "bundled": true,
          "dev": true
        }
      }
    },
    "string_decoder": {
      "version": "0.10.31",
      "resolved": "https://somesite.com:4873/string_decoder/-/string_decoder-0.10.31.tgz",
      "integrity": "sha1-YuIDvEF2bGwoyfYfEfMB2rHFMS+pQ="
    }
  }
}

Sometimes the SBOM results with no library:

{
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuid:acc20020-5aa2-4697-99e4-9e6f5ae38d39",
  "version": 1,
  "metadata": {
    "timestamp": "2023-11-06T10:22:06+00:00",
    "tools": [
      {
        "vendor": "aquasecurity",
        "name": "trivy",
        "version": "0.44.1"
      }
    ],
    "component": {
      "bom-ref": "a8432caf-eb70-4d5c-8367-4ad4d511d9fb",
      "type": "application",
      "name": "package-lock.json",
      "properties": [
        {
          "name": "aquasecurity:trivy:SchemaVersion",
          "value": "2"
        }
      ]
    }
  },
  "components": [],
  "dependencies": [
    {
      "ref": "a8432caf-eb70-4d5c-8367-4ad4d511d9fb",
      "dependsOn": []
    }
  ],
  "vulnerabilities": []
}

Sometime with SBOM results containing string_decoder library:

{
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuid:9584412b-e641-4d28-b8bd-a3210fa912b2",
  "version": 1,
  "metadata": {
    "timestamp": "2023-11-06T10:22:05+00:00",
    "tools": [
      {
        "vendor": "aquasecurity",
        "name": "trivy",
        "version": "0.44.1"
      }
    ],
    "component": {
      "bom-ref": "6c4a5ce3-6c04-442d-8713-eeba498a987e",
      "type": "application",
      "name": "package-lock.json",
      "properties": [
        {
          "name": "aquasecurity:trivy:SchemaVersion",
          "value": "2"
        }
      ]
    }
  },
  "components": [
    {
      "bom-ref": "16c041e0-974a-401a-83e5-38fcaa4dea9f",
      "type": "application",
      "name": "package-lock.json",
      "properties": [
        {
          "name": "aquasecurity:trivy:Class",
          "value": "lang-pkgs"
        },
        {
          "name": "aquasecurity:trivy:Type",
          "value": "npm"
        }
      ]
    },
    {
      "bom-ref": "pkg:npm/[email protected]",
      "type": "library",
      "name": "string_decoder",
      "version": "0.10.31",
      "purl": "pkg:npm/[email protected]",
      "properties": [
        {
          "name": "aquasecurity:trivy:PkgID",
          "value": "[email protected]"
        },
        {
          "name": "aquasecurity:trivy:PkgType",
          "value": "npm"
        }
      ]
    }
  ],
  "dependencies": [
    {
      "ref": "16c041e0-974a-401a-83e5-38fcaa4dea9f",
      "dependsOn": [
        "pkg:npm/[email protected]"
      ]
    },
    {
      "ref": "6c4a5ce3-6c04-442d-8713-eeba498a987e",
      "dependsOn": [
        "16c041e0-974a-401a-83e5-38fcaa4dea9f"
      ]
    },
    {
      "ref": "pkg:npm/[email protected]",
      "dependsOn": []
    }
  ],
  "vulnerabilities": []
}

Target

Filesystem

Scanner

None

Output Format

CycloneDX

Mode

Standalone

Debug Output

trivy fs --scanners license --license-full --license-confidence-level 0.4 --format cyclonedx package-lock.json --debug
2023-11-06T12:25:49.045+0200	DEBUG	["cyclonedx" "spdx" "spdx-json" "github"] automatically enables '--list-all-pkgs'.
2023-11-06T12:25:49.045+0200	DEBUG	Severities: ["UNKNOWN" "LOW" "MEDIUM" "HIGH" "CRITICAL"]
2023-11-06T12:25:49.046+0200	DEBUG	Ignore statuses	{"statuses": null}
2023-11-06T12:25:49.053+0200	DEBUG	cache dir:  /Users/osandak/Library/Caches/trivy
2023-11-06T12:25:49.053+0200	INFO	Full license scanning is enabled
2023-11-06T12:25:49.054+0200	DEBUG	Walk the file tree rooted at 'package-lock.json' in parallel
2023-11-06T12:25:49.055+0200	INFO	To collect the license information of packages in "package-lock.json", "npm install" needs to be performed beforehand
2023-11-06T12:25:49.055+0200	WARN	Cannot resolve the version: inherits@^2.0.3
2023-11-06T12:25:49.055+0200	WARN	Cannot resolve the version: util-deprecate@^1.0.1
2023-11-06T12:25:49.055+0200	WARN	Cannot resolve the version: stream-iterate@^1.1.0
2023-11-06T12:25:49.055+0200	WARN	Cannot resolve the version: inherits@~2.0.1
2023-11-06T12:25:49.055+0200	WARN	Cannot resolve the version: inherits@~2.0.1
2023-11-06T12:25:49.055+0200	WARN	Cannot resolve the version: core-util-is@~1.0.0
2023-11-06T12:25:49.062+0200	DEBUG	OS is not detected.
{
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuid:0da5a52d-74ed-41a5-9e7e-dd865bc6ab74",
  "version": 1,
  "metadata": {
    "timestamp": "2023-11-06T10:25:49+00:00",
    "tools": [
      {
        "vendor": "aquasecurity",
        "name": "trivy",
        "version": "0.44.1"
      }
    ],
    "component": {
      "bom-ref": "a9f6856e-a0b0-439f-9825-e64ede1ba7d8",
      "type": "application",
      "name": "package-lock.json",
      "properties": [
        {
          "name": "aquasecurity:trivy:SchemaVersion",
          "value": "2"
        }
      ]
    }
  },
  "components": [],
  "dependencies": [
    {
      "ref": "a9f6856e-a0b0-439f-9825-e64ede1ba7d8",
      "dependsOn": []
    }
  ],
  "vulnerabilities": []
}

Operating System

macOS 13.6

Version

trivy --version
Version: 0.44.1
Vulnerability DB:
  Version: 2
  UpdatedAt: 2023-11-01 06:23:05.358944701 +0000 UTC
  NextUpdate: 2023-11-01 12:23:05.358944401 +0000 UTC
  DownloadedAt: 2023-11-01 10:33:08.688297 +0000 UTC
Java DB:
  Version: 1
  UpdatedAt: 2023-11-05 01:04:21.6435653 +0000 UTC
  NextUpdate: 2023-11-08 01:04:21.6435647 +0000 UTC
  DownloadedAt: 2023-11-05 10:39:11.828838 +0000 UTC

Checklist

@DmitriyLewen DmitriyLewen added kind/bug Categorizes issue or PR as related to a bug. scan/vulnerability Issues relating to vulnerability scanning labels Nov 7, 2023
@DmitriyLewen DmitriyLewen self-assigned this Nov 7, 2023
@DmitriyLewen
Copy link
Contributor Author

Hello @OfirSandak
Can you write steps to create your example file?
I tried to get the same result, but npm seems to resolve this case:

/npm_app # npm install --save-dev [email protected]

added 2 packages, and audited 3 packages in 2s

/npm_app # npm install --save [email protected]

up to date, audited 3 packages in 1s

/npm_app # npm i --lockfile-version 1
npm WARN Converting lock file (package-lock.json) from v3 -> v1 

up to date, audited 3 packages in 1s

/npm_app # cat package-lock.json 
{
  "name": "npm_app",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "debug": {
      "version": "2.6.9",
      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
      "dev": true,
      "requires": {
        "ms": "2.0.0"
      }
    },
    "ms": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
    }
  }
}


@OfirSandak
Copy link

OfirSandak commented Nov 8, 2023

Hi @DmitriyLewen
I came across this example on an existing app, I cannot be sure how it was created (it might be even manually edited), but I do know it was created on an old npm, v8 I assume.
From npm documentation it seems this format is legit, having the dependencies of a dependency exactly as at the top level, so the package-lock.json is valid.
I cannot share the original package-lock.json, but I edit it so I can share an example having the same principal issue:

{
  "name": "store",
  "version": "1.13.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "rs": {
      "version": "3.0.0",
      "resolved": "https://someothersite.com/repository/rs-npm-group/rs/-/rs-3.0.0.tgz",
      "integrity": "sha512-EUAyP5UHU5hxF8VPT0LKfW8gjYLshq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==",
      "dev": true,
      "requires": {
        "readable-stream": "^3.0.1"
      },
      "dependencies": {
        "readable-stream": {
          "version": "3.6.0",
          "resolved": "https://someothersite.com/repository/ps-npm-group/readable-stream/-/readable-stream-3.6.0.tgz",
          "integrity": "sha512-BViHy7LKeVz4oNnkcLJ+lVSL6dvpiFeX6/d3oSH8zCW7UxP2oncdhk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
          "dev": true,
          "requires": {
            "inherits": "^2.0.3",
            "string_decoder": "^1.1.1",
            "util-deprecate": "^1.0.1"
          }
        },
        "safe-buffer": {
          "version": "5.2.0",
          "resolved": "https://someothersite.com/repository/ps-npm-group/safe-buffer/-/safe-buffer-5.2.0.tgz",
          "integrity": "sha512-fZEwUGbVV7kouZs1jCdMfLdt95hdIv0ZeHg6L7qPeciMZhsZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
          "dev": true
        },
        "string_decoder": {
          "version": "1.3.0",
          "resolved": "https://someothersite.com/repository/ps-npm-group/string_decoder/-/string_decoder-1.3.0.tgz",
          "integrity": "sha512-hkRX8U1WjJFd8LVDJ2yQ/wWgWxaopEsABU1XfkM8A+j0s+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
          "dev": true,
          "requires": {
            "safe-buffer": "~5.2.0"
          }
        }
      }
    },
    "sorted-union-stream": {
      "version": "2.1.3",
      "bundled": true,
      "dev": true,
      "requires": {
        "from2": "^1.3.0",
        "stream-iterate": "^1.1.0"
      },
      "dependencies": {
        "from2": {
          "version": "1.3.0",
          "bundled": true,
          "dev": true,
          "requires": {
            "inherits": "~2.0.1",
            "readable-stream": "~1.1.10"
          }
        },
        "isarray": {
          "version": "0.0.1",
          "bundled": true,
          "dev": true
        },
        "readable-stream": {
          "version": "1.1.14",
          "bundled": true,
          "dev": true,
          "requires": {
            "core-util-is": "~1.0.0",
            "inherits": "~2.0.1",
            "isarray": "0.0.1",
            "string_decoder": "~0.10.x"
          }
        },
        "string_decoder": {
          "version": "0.10.31",
          "bundled": true,
          "dev": true
        }
      }
    },
    "string_decoder": {
      "version": "0.10.31",
      "resolved": "https://somesite.com:4873/string_decoder/-/string_decoder-0.10.31.tgz",
      "integrity": "sha1-YuIDvEF2bGwoyfYfEfMB2rHFMS+pQ="
    }
  }
}

@DmitriyLewen
Copy link
Contributor Author

I created image containing npm v8 and your package-lock.json file:

FROM node:alpine3.15

COPY ./package-lock.json /app/package-lock.json

npm can't resolve this file:

/app # npm ls --package-lock-only
[email protected] /app
`-- (empty)

npm i --package-lock-only command should correct package-lock.json file - https://stackoverflow.com/a/57867531

I don't have package.json file for this project to check this.
Can you test this command?

@sapirif
Copy link

sapirif commented Nov 30, 2023

Hey - Any news about this issue?

@DmitriyLewen
Copy link
Contributor Author

Hello @sapirif
I wait response to make sure this lock file is correct for npm.
If you have another example with reproduce steps - please send it to me.

@sapirif
Copy link

sapirif commented Dec 5, 2023

I will give you an example -
package.json

I used this package json - and generated lock file with this command: npm install --package-lock-only
npm version 10.2.0
and I this lock file -
package-lock.json

after running trivy twice with this command: trivy fs --format cyclonedx package-lock.json
I got 2 different result:
libs.txt
libs2.txt

checking "components" part - got a diff in packages -
in the first one 159 from type library
In the second one 165.

Moreover we get some libraries that are not similar in those 2 files:

In libs but not in lib2
{'bcrypt-pbkdf', 'json-schema-traverse', 'mime', 'safe-buffer', 'safer-buffer'}

In lib2 but not in lib
{'ajv',
'assert-plus',
'colors',
'core-util-is',
'debug',
'extend',
'forever-agent',
'form-data',
'tunnel-agent',
'unpipe',
'verror'}

Hope this will be enough details

@DmitriyLewen
Copy link
Contributor Author

Thank you!

I'm currently working on another task. When I have time, I’ll check the example and write to you.

@DmitriyLewen
Copy link
Contributor Author

Hello everyone!
Thanks for your help and examples.

Created aquasecurity/go-dep-parser#280 to fix this problem.

@OfirSandak
Copy link

Hi @DmitriyLewen, latest Trivy version released last week doesn't include this fix, is it possible to update Trivy to use go-dep-parser latest version?
Thank you

@knqyf263 knqyf263 added this to the v0.49.0 milestone Jan 3, 2024
@knqyf263
Copy link
Collaborator

knqyf263 commented Jan 3, 2024

#5837 will be included in v0.49.0.

@DmitriyLewen
Copy link
Contributor Author

The changes have been merged into main branch and will be included in the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Categorizes issue or PR as related to a bug. scan/vulnerability Issues relating to vulnerability scanning
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants