anchore / syft

CLI tool and library for generating a Software Bill of Materials from container images and filesystems
Apache License 2.0
6.29k stars 578 forks source link

Conan cataloger: distinquish normal and build requirements - might be relevant for other catalogers as well (e.g. NPM) #3386

Open jngrb opened 4 weeks ago

jngrb commented 4 weeks ago

What would you like to be added:

The Conan cataloger #1083 which indexes conan.lock files (conan v1 or conan v2 #2461) should distinquish regular requirements and build requirements with a certain CycloneDX attribute, e.g.

cdx:composer:package:isDevRequirement

as specified here:

https://github.com/CycloneDX/cyclonedx-property-taxonomy/blob/main/cdx/composer.md

And for SPDX, the relationship type should be set.

Currently, both dependencies of both requirements types are listed indistinguishable.

(My primary use case is Conan v1 and v2 and the CycloneDX format.)

Specific problem / bug:

When a certain Conan recipe is both a requirement and a build requirement, generating the SBOM via syft results in duplicated entries. As an effect, the produced SBOM file cannot be loaded anymore in other applications due to a cyclonedx.exception.model.UnknownComponentDependencyException.

Why is this needed:

The goal is a final BOM can be parsed for "productive" dependencies (usually deployed to consumers) and "build tool" requirements (only part of the build environment).

Also to exception for duplicated entries should be avoided.

Additional context:

Other cataloger do this for NPM as well: cyclonedx-node-npm already does this and Yarn intends to do it as well: CycloneDX/cyclonedx-node-yarn#51 - however, they have their own property cdx:npm:package:development

But in syft, the NPM cataloger ignores the "devDependencies" flag both relation ship types end up in the SBOM without being distinquished - just as for Conan.

An alternative strategy might be that there is an global option (or CLI flag) to include build/dev requirements (or not) - in the same ways the glob parameter could be made configurable for Conan, cf. #1854

Minimal example:

Conan file:

from conan import ConanFile

class ExampleOpenSsslRecipe(ConanFile):
    settings = "os", "compiler", "build_type", "arch"
    generators = "CMakeToolchain", "CMakeDeps"

    def requirements(self):
        # we need the openssl libraries during runtime
        # to load and process cryptographic keys
        self.requires("openssl/3.2.1")

    def build_requirements(self):
        # we need openssl.exe during build process
        # to generate cryptographic keys
        self.tool_requires("openssl/3.2.1")

Using Conan v1 and using a dummy cross-compile environment, conan install -pr:h default -pr:b default . produces the conan.lock file attached. (My real use case is a much more complicated cross-compilation where the build and host profiles differ significantly.)

Using syft scan . I get the sbom json file attached. This file, I cannot upload e.g. to DependencyTrack as interpreting it fails with the mentioned exceptions.

minimal_sbom_example.zip

jngrb commented 4 weeks ago

There is a relationship to "relationships in SBOMS" #572 and likely to "duplicated NPM entries" #2559

kzantow commented 3 weeks ago

I think it's a great idea to be able to appropriately identify relationships as development/build/test/etc. vs. those included at runtime. You've referenced the right issues already (another is #3130).

I believe the correct way to do this is to define new relationship types, probably analogous to those defined in SPDX for build-time dependencies and perhaps other scopes as appropriate, and update the catalogers to return appropriate relationships to these dependencies. However, this does not map nicely to CycloneDX -- since this is a component property. What happens in the event that there are multiple instances of the same package with different qualifiers? Is there some way to model this in CycloneDX in a way that would support multiple components and each has the properties appropriately set without resulting in duplicate packages? Any suggestions how to handle this consistently would be much appreciated!