From 66ca7653f3803f30589c4e9be99b8c6ed8ce50e8 Mon Sep 17 00:00:00 2001 From: Alexey Ovchinnikov Date: Sun, 8 Dec 2024 13:11:17 -0600 Subject: [PATCH] SPDX restructuring: initial step This commit builds on top of proposed SPDX support and addresses the following: * simplifies merge logic to align it with design in https://github.com/konflux-ci/architecture/pull/213; * adjusts the model to make it work with Syft generated SPDX Sboms; * adds tests for some of existing and some new SPDX-CyDX handling and merging cases. This is not the final form and more work still has to be done: * several important test cases are pending; * CyDX SBOM has to be amended to better fit into the new structure; * Decisions need to be additionally documented within the code; * This commit and its parent must be split into several parts to simplify repository history. Co-authored-by: Jindrich Luza Signed-off-by: Alexey Ovchinnikov --- cachi2/core/models/property_semantics.py | 125 +- cachi2/core/models/sbom.py | 204 +- cachi2/core/utils.py | 7 +- cachi2/interface/cli.py | 23 +- tests/unit/data/alpine.pretty.json | 2514 +++++++++++++++++ tests/unit/data/sboms/cachi2.bom.spdx.json | 2 +- tests/unit/data/sboms/merged.bom.spdx.json | 2 +- ...thing.more.simple.0.100.0.spdx.pretty.json | 112 + .../something.simple0.100.0.spdx.pretty.json | 87 + tests/unit/models/test_sbom.py | 40 +- tests/unit/test_cli.py | 2 +- tests/unit/test_merge_spdx.py | 776 ++--- 12 files changed, 3212 insertions(+), 682 deletions(-) create mode 100644 tests/unit/data/alpine.pretty.json create mode 100644 tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json create mode 100644 tests/unit/data/something.simple0.100.0.spdx.pretty.json diff --git a/cachi2/core/models/property_semantics.py b/cachi2/core/models/property_semantics.py index 6349b249d..6261b9a77 100644 --- a/cachi2/core/models/property_semantics.py +++ b/cachi2/core/models/property_semantics.py @@ -1,12 +1,12 @@ import functools from dataclasses import dataclass, field from itertools import groupby -from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Tuple +from typing import TYPE_CHECKING, Iterable, Optional if TYPE_CHECKING: from typing_extensions import Self, assert_never -from cachi2.core.models.sbom import Component, Property, SPDXPackage, SPDXRelation +from cachi2.core.models.sbom import Component, Property def merge_component_properties(components: Iterable[Component]) -> list[Component]: @@ -101,124 +101,3 @@ def merge(self, other: "Self") -> "Self": pip_package_binary=self.pip_package_binary or other.pip_package_binary, bundler_package_binary=self.bundler_package_binary or other.bundler_package_binary, ) - - -def merge_relationships( - relationships_list: List[List[SPDXRelation]], doc_ids: List[str], packages: List[SPDXPackage] -) -> Tuple[List[SPDXRelation], List[SPDXPackage]]: - """Merge SPDX relationships. - - Function takes relationships lists, list of spdx document ids and unified list of packages. - For all relationships lists, map and inverse map of relations are created. - These maps are used to find root elements of the SPDX document. - - For relationhips lists, map and inverse map of relations are created. SPDX document usually - contains root package containing all real packages. Root element is found by searching - through map and inverse map of relationships. Element which has entry in map containing - other elements and has entry in inverse map containing entry pointing to root element is - considered as root element. - - packages are searched in the relationships and their ID is stored as middle element. - """ - - def map_relationships( - relationships: List[SPDXRelation], - ) -> Tuple[Dict[str, List[str]], Dict[str, str]]: - """Return (map and inverse map) for given relationships. - - Map is where key is SPDXID of element in relationship which is refered by spdxElementId - and value is list of elements refered by relatedSpdxElement in the relationship with the - element. - Inverse map is opposite of map where key is relatedSpdxElement and value is spdxElementId. - """ - relations_map: Dict[str, List[str]] = {} - inverse_map: Dict[str, str] = {} - - for rel in relationships: - spdx_id, related_spdx = rel.spdxElementId, rel.relatedSpdxElement - relations_map.setdefault(spdx_id, []).append(related_spdx) - inverse_map[related_spdx] = spdx_id - - return relations_map, inverse_map - - def process_relation( - rel: SPDXRelation, - doc_main: Optional[str], - doc_other: Optional[str], - root_package_main: str, - root_package_other: Optional[str], - merged_relationships: List[SPDXRelation], - ) -> None: - """Process a single SPDX relationship. - - Add relatationship to merged relationships list while replacing spdxElementId and - relatedSpdxElement with id of primary root package if original elements refers to - other root package. - Relationship is added only if it refers to package in the list of packages. - """ - new_rel = SPDXRelation( - spdxElementId=( - root_package_main if rel.spdxElementId == root_package_other else rel.spdxElementId - ), - relatedSpdxElement=( - doc_main if rel.relatedSpdxElement == root_package_other else rel.relatedSpdxElement - ), - relationshipType=rel.relationshipType, - ) - if new_rel.spdxElementId == root_package_other: - new_rel.spdxElementId = root_package_main - if new_rel.spdxElementId in package_ids or new_rel.relatedSpdxElement in package_ids: - merged_relationships.append(new_rel) - - package_ids = {pkg.SPDXID for pkg in packages} - _packages = packages[:] - maps = [] - inv_maps = [] - root_package_ids = [] - for relationships in relationships_list: - _map, inv_map = map_relationships(relationships) - maps.append(_map) - inv_maps.append(inv_map) - - for _map, _inv_map, doc_id in zip(maps, inv_maps, doc_ids): - root_package_id = next((r for r, c in _map.items() if _inv_map.get(r) == doc_id), None) - root_package_ids.append(root_package_id) - - merged_relationships = [] - - root_package_main = root_package_ids[0] - if not root_package_main: - _packages.append( - SPDXPackage( - SPDXID="SPDXRef-DocumentRoot-File-", - name="", - ) - ) - root_package_main = "SPDXRef-DocumentRoot-File-" - merged_relationships.append( - SPDXRelation( - spdxElementId=doc_ids[0], - relatedSpdxElement=root_package_main, - relationshipType="DESCRIBES", - ) - ) - - doc_main = doc_ids[0] - - for relationships, doc_id, root_package_id in zip( - relationships_list, doc_ids, root_package_ids - ): - for rel in relationships: - process_relation( - rel, doc_main, doc_id, root_package_main, root_package_id, merged_relationships - ) - - # Remove root packages of other elements from the list of packages - for _root_package in root_package_ids[1:]: - found_root_packages: List[Optional[SPDXPackage]] = [ - x for x in _packages if x.SPDXID == _root_package - ] - root_package: Optional[SPDXPackage] = (found_root_packages or [None])[0] - if root_package: - _packages.pop(_packages.index(root_package)) - return merged_relationships, _packages diff --git a/cachi2/core/models/sbom.py b/cachi2/core/models/sbom.py index 1e5cdb68f..3f3c929e0 100644 --- a/cachi2/core/models/sbom.py +++ b/cachi2/core/models/sbom.py @@ -1,6 +1,9 @@ import datetime import hashlib import json +from collections import defaultdict +from functools import cached_property +from pathlib import Path from typing import Annotated, Any, Dict, Iterable, Literal, Optional, Union from urllib.parse import urlparse @@ -8,6 +11,7 @@ from packageurl import PackageURL from cachi2.core.models.validators import unique_sorted +from cachi2.core.utils import first PropertyName = Literal[ "cachi2:bundler:package:binary", @@ -135,7 +139,7 @@ def to_spdx(self, doc_namespace: str) -> "SPDXSbom": for prop in component.properties: annotations.append( SPDXPackageAnnotation( - annotator="Tool:cachi2:jsonencoded", + annotator="Tool: cachi2:jsonencoded", annotationDate=datetime.datetime.now().isoformat()[:-7] + "Z", annotationType="OTHER", comment=json.dumps( @@ -233,6 +237,16 @@ def __hash__(self) -> int: return hash((self.referenceLocator, self.referenceType, self.referenceCategory)) +class SPDXPackageExternalRefSecurity(SPDXPackageExternalRef): + """SPDX Package External Reference for category package-manager. + + Compliant to the SPDX specification: + https://spdx.github.io/spdx-spec/v2.3/package-information/#721-external-reference-field + """ + + referenceCategory: Literal["SECURITY"] + + class SPDXPackageExternalRefPackageManager(SPDXPackageExternalRef): """SPDX Package External Reference for category package-manager. @@ -256,14 +270,32 @@ class SPDXPackageExternalRefPackageManagerPURL( referenceType: Literal["purl"] +class SPDXPackageExternalRefSecurityPURL( + SPDXPackageExternalRefSecurity, SPDXPackageExternalRefReferenceLocatorURI +): + """SPDX Package External Reference for category package-manager and type purl. + + Compliant to the SPDX specification: + https://spdx.github.io/spdx-spec/v2.3/package-information/#721-external-reference-field + """ + + referenceCategory: Literal["SECURITY"] + referenceType: Literal["cpe23Type"] + + SPDXPackageExternalRefPackageManagerType = Annotated[ SPDXPackageExternalRefPackageManagerPURL, pydantic.Field(discriminator="referenceType"), ] +SPDXPackageExternalRefSecurityType = Annotated[ + SPDXPackageExternalRefSecurityPURL, + pydantic.Field(discriminator="referenceType"), +] + SPDXPackageExternalRefType = Annotated[ - Union[SPDXPackageExternalRefPackageManagerType,], + Union[SPDXPackageExternalRefPackageManagerType, SPDXPackageExternalRefSecurityType], pydantic.Field(discriminator="referenceCategory"), ] @@ -284,6 +316,43 @@ def __hash__(self) -> int: return hash((self.annotator, self.annotationDate, self.annotationType, self.comment)) +class SPDXChecksum(pydantic.BaseModel): + """A basic representation of a checksum entry.""" + + algorithm: str + checksumValue: str + + def __hash__(self) -> int: + return hash(self.algorithm + self.checksumValue) + + +class SPDXFile(pydantic.BaseModel): + """SPDX File. + + Compliant to the SPDX specification: + https://spdx.github.io/spdx-spec/v2.3/package-information/ + + An actual SPDX document generated from a directory or a container image + would usually contain "files" section. This section would contain file + entries of this shape. + """ + + SPDXID: Optional[str] = None + fileName: str + checksums: list[SPDXChecksum] = [] # TODO: flesh out proper cehcksums type + licenseConcluded: str = "NOASSERTION" + copyrightText: str = "" + comment: str = "" + + def __hash__(self) -> int: + return hash( + hash(self.SPDXID) + + hash(self.fileName) + + hash(self.licenseConcluded + self.copyrightText + self.comment) + + sum(hash(c) for c in self.checksums) + ) + + class SPDXPackage(pydantic.BaseModel): """SPDX Package. @@ -301,6 +370,16 @@ class SPDXPackage(pydantic.BaseModel): def __lt__(self, other: "SPDXPackage") -> bool: return (self.SPDXID or "") < (other.SPDXID or "") + def __hash__(self) -> int: + return hash( + hash(self.SPDXID) + + hash(self.name) + + hash(self.versionInfo) + + hash(self.downloadLocation) + + sum(hash(e) for e in self.externalRefs) + + sum(hash(a) for a in self.annotations) + ) + @staticmethod def _calculate_package_hash_from_dict(package_dict: Dict[str, Any]) -> str: return hashlib.sha256(json.dumps(package_dict, sort_keys=True).encode()).hexdigest() @@ -315,7 +394,7 @@ def _purls_validation( unique_purls_parts = set([(p.type, p.name, p.version) for p in parsed_purls]) if len(unique_purls_parts) > 1: raise ValueError( - "SPDXPackage includes multiple purls with different (type,name,version): " + "SPDXPackage includes multiple purls with different (type,name,version) tuple: " + f"{unique_purls_parts}" ) return refs @@ -377,6 +456,12 @@ class SPDXRelation(pydantic.BaseModel): relatedSpdxElement: str relationshipType: str + def __hash__(self) -> int: + return hash( + hash(self.spdxElementId + self.relatedSpdxElement + self.relationshipType) + + hash(self.comment) + ) + class SPDXSbom(pydantic.BaseModel): """Software bill of materials in the SPDX format. @@ -385,7 +470,9 @@ class SPDXSbom(pydantic.BaseModel): https://spdx.github.io/spdx-spec/v2.3 """ - model_config = pydantic.ConfigDict(extra="forbid") + # NOTE: The model is intentionally made non-strict for now because a strict model rejects + # SBOMs generated by Syft. It is unclear at the moment if additional preprocessing will + # be happening or desired. spdxVersion: Literal["SPDX-2.3"] = "SPDX-2.3" SPDXID: Literal["SPDXRef-DOCUMENT"] = "SPDXRef-DOCUMENT" @@ -395,8 +482,23 @@ class SPDXSbom(pydantic.BaseModel): creationInfo: SPDXCreationInfo packages: list[SPDXPackage] = [] + files: list[SPDXFile] = [] relationships: list[SPDXRelation] = [] + def __hash__(self) -> int: + return hash( + hash(self.name + self.documentNamespace) + + hash(SPDXCreationInfo) + + sum(hash(p) for p in self.packages) + + sum(hash(f) for f in self.files) + + sum(hash(r) for r in self.relationships) + ) + + @classmethod + def from_file(cls, path: Path) -> "SPDXSbom": + """Consume a SPDX json directly from a file.""" + return cls.model_validate_json(path.read_text()) + @staticmethod def deduplicate_spdx_packages(items: Iterable[SPDXPackage]) -> list[SPDXPackage]: """Deduplicate SPDX packages and merge external references. @@ -404,6 +506,7 @@ def deduplicate_spdx_packages(items: Iterable[SPDXPackage]) -> list[SPDXPackage] If package with same name and version is found multiple times in the list, merge external references of all the packages into one package. """ + # NOTE: keeping this implementation mostly intact for historical reasons. unique_items = {} for item in items: purls = [ @@ -411,11 +514,18 @@ def deduplicate_spdx_packages(items: Iterable[SPDXPackage]) -> list[SPDXPackage] ] if purls: keys = [PackageURL.from_string(purl) for purl in purls if purl] - purl_tnv = [(p.type, p.name, p.version) for p in keys][0] + # name can exist in mutiple namespaces, e.g. rand exists in both math and + # crypto, and must be distinguished between. + p = keys[0] + package_name = p.name + if p.namespace is not None: + package_name = p.namespace + "/" + p.name + purl_tnv = (p.type, package_name, p.version) else: purl_tnv = ("", item.name, item.versionInfo or "") if purl_tnv not in unique_items: + # TODO: model_copy? unique_items[purl_tnv] = SPDXPackage( SPDXID=item.SPDXID, name=item.name, versionInfo=item.versionInfo ) @@ -445,6 +555,86 @@ def _unique_packages(cls, packages: list[SPDXPackage]) -> list[SPDXPackage]: """Sort and de-duplicate components.""" return cls.deduplicate_spdx_packages(packages) + @cached_property + def root_id(self) -> str: + """Return the root_id of this SBOM.""" + direct_relationships, inverse_relationships = defaultdict(list), dict() + for rel in self.relationships: + direct_relationships[rel.spdxElementId].append(rel.relatedSpdxElement) + inverse_relationships[rel.relatedSpdxElement] = rel.spdxElementId + # noqa because the name is bound to make local intent clearer and first() call easier to + # follow. + unidirectionally_related_package = ( + lambda p: inverse_relationships.get(p) == self.SPDXID # noqa: E731 + ) + # Note: defaulting to top-level SPDXID is inherited from the original implementation. + # It is unclear if it is really needed, but is left around to match the precedent. + root_id = first(unidirectionally_related_package, direct_relationships, self.SPDXID) + return root_id + + # NOTE: having this as cached will cause trouble when sequentially + # constructing the object off of an empty state. + @property + def non_root_packages(self) -> list[SPDXPackage]: + """Return non-root packages.""" + return [p for p in self.packages if p.SPDXID != self.root_id] + + @staticmethod + def retarget_and_prune_relationships( + from_sbom: "SPDXSbom", + to_sbom: "SPDXSbom", + ) -> list[SPDXRelation]: + """Retarget and prune relationships.""" + out = [] + for r in from_sbom.relationships: + # Do a copy to ensure we are not pulling a carpet from underneath us: + new_rel = r.model_copy(deep=True) + if new_rel.spdxElementId == from_sbom.root_id: + new_rel.spdxElementId = to_sbom.root_id + if new_rel.relatedSpdxElement == from_sbom.root_id: + new_rel.spdxElementId = to_sbom.SPDXID + # Old top-level "DESCRIBES" must go: + if not ( + new_rel.relatedSpdxElement == from_sbom.root_id + and new_rel.relationshipType == "DESCRIBES" + ): + out.append(new_rel) + return out + + def __add__(self, other: Union["SPDXSbom", Sbom]) -> "SPDXSbom": + if isinstance(other, self.__class__): + # Packages are not going to be modified so it is OK to just pass references around. + merged_packages = self.packages + other.non_root_packages + # Relationships, on the other hand, are amended, so new + # relationships will be constructed. + # Further, identical relationships should be dropped. + # Deduplication based on building a set is considered safe because all + # fields of all elements are used to compute a hash. + # Just using set won't work satisfactory since that would shuffle relationships. + merged_relationships, seen_relationships = [], set() + processed_other = self.retarget_and_prune_relationships(from_sbom=other, to_sbom=self) + for r in self.relationships + processed_other: + if r not in seen_relationships: + seen_relationships.add(r) + merged_relationships.append(r) + # The same as packages: files are not modified, so keeping them as is. + # Identical file entries should be skipped. + merged_files = list(set(self.files + other.files)) + res = self.model_copy( + update={ + # At the moment of writing pydantic does not deem it necessary to + # validate updated fields because we should just trust them [1]. + "packages": self.deduplicate_spdx_packages(merged_packages), + "relationships": merged_relationships, + "files": merged_files, + }, + deep=True, + ) + return res + elif isinstance(other, Sbom): + return self + other.to_spdx(doc_namespace="NOASSERTION") + raise Exception("Something smart goes here") + def to_cyclonedx(self) -> Sbom: """Convert a SPDX SBOM to a CycloneDX SBOM.""" components = [] @@ -503,3 +693,7 @@ def to_cyclonedx(self) -> Sbom: components=components, metadata=Metadata(tools=tools), ) + + +# References +# [1] https://github.com/pydantic/pydantic/blob/6fa92d139a297a26725dec0a7f9b0cce912d6a7f/pydantic/main.py#L383 diff --git a/cachi2/core/utils.py b/cachi2/core/utils.py index 017181813..ad6415fd8 100644 --- a/cachi2/core/utils.py +++ b/cachi2/core/utils.py @@ -8,7 +8,7 @@ import sys from functools import cache from pathlib import Path -from typing import Callable, Iterable, Iterator, Optional, Sequence +from typing import Any, Callable, Iterable, Iterator, Optional, Sequence from cachi2.core.config import get_config from cachi2.core.errors import Cachi2Error @@ -195,3 +195,8 @@ def get_cache_dir() -> Path: except KeyError: cache_dir = Path.home().joinpath(".cache") return cache_dir.joinpath("cachi2") + + +def first(predicate: Callable, iterable: Iterable, fallback: Any) -> Any: + """Return the first match of predicate in iterable or fallback value.""" + return next((x for x in iterable if predicate(x)), fallback) diff --git a/cachi2/interface/cli.py b/cachi2/interface/cli.py index d19596d3a..fc3899f3a 100644 --- a/cachi2/interface/cli.py +++ b/cachi2/interface/cli.py @@ -8,7 +8,7 @@ import sys from itertools import chain from pathlib import Path -from typing import Any, Callable, List, Optional, Union, cast +from typing import Any, Callable, List, Optional, Union import pydantic import typer @@ -18,7 +18,7 @@ from cachi2.core.extras.envfile import EnvFormat, generate_envfile from cachi2.core.models.input import Flag, PackageInput, Request, parse_user_input from cachi2.core.models.output import BuildConfig -from cachi2.core.models.property_semantics import merge_component_properties, merge_relationships +from cachi2.core.models.property_semantics import merge_component_properties from cachi2.core.models.sbom import Sbom, SPDXSbom from cachi2.core.resolver import inject_files_post, resolve_packages, supported_package_managers from cachi2.core.rooted_path import RootedPath @@ -454,6 +454,7 @@ def merge_sboms( cyclonedx_sboms_to_merge.append(_sbom.to_cyclonedx()) else: cyclonedx_sboms_to_merge.append(_sbom) + # TODO: merging SBOMs should be done uniformly via "+" sbom: Union[Sbom, SPDXSbom] = Sbom( components=merge_component_properties( chain.from_iterable(s.components for s in cyclonedx_sboms_to_merge) @@ -467,23 +468,11 @@ def merge_sboms( else: spdx_sboms_to_merge.append(_sbom) - packages = chain.from_iterable(cast(SPDXSbom, s).packages for s in spdx_sboms_to_merge) - sbom = SPDXSbom( - spdxVersion="SPDX-2.3", - SPDXID="SPDXRef-DOCUMENT", - dataLicense="CC0-1.0", - name=sbom_name or cast(SPDXSbom, spdx_sboms_to_merge[0]).name, - documentNamespace="NOASSERTION", - creationInfo=cast(SPDXSbom, spdx_sboms_to_merge[0]).creationInfo, - packages=packages, - ) + sbom = sum(spdx_sboms_to_merge, start=spdx_sboms_to_merge[0]) + if sbom_name is not None: + sbom.name = sbom_name sbom.creationInfo.created = datetime.datetime.now().isoformat()[:-7] + "Z" - root_ids: List[str] = [s.SPDXID for s in spdx_sboms_to_merge] - sbom.relationships, sbom.packages = merge_relationships( - [s.relationships for s in spdx_sboms_to_merge], root_ids, sbom.packages - ) - sbom_json = sbom.model_dump_json(indent=2, by_alias=True, exclude_none=True) if output_sbom_file_name is not None: diff --git a/tests/unit/data/alpine.pretty.json b/tests/unit/data/alpine.pretty.json new file mode 100644 index 000000000..0c5e02c6a --- /dev/null +++ b/tests/unit/data/alpine.pretty.json @@ -0,0 +1,2514 @@ +{ + "spdxVersion": "SPDX-2.3", + "dataLicense": "CC0-1.0", + "SPDXID": "SPDXRef-DOCUMENT", + "name": "alpine", + "documentNamespace": "https://anchore.com/syft/image/alpine-23a16066-6f89-4a51-9c35-aa776bcc77d7", + "creationInfo": { + "licenseListVersion": "3.22", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-0.100.0" + ], + "created": "2024-12-11T00:58:09Z" + }, + "packages": [ + { + "name": "alpine-baselayout", + "SPDXID": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "versionInfo": "3.6.8-r0", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "GPL-2.0-only", + "copyrightText": "NOASSERTION", + "description": "Alpine base dir structure and init scripts", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine-baselayout:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine_baselayout:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/alpine-baselayout@3.6.8-r0?arch=x86_64&distro=alpine-3.21.0" + } + ] + }, + { + "name": "alpine-baselayout-data", + "SPDXID": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "versionInfo": "3.6.8-r0", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "GPL-2.0-only", + "copyrightText": "NOASSERTION", + "description": "Alpine base dir structure and init scripts", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-baselayout-data:alpine-baselayout-data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-baselayout-data:alpine_baselayout_data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_baselayout_data:alpine-baselayout-data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_baselayout_data:alpine_baselayout_data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-baselayout:alpine-baselayout-data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-baselayout:alpine_baselayout_data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_baselayout:alpine-baselayout-data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_baselayout:alpine_baselayout_data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine-baselayout-data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine_baselayout_data:3.6.8-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/alpine-baselayout-data@3.6.8-r0?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.21.0" + } + ] + }, + { + "name": "alpine-keys", + "SPDXID": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "versionInfo": "2.5-r0", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://alpinelinux.org", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "description": "Public keys for Alpine Linux packages", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-keys:alpine-keys:2.5-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-keys:alpine_keys:2.5-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_keys:alpine-keys:2.5-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_keys:alpine_keys:2.5-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine-keys:2.5-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine_keys:2.5-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/alpine-keys@2.5-r0?arch=x86_64&distro=alpine-3.21.0" + } + ] + }, + { + "name": "alpine-release", + "SPDXID": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "versionInfo": "3.21.0-r0", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://alpinelinux.org", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "description": "Alpine release data", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-release:alpine-release:3.21.0-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine-release:alpine_release:3.21.0-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_release:alpine-release:3.21.0-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine_release:alpine_release:3.21.0-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine-release:3.21.0-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:alpine:alpine_release:3.21.0-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/alpine-release@3.21.0-r0?arch=x86_64&upstream=alpine-base&distro=alpine-3.21.0" + } + ] + }, + { + "name": "apk-tools", + "SPDXID": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "versionInfo": "2.14.6-r2", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://gitlab.alpinelinux.org/alpine/apk-tools", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "GPL-2.0-only", + "copyrightText": "NOASSERTION", + "description": "Alpine Package Keeper - package manager for alpine", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:apk-tools:apk-tools:2.14.6-r2:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:apk-tools:apk_tools:2.14.6-r2:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:apk_tools:apk-tools:2.14.6-r2:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:apk_tools:apk_tools:2.14.6-r2:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:apk:apk-tools:2.14.6-r2:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:apk:apk_tools:2.14.6-r2:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/apk-tools@2.14.6-r2?arch=x86_64&distro=alpine-3.21.0" + } + ] + }, + { + "name": "busybox", + "SPDXID": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "versionInfo": "1.37.0-r8", + "supplier": "Person: Sören Tempel ", + "originator": "Person: Sören Tempel ", + "downloadLocation": "https://busybox.net/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "GPL-2.0-only", + "copyrightText": "NOASSERTION", + "description": "Size optimized toolbox of many common UNIX utilities", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:busybox:busybox:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/busybox@1.37.0-r8?arch=x86_64&distro=alpine-3.21.0" + } + ] + }, + { + "name": "busybox-binsh", + "SPDXID": "SPDXRef-Package-apk-busybox-binsh-79dd77b653445aa8", + "versionInfo": "1.37.0-r8", + "supplier": "Person: Sören Tempel ", + "originator": "Person: Sören Tempel ", + "downloadLocation": "https://busybox.net/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "GPL-2.0-only", + "copyrightText": "NOASSERTION", + "description": "busybox ash /bin/sh", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:busybox-binsh:busybox-binsh:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:busybox-binsh:busybox_binsh:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:busybox_binsh:busybox-binsh:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:busybox_binsh:busybox_binsh:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:busybox:busybox-binsh:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:busybox:busybox_binsh:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/busybox-binsh@1.37.0-r8?arch=x86_64&upstream=busybox&distro=alpine-3.21.0" + } + ] + }, + { + "name": "ca-certificates-bundle", + "SPDXID": "SPDXRef-Package-apk-ca-certificates-bundle-67dec00a55941450", + "versionInfo": "20241010-r0", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "(MPL-2.0 AND MIT)", + "copyrightText": "NOASSERTION", + "description": "Pre generated bundle of Mozilla certificates", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca-certificates-bundle:ca-certificates-bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca-certificates-bundle:ca_certificates_bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca_certificates_bundle:ca-certificates-bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca_certificates_bundle:ca_certificates_bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca-certificates:ca-certificates-bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca-certificates:ca_certificates_bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca_certificates:ca-certificates-bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca_certificates:ca_certificates_bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:mozilla:ca-certificates-bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:mozilla:ca_certificates_bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca:ca-certificates-bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ca:ca_certificates_bundle:20241010-r0:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/ca-certificates-bundle@20241010-r0?arch=x86_64&upstream=ca-certificates&distro=alpine-3.21.0" + } + ] + }, + { + "name": "libcrypto3", + "SPDXID": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "versionInfo": "3.3.2-r4", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://www.openssl.org/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "Apache-2.0", + "copyrightText": "NOASSERTION", + "description": "Crypto library from openssl", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libcrypto3:libcrypto3:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libcrypto3:libcrypto:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libcrypto:libcrypto3:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libcrypto:libcrypto:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/libcrypto3@3.3.2-r4?arch=x86_64&upstream=openssl&distro=alpine-3.21.0" + } + ] + }, + { + "name": "libssl3", + "SPDXID": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "versionInfo": "3.3.2-r4", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://www.openssl.org/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "Apache-2.0", + "copyrightText": "NOASSERTION", + "description": "SSL shared libraries", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libssl3:libssl3:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libssl3:libssl:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libssl:libssl3:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:libssl:libssl:3.3.2-r4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/libssl3@3.3.2-r4?arch=x86_64&upstream=openssl&distro=alpine-3.21.0" + } + ] + }, + { + "name": "musl", + "SPDXID": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "versionInfo": "1.2.5-r8", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://musl.libc.org/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "description": "the musl c library (libc) implementation", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl-libc:musl:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl_libc:musl:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl:musl:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/musl@1.2.5-r8?arch=x86_64&distro=alpine-3.21.0" + } + ] + }, + { + "name": "musl-utils", + "SPDXID": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "versionInfo": "1.2.5-r8", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://musl.libc.org/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "(MIT AND BSD-2-Clause AND GPL-2.0-or-later)", + "copyrightText": "NOASSERTION", + "description": "the musl c library (libc) implementation", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl-utils:musl-utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl-utils:musl_utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl_utils:musl-utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl_utils:musl_utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl-libc:musl-utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl-libc:musl_utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl:musl-utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:musl:musl_utils:1.2.5-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/musl-utils@1.2.5-r8?arch=x86_64&upstream=musl&distro=alpine-3.21.0" + } + ] + }, + { + "name": "scanelf", + "SPDXID": "SPDXRef-Package-apk-scanelf-5732e2d080a0a28c", + "versionInfo": "1.3.8-r1", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://wiki.gentoo.org/wiki/Hardened/PaX_Utilities", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "GPL-2.0-only", + "copyrightText": "NOASSERTION", + "description": "Scan ELF binaries for stuff", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:scanelf:scanelf:1.3.8-r1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/scanelf@1.3.8-r1?arch=x86_64&upstream=pax-utils&distro=alpine-3.21.0" + } + ] + }, + { + "name": "ssl_client", + "SPDXID": "SPDXRef-Package-apk-ssl-client-9894cb492b9e703b", + "versionInfo": "1.37.0-r8", + "supplier": "Person: Sören Tempel ", + "originator": "Person: Sören Tempel ", + "downloadLocation": "https://busybox.net/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "GPL-2.0-only", + "copyrightText": "NOASSERTION", + "description": "External ssl_client for busybox wget", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ssl-client:ssl-client:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ssl-client:ssl_client:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ssl_client:ssl-client:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ssl_client:ssl_client:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ssl:ssl-client:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ssl:ssl_client:1.37.0-r8:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/ssl_client@1.37.0-r8?arch=x86_64&upstream=busybox&distro=alpine-3.21.0" + } + ] + }, + { + "name": "zlib", + "SPDXID": "SPDXRef-Package-apk-zlib-cd1596a99504840a", + "versionInfo": "1.3.1-r2", + "supplier": "Person: Natanael Copa ", + "originator": "Person: Natanael Copa ", + "downloadLocation": "https://zlib.net/", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from APK DB: /lib/apk/db/installed", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "Zlib", + "copyrightText": "NOASSERTION", + "description": "A compression/decompression Library", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:zlib:zlib:1.3.1-r2:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:apk/alpine/zlib@1.3.1-r2?arch=x86_64&distro=alpine-3.21.0" + } + ] + }, + { + "name": "alpine", + "SPDXID": "SPDXRef-DocumentRoot-Image-alpine", + "versionInfo": "sha256:2c43f33bd1502ec7818bce9eea60e062d04eeadc4aa31cad9dabecb1e48b647b", + "supplier": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "checksums": [ + { + "algorithm": "SHA256", + "checksumValue": "2c43f33bd1502ec7818bce9eea60e062d04eeadc4aa31cad9dabecb1e48b647b" + } + ], + "externalRefs": [ + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:oci/alpine@sha256:2c43f33bd1502ec7818bce9eea60e062d04eeadc4aa31cad9dabecb1e48b647b?arch=amd64" + } + ], + "primaryPackagePurpose": "CONTAINER" + } + ], + "files": [ + { + "fileName": "/bin/busybox", + "SPDXID": "SPDXRef-File-bin-busybox-468f4889734362f5", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/alpine-release", + "SPDXID": "SPDXRef-File-etc-alpine-release-fd2f197c9c548c66", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-4a6a0840.rsa.pub-e31ca5e7df53db52", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5243ef4b.rsa.pub-dd82cc7a531a4f8a", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5261cecb.rsa.pub-8503eca0329855ac", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-6165ee59.rsa.pub-9fc2b76378071420", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/apk/keys/alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-61666e3f.rsa.pub-e174ab22f2beeb60", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/busybox-paths.d/busybox", + "SPDXID": "SPDXRef-File-etc-busybox-paths.d-busybox-3cbfe16761873575", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/crontabs/root", + "SPDXID": "SPDXRef-File-etc-crontabs-root-86d9785f3abff156", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/fstab", + "SPDXID": "SPDXRef-File-etc-fstab-b80c3cb56c980b08", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/group", + "SPDXID": "SPDXRef-File-etc-group-7db3625241f6856d", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/hostname", + "SPDXID": "SPDXRef-File-etc-hostname-e7d0d8adb0625ce4", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/hosts", + "SPDXID": "SPDXRef-File-etc-hosts-6ac577ecad2ec5b0", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/inittab", + "SPDXID": "SPDXRef-File-etc-inittab-4d8d5f0587154018", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/issue", + "SPDXID": "SPDXRef-File-etc-issue-b413295f2e1636b9", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/logrotate.d/acpid", + "SPDXID": "SPDXRef-File-etc-logrotate.d-acpid-e680a539c74e700d", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/modprobe.d/aliases.conf", + "SPDXID": "SPDXRef-File-etc-modprobe.d-aliases.conf-b29978812ba855fa", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/modprobe.d/blacklist.conf", + "SPDXID": "SPDXRef-File-etc-modprobe.d-blacklist.conf-b58b1a80d90b95b5", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/modprobe.d/i386.conf", + "SPDXID": "SPDXRef-File-etc-modprobe.d-i386.conf-f54933ed0cb86bd2", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/modprobe.d/kms.conf", + "SPDXID": "SPDXRef-File-etc-modprobe.d-kms.conf-bae009a41fd01a1d", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/modules", + "SPDXID": "SPDXRef-File-etc-modules-a3196be7d01a0aec", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/motd", + "SPDXID": "SPDXRef-File-etc-motd-4eb653645b7f13ee", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/network/if-up.d/dad", + "SPDXID": "SPDXRef-File-etc-network-if-up.d-dad-ae53711b4c2ae508", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/nsswitch.conf", + "SPDXID": "SPDXRef-File-etc-nsswitch.conf-668425e791126652", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/passwd", + "SPDXID": "SPDXRef-File-etc-passwd-52c8226245401a54", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/profile", + "SPDXID": "SPDXRef-File-etc-profile-773e11b623fa2206", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/profile.d/20locale.sh", + "SPDXID": "SPDXRef-File-etc-profile.d-20locale.sh-ff541b2c108c7e57", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/profile.d/README", + "SPDXID": "SPDXRef-File-etc-profile.d-README-22834df769d2095e", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/profile.d/color_prompt.sh.disabled", + "SPDXID": "SPDXRef-File-etc-profile.d-color-prompt.sh.disabled-96f77289dc1c6105", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/protocols", + "SPDXID": "SPDXRef-File-etc-protocols-2ebaf2d5275a87c3", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/secfixes.d/alpine", + "SPDXID": "SPDXRef-File-etc-secfixes.d-alpine-31f4ab357226cd60", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/securetty", + "SPDXID": "SPDXRef-File-etc-securetty-f5ddc6e8bf552536", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/services", + "SPDXID": "SPDXRef-File-etc-services-5e64bee7d0512520", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/shadow", + "SPDXID": "SPDXRef-File-etc-shadow-e52a006d3d1244db", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/shells", + "SPDXID": "SPDXRef-File-etc-shells-5f409797065e8a24", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/ssl/certs/ca-certificates.crt", + "SPDXID": "SPDXRef-File-etc-ssl-certs-ca-certificates.crt-860b9d53645feb47", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/ssl/ct_log_list.cnf", + "SPDXID": "SPDXRef-File-etc-ssl-ct-log-list.cnf-97ee0f53ad135fdd", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/ssl/ct_log_list.cnf.dist", + "SPDXID": "SPDXRef-File-etc-ssl-ct-log-list.cnf.dist-7386b7ea31c8254f", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/ssl/openssl.cnf", + "SPDXID": "SPDXRef-File-etc-ssl-openssl.cnf-9afb2be8c7429f0d", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/ssl/openssl.cnf.dist", + "SPDXID": "SPDXRef-File-etc-ssl-openssl.cnf.dist-70e74fc481bbd7b7", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/sysctl.conf", + "SPDXID": "SPDXRef-File-etc-sysctl.conf-c068f4c2abc469f7", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/etc/udhcpc/udhcpc.conf", + "SPDXID": "SPDXRef-File-etc-udhcpc-udhcpc.conf-378d389540b30911", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/lib/apk/db/installed", + "SPDXID": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/lib/ld-musl-x86_64.so.1", + "SPDXID": "SPDXRef-File-lib-ld-musl-x86-64.so.1-6e7e3004534b86d1", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/sbin/apk", + "SPDXID": "SPDXRef-File-sbin-apk-0c90571c31cc24d4", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/sbin/ldconfig", + "SPDXID": "SPDXRef-File-sbin-ldconfig-f058d85fa2770b4f", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/bin/getconf", + "SPDXID": "SPDXRef-File-usr-bin-getconf-cb10741d9c217d07", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/bin/getent", + "SPDXID": "SPDXRef-File-usr-bin-getent-d36d4602a8c0ad50", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/bin/iconv", + "SPDXID": "SPDXRef-File-usr-bin-iconv-b33e7a49b30565e7", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/bin/ldd", + "SPDXID": "SPDXRef-File-usr-bin-ldd-485cab4248b11e3f", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/bin/scanelf", + "SPDXID": "SPDXRef-File-usr-bin-scanelf-97db8aae69dc1643", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/bin/ssl_client", + "SPDXID": "SPDXRef-File-usr-bin-ssl-client-b4bab8e79035429e", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/engines-3/afalg.so", + "SPDXID": "SPDXRef-File-usr-lib-engines-3-afalg.so-51e3b429173363b7", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/engines-3/capi.so", + "SPDXID": "SPDXRef-File-usr-lib-engines-3-capi.so-2cac453818c05153", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/engines-3/loader_attic.so", + "SPDXID": "SPDXRef-File-usr-lib-engines-3-loader-attic.so-b2bd5535e09327d5", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/engines-3/padlock.so", + "SPDXID": "SPDXRef-File-usr-lib-engines-3-padlock.so-2230852154a764a9", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/libapk.so.2.14.0", + "SPDXID": "SPDXRef-File-usr-lib-libapk.so.2.14.0-4e2deeb47f39a10e", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/libcrypto.so.3", + "SPDXID": "SPDXRef-File-usr-lib-libcrypto.so.3-a36b11ef91e748da", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/libssl.so.3", + "SPDXID": "SPDXRef-File-usr-lib-libssl.so.3-69cc85b55482eba1", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/libz.so.1.3.1", + "SPDXID": "SPDXRef-File-usr-lib-libz.so.1.3.1-014a43ace0388eab", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/os-release", + "SPDXID": "SPDXRef-File-usr-lib-os-release-c36f73b65f306d73", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/ossl-modules/legacy.so", + "SPDXID": "SPDXRef-File-usr-lib-ossl-modules-legacy.so-ff43617ec381da18", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/lib/sysctl.d/00-alpine.conf", + "SPDXID": "SPDXRef-File-usr-lib-sysctl.d-00-alpine.conf-d70650009c2bb036", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-4a6a0840.rsa.pub-0c253a006a51a055", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5243ef4b.rsa.pub-7430793c9843ac71", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-524d27bb.rsa.pub-9174b40bd64a4afa", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5261cecb.rsa.pub-41bcca0722df483b", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-58199dcc.rsa.pub-33dbeb08a729965e", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-58cbb476.rsa.pub-ee960619cbfa52da", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-58e4f17d.rsa.pub-3104c985f7217a91", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5e69ca50.rsa.pub-1e36d9959ceb1540", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-60ac2099.rsa.pub-abac01a20548e31f", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-6165ee59.rsa.pub-60f3660667c882d5", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-61666e3f.rsa.pub-20c139d549b80964", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-616a9724.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616a9724.rsa.pub-9ee7f6bfafbd04f5", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-616abc23.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616abc23.rsa.pub-c0f8875bed907f16", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-616ac3bc.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616ac3bc.rsa.pub-5d2bce7c30d4842e", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-616adfeb.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616adfeb.rsa.pub-6277d3a7f9f78fa0", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-616ae350.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616ae350.rsa.pub-e8e728f7eb9ac206", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-616db30d.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616db30d.rsa.pub-58dfe972c27db41d", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/apk/keys/alpine-devel@lists.alpinelinux.org-66ba20fe.rsa.pub", + "SPDXID": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-66ba20fe.rsa.pub-9d58e602c9201b03", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + }, + { + "fileName": "/usr/share/udhcpc/default.script", + "SPDXID": "SPDXRef-File-usr-share-udhcpc-default.script-431ddc0b26fa5372", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "", + "comment": "layerID: sha256:3e01818d79cd3467f1d60e54224f3f6ce5170eceb54e265d96bb82344b8c24e7" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-scanelf-5732e2d080a0a28c", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-File-lib-ld-musl-x86-64.so.1-6e7e3004534b86d1", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-ssl-client-9894cb492b9e703b", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relatedSpdxElement": "SPDXRef-Package-apk-zlib-cd1596a99504840a", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relatedSpdxElement": "SPDXRef-File-usr-bin-ldd-485cab4248b11e3f", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relatedSpdxElement": "SPDXRef-File-usr-bin-iconv-b33e7a49b30565e7", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relatedSpdxElement": "SPDXRef-File-usr-bin-getconf-cb10741d9c217d07", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relatedSpdxElement": "SPDXRef-File-usr-bin-getent-d36d4602a8c0ad50", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relatedSpdxElement": "SPDXRef-File-sbin-ldconfig-f058d85fa2770b4f", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-etc-udhcpc-udhcpc.conf-378d389540b30911", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-etc-busybox-paths.d-busybox-3cbfe16761873575", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-usr-share-udhcpc-default.script-431ddc0b26fa5372", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-bin-busybox-468f4889734362f5", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-Package-apk-busybox-binsh-79dd77b653445aa8", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-etc-network-if-up.d-dad-ae53711b4c2ae508", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-etc-logrotate.d-acpid-e680a539c74e700d", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relatedSpdxElement": "SPDXRef-File-etc-securetty-f5ddc6e8bf552536", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "relatedSpdxElement": "SPDXRef-File-etc-secfixes.d-alpine-31f4ab357226cd60", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "relatedSpdxElement": "SPDXRef-File-etc-issue-b413295f2e1636b9", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "relatedSpdxElement": "SPDXRef-File-usr-lib-os-release-c36f73b65f306d73", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "relatedSpdxElement": "SPDXRef-File-etc-alpine-release-fd2f197c9c548c66", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-profile.d-README-22834df769d2095e", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-motd-4eb653645b7f13ee", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-crontabs-root-86d9785f3abff156", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-profile.d-color-prompt.sh.disabled-96f77289dc1c6105", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-modprobe.d-aliases.conf-b29978812ba855fa", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-modprobe.d-blacklist.conf-b58b1a80d90b95b5", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-modprobe.d-kms.conf-bae009a41fd01a1d", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-usr-lib-sysctl.d-00-alpine.conf-d70650009c2bb036", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-modprobe.d-i386.conf-f54933ed0cb86bd2", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relatedSpdxElement": "SPDXRef-File-etc-profile.d-20locale.sh-ff541b2c108c7e57", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-scanelf-5732e2d080a0a28c", + "relatedSpdxElement": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-scanelf-5732e2d080a0a28c", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-scanelf-5732e2d080a0a28c", + "relatedSpdxElement": "SPDXRef-File-usr-bin-scanelf-97db8aae69dc1643", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-4a6a0840.rsa.pub-0c253a006a51a055", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5e69ca50.rsa.pub-1e36d9959ceb1540", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-61666e3f.rsa.pub-20c139d549b80964", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-58e4f17d.rsa.pub-3104c985f7217a91", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-58199dcc.rsa.pub-33dbeb08a729965e", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5261cecb.rsa.pub-41bcca0722df483b", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616db30d.rsa.pub-58dfe972c27db41d", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616ac3bc.rsa.pub-5d2bce7c30d4842e", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-6165ee59.rsa.pub-60f3660667c882d5", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616adfeb.rsa.pub-6277d3a7f9f78fa0", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5243ef4b.rsa.pub-7430793c9843ac71", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5261cecb.rsa.pub-8503eca0329855ac", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-524d27bb.rsa.pub-9174b40bd64a4afa", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-66ba20fe.rsa.pub-9d58e602c9201b03", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616a9724.rsa.pub-9ee7f6bfafbd04f5", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-6165ee59.rsa.pub-9fc2b76378071420", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-60ac2099.rsa.pub-abac01a20548e31f", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616abc23.rsa.pub-c0f8875bed907f16", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-5243ef4b.rsa.pub-dd82cc7a531a4f8a", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-61666e3f.rsa.pub-e174ab22f2beeb60", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-4a6a0840.rsa.pub-e31ca5e7df53db52", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-616ae350.rsa.pub-e8e728f7eb9ac206", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relatedSpdxElement": "SPDXRef-File-...alpine-devel-lists.alpinelinux.org-58cbb476.rsa.pub-ee960619cbfa52da", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-usr-lib-engines-3-padlock.so-2230852154a764a9", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-usr-lib-engines-3-capi.so-2cac453818c05153", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-usr-lib-engines-3-afalg.so-51e3b429173363b7", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-etc-ssl-openssl.cnf.dist-70e74fc481bbd7b7", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-etc-ssl-ct-log-list.cnf.dist-7386b7ea31c8254f", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-etc-ssl-ct-log-list.cnf-97ee0f53ad135fdd", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-Package-apk-ssl-client-9894cb492b9e703b", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-etc-ssl-openssl.cnf-9afb2be8c7429f0d", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-usr-lib-libcrypto.so.3-a36b11ef91e748da", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-usr-lib-engines-3-loader-attic.so-b2bd5535e09327d5", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relatedSpdxElement": "SPDXRef-File-usr-lib-ossl-modules-legacy.so-ff43617ec381da18", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-67dec00a55941450", + "relatedSpdxElement": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-67dec00a55941450", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ca-certificates-bundle-67dec00a55941450", + "relatedSpdxElement": "SPDXRef-File-etc-ssl-certs-ca-certificates.crt-860b9d53645feb47", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relatedSpdxElement": "SPDXRef-File-usr-lib-libssl.so.3-69cc85b55482eba1", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relatedSpdxElement": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relatedSpdxElement": "SPDXRef-Package-apk-ssl-client-9894cb492b9e703b", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-protocols-2ebaf2d5275a87c3", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-inittab-4d8d5f0587154018", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-passwd-52c8226245401a54", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-services-5e64bee7d0512520", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-shells-5f409797065e8a24", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-nsswitch.conf-668425e791126652", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-hosts-6ac577ecad2ec5b0", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-profile-773e11b623fa2206", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-group-7db3625241f6856d", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-modules-a3196be7d01a0aec", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-fstab-b80c3cb56c980b08", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-sysctl.conf-c068f4c2abc469f7", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-shadow-e52a006d3d1244db", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relatedSpdxElement": "SPDXRef-File-etc-hostname-e7d0d8adb0625ce4", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relatedSpdxElement": "SPDXRef-File-sbin-apk-0c90571c31cc24d4", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relatedSpdxElement": "SPDXRef-File-usr-lib-libapk.so.2.14.0-4e2deeb47f39a10e", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-binsh-79dd77b653445aa8", + "relatedSpdxElement": "SPDXRef-File-bin-busybox-468f4889734362f5", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-binsh-79dd77b653445aa8", + "relatedSpdxElement": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-busybox-binsh-79dd77b653445aa8", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ssl-client-9894cb492b9e703b", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-Package-apk-ssl-client-9894cb492b9e703b", + "relatedSpdxElement": "SPDXRef-File-usr-bin-ssl-client-b4bab8e79035429e", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-zlib-cd1596a99504840a", + "relatedSpdxElement": "SPDXRef-File-usr-lib-libz.so.1.3.1-014a43ace0388eab", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-Package-apk-zlib-cd1596a99504840a", + "relatedSpdxElement": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relationshipType": "DEPENDENCY_OF" + }, + { + "spdxElementId": "SPDXRef-Package-apk-zlib-cd1596a99504840a", + "relatedSpdxElement": "SPDXRef-File-lib-apk-db-installed-847731c531b13bae", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-alpine-baselayout-51b252cbcc64365d", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-alpine-baselayout-data-6f47cd381e7d99ac", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-alpine-keys-5dd53a4dcb46e28e", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-alpine-release-51163b3e15318574", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-apk-tools-71bc4cfa3d7edaba", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-busybox-4f44d11c6a9d8f9c", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-busybox-binsh-79dd77b653445aa8", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-ca-certificates-bundle-67dec00a55941450", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-libcrypto3-60435cc06ed5c73a", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-libssl3-6ea5aa937ae77a59", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-musl-17abef0c23a9509f", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-musl-utils-472b480bd2fe3378", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-scanelf-5732e2d080a0a28c", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-ssl-client-9894cb492b9e703b", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Image-alpine", + "relatedSpdxElement": "SPDXRef-Package-apk-zlib-cd1596a99504840a", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relatedSpdxElement": "SPDXRef-DocumentRoot-Image-alpine", + "relationshipType": "DESCRIBES" + } + ] +} diff --git a/tests/unit/data/sboms/cachi2.bom.spdx.json b/tests/unit/data/sboms/cachi2.bom.spdx.json index e388b7fa6..a8d5f93c3 100644 --- a/tests/unit/data/sboms/cachi2.bom.spdx.json +++ b/tests/unit/data/sboms/cachi2.bom.spdx.json @@ -7,7 +7,7 @@ "creationInfo": { "licenseListVersion": "3.24", "creators": [ - "Organization: Anchore, Inc", + "Organization: Red Hat, Inc", "Tool: cachi2-" ], "created": "2024-08-21T11:19:04Z" diff --git a/tests/unit/data/sboms/merged.bom.spdx.json b/tests/unit/data/sboms/merged.bom.spdx.json index d1fe15e33..36b626b58 100644 --- a/tests/unit/data/sboms/merged.bom.spdx.json +++ b/tests/unit/data/sboms/merged.bom.spdx.json @@ -9,7 +9,7 @@ "creators": [ "Organization: Anchore, Inc", "Tool: syft-0.100.0", - "Organization: Anchore, Inc", + "Organization: Red Hat, Inc", "Tool: cachi2-" ], "created": "2024-08-21T11:19:30Z" diff --git a/tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json b/tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json new file mode 100644 index 000000000..1dbb0b2d7 --- /dev/null +++ b/tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json @@ -0,0 +1,112 @@ +{ + "spdxVersion": "SPDX-2.3", + "dataLicense": "CC0-1.0", + "SPDXID": "SPDXRef-DOCUMENT", + "name": "more_experiments/", + "documentNamespace": "https://anchore.com/syft/dir/more_experiments-22e50414-3115-4435-aa19-4e87afa03d09", + "creationInfo": { + "licenseListVersion": "3.22", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-0.100.0" + ], + "created": "2024-12-09T23:44:30Z" + }, + "packages": [ + { + "name": "i2c-devel", + "SPDXID": "SPDXRef-Package-rpm-i2c-devel-137ed927c09bd14d", + "versionInfo": "0:2.10.5-8.el3", + "supplier": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from RPM DB: /i2c-devel-2.10.5-8.el3.x86_64.rpm", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "LicenseRef-GPL", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:i2c-devel:i2c-devel:0\\:2.10.5-8.el3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:i2c-devel:i2c_devel:0\\:2.10.5-8.el3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:i2c_devel:i2c-devel:0\\:2.10.5-8.el3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:i2c_devel:i2c_devel:0\\:2.10.5-8.el3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:i2c:i2c-devel:0\\:2.10.5-8.el3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:i2c:i2c_devel:0\\:2.10.5-8.el3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:rpm/i2c-devel@2.10.5-8.el3?arch=x86_64&epoch=0&upstream=i2c-2.10.5-8.el3.src.rpm" + } + ] + }, + { + "name": "more_experiments/", + "SPDXID": "SPDXRef-DocumentRoot-Directory-more-experiments-", + "supplier": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "primaryPackagePurpose": "FILE" + } + ], + "files": [ + { + "fileName": "/i2c-devel-2.10.5-8.el3.x86_64.rpm", + "SPDXID": "SPDXRef-File-i2c-devel-2.10.5-8.el3.x86-64.rpm-0992d87b036af481", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "" + } + ], + "hasExtractedLicensingInfos": [ + { + "licenseId": "LicenseRef-GPL", + "extractedText": "GPL" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-Package-rpm-i2c-devel-137ed927c09bd14d", + "relatedSpdxElement": "SPDXRef-File-i2c-devel-2.10.5-8.el3.x86-64.rpm-0992d87b036af481", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Directory-more-experiments-", + "relatedSpdxElement": "SPDXRef-Package-rpm-i2c-devel-137ed927c09bd14d", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relatedSpdxElement": "SPDXRef-DocumentRoot-Directory-more-experiments-", + "relationshipType": "DESCRIBES" + } + ] +} diff --git a/tests/unit/data/something.simple0.100.0.spdx.pretty.json b/tests/unit/data/something.simple0.100.0.spdx.pretty.json new file mode 100644 index 000000000..8f053e98c --- /dev/null +++ b/tests/unit/data/something.simple0.100.0.spdx.pretty.json @@ -0,0 +1,87 @@ +{ + "spdxVersion": "SPDX-2.3", + "dataLicense": "CC0-1.0", + "SPDXID": "SPDXRef-DOCUMENT", + "name": "experiments/", + "documentNamespace": "https://anchore.com/syft/dir/experiments-d6d4a378-508e-4f7b-b478-22f0d8e0978c", + "creationInfo": { + "licenseListVersion": "3.22", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-0.100.0" + ], + "created": "2024-12-09T19:00:27Z" + }, + "packages": [ + { + "name": "ash", + "SPDXID": "SPDXRef-Package-rpm-ash-b5c592006a5ddade", + "versionInfo": "0:0.3.8-20.el4_7.1", + "supplier": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "sourceInfo": "acquired package info from RPM DB: /ash-0.3.8-20.el4_7.1.x86_64.rpm", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "LicenseRef-BSD", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:ash:ash:0\\:0.3.8-20.el4_7.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:rpm/ash@0.3.8-20.el4_7.1?arch=x86_64&epoch=0&upstream=ash-0.3.8-20.el4_7.1.src.rpm" + } + ] + }, + { + "name": "experiments/", + "SPDXID": "SPDXRef-DocumentRoot-Directory-experiments-", + "supplier": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "primaryPackagePurpose": "FILE" + } + ], + "files": [ + { + "fileName": "/ash-0.3.8-20.el4_7.1.x86_64.rpm", + "SPDXID": "SPDXRef-File-ash-0.3.8-20.el4-7.1.x86-64.rpm-39422426cc3490ed", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "0000000000000000000000000000000000000000" + } + ], + "licenseConcluded": "NOASSERTION", + "copyrightText": "" + } + ], + "hasExtractedLicensingInfos": [ + { + "licenseId": "LicenseRef-BSD", + "extractedText": "BSD" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-Package-rpm-ash-b5c592006a5ddade", + "relatedSpdxElement": "SPDXRef-File-ash-0.3.8-20.el4-7.1.x86-64.rpm-39422426cc3490ed", + "relationshipType": "OTHER", + "comment": "evident-by: indicates the package's existence is evident by the given file" + }, + { + "spdxElementId": "SPDXRef-DocumentRoot-Directory-experiments-", + "relatedSpdxElement": "SPDXRef-Package-rpm-ash-b5c592006a5ddade", + "relationshipType": "CONTAINS" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relatedSpdxElement": "SPDXRef-DocumentRoot-Directory-experiments-", + "relationshipType": "DESCRIBES" + } + ] +} diff --git a/tests/unit/models/test_sbom.py b/tests/unit/models/test_sbom.py index d1fa17428..dc049eb53 100644 --- a/tests/unit/models/test_sbom.py +++ b/tests/unit/models/test_sbom.py @@ -238,22 +238,6 @@ def test_invalid_packages(self, input_data: dict[str, str], expect_error: str) - @pytest.mark.parametrize( "category,type,locator,valid", [ - ("SECURITY", "cpe22Type", "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", False), - ( - "SECURITY", - "cpe23Type", - "cpe:2.3:a:microsoft:internet_explorer:8.0.6001:beta:*:*:*:*:*:*", - False, - ), - ("SECURITY", "advisory", "https://nvd.nist.gov/vuln/detail/CVE-2020-28498", False), - ("SECURITY", "fix", "https://github.com/indutny/elliptic/commit/441b7428", False), - ( - "SECURITY", - "url", - "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md", - False, - ), - ("SECURITY", "swid", "2df9de35-0aff-4a86-ace6-f7dddd1ade4c", False), ("PACKAGE-MANAGER", "maven-central", "org.apache.tomcat:tomcat:9.0.0.M4", False), ("PACKAGE-MANAGER", "npm", "http-server@0.3.0", False), ("PACKAGE-MANAGER", "nuget", "Microsoft.AspNet.MVC/5.0.0", False), @@ -278,7 +262,7 @@ def test_package_unsupported_external_ref( ) -> None: """Fails on unsupported category and type combinations. - Only PACKAGE-MANAGER category with type purl is supported. + Only PACKAGE-MANAGER and SECURITY categories with type purl is supported. """ adapter: pydantic.TypeAdapter = pydantic.TypeAdapter(SPDXPackageExternalRefType) with pytest.raises(pydantic.ValidationError): @@ -383,13 +367,13 @@ def test_to_spdx(self, isodate: datetime.datetime) -> None: ], annotations=[ SPDXPackageAnnotation( - annotator="Tool:cachi2:jsonencoded", + annotator="Tool: cachi2:jsonencoded", annotationDate="2021-07-01T00:00:00Z", annotationType="OTHER", comment=json.dumps({"name": "cachi2:found_by", "value": "cachi2"}), ), SPDXPackageAnnotation( - annotator="Tool:cachi2:jsonencoded", + annotator="Tool: cachi2:jsonencoded", annotationDate="2021-07-01T00:00:00Z", annotationType="OTHER", comment=json.dumps({"name": "cdx:npm:package:bundled", "value": "true"}), @@ -409,7 +393,7 @@ def test_to_spdx(self, isodate: datetime.datetime) -> None: ], annotations=[ SPDXPackageAnnotation( - annotator="Tool:cachi2:jsonencoded", + annotator="Tool: cachi2:jsonencoded", annotationDate="2021-07-01T00:00:00Z", annotationType="OTHER", comment=json.dumps({"name": "cachi2:found_by", "value": "cachi2"}), @@ -429,7 +413,7 @@ def test_to_spdx(self, isodate: datetime.datetime) -> None: ], annotations=[ SPDXPackageAnnotation( - annotator="Tool:cachi2:jsonencoded", + annotator="Tool: cachi2:jsonencoded", annotationDate="2021-07-01T00:00:00Z", annotationType="OTHER", comment=json.dumps({"name": "cachi2:found_by", "value": "cachi2"}), @@ -862,7 +846,7 @@ def test_spdx_sbom_can_be_converted_to_cyclonedx_and_back_without_loosing_any_da ], "annotations": [ { - "annotator": "Tool:cachi2:jsonencoded", + "annotator": "Tool: cachi2:jsonencoded", "annotationDate": "2021-07-01T00:00:00Z", "annotationType": "OTHER", "comment": '{"name": "cachi2:found_by", "value": "cachi2"}', @@ -882,7 +866,7 @@ def test_spdx_sbom_can_be_converted_to_cyclonedx_and_back_without_loosing_any_da ], "annotations": [ { - "annotator": "Tool:cachi2:jsonencoded", + "annotator": "Tool: cachi2:jsonencoded", "annotationDate": "2021-07-01T00:00:00Z", "annotationType": "OTHER", "comment": '{"name": "cachi2:found_by", "value": "cachi2"}', @@ -902,7 +886,7 @@ def test_spdx_sbom_can_be_converted_to_cyclonedx_and_back_without_loosing_any_da ], "annotations": [ { - "annotator": "Tool:cachi2:jsonencoded", + "annotator": "Tool: cachi2:jsonencoded", "annotationDate": "2021-07-01T00:00:00Z", "annotationType": "OTHER", "comment": '{"name": "cachi2:found_by", "value": "cachi2"}', @@ -922,7 +906,7 @@ def test_spdx_sbom_can_be_converted_to_cyclonedx_and_back_without_loosing_any_da ], "annotations": [ { - "annotator": "Tool:cachi2:jsonencoded", + "annotator": "Tool: cachi2:jsonencoded", "annotationDate": "2021-07-01T00:00:00Z", "annotationType": "OTHER", "comment": '{"name": "cachi2:found_by", "value": "cachi2"}', @@ -942,7 +926,7 @@ def test_spdx_sbom_can_be_converted_to_cyclonedx_and_back_without_loosing_any_da ], "annotations": [ { - "annotator": "Tool:cachi2:jsonencoded", + "annotator": "Tool: cachi2:jsonencoded", "annotationDate": "2021-07-01T00:00:00Z", "annotationType": "OTHER", "comment": '{"name": "cachi2:found_by", "value": "cachi2"}', @@ -962,7 +946,7 @@ def test_spdx_sbom_can_be_converted_to_cyclonedx_and_back_without_loosing_any_da ], "annotations": [ { - "annotator": "Tool:cachi2:jsonencoded", + "annotator": "Tool: cachi2:jsonencoded", "annotationDate": "2021-07-01T00:00:00Z", "annotationType": "OTHER", "comment": '{"name": "cachi2:found_by", "value": "cachi2"}', @@ -982,7 +966,7 @@ def test_spdx_sbom_can_be_converted_to_cyclonedx_and_back_without_loosing_any_da ], "annotations": [ { - "annotator": "Tool:cachi2:jsonencoded", + "annotator": "Tool: cachi2:jsonencoded", "annotationDate": "2021-07-01T00:00:00Z", "annotationType": "OTHER", "comment": '{"name": "cachi2:found_by", "value": "cachi2"}', diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index 568c130f6..a8b3d34df 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -974,7 +974,7 @@ def test_a_user_can_successfully_save_sboms_merge_results_to_a_file( [ [ "./tests/unit/data/sboms/cachi2.bom.spdx.json", - "./tests/unit/data/sboms/syft.bom.spdx.json", + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", ], ], ) diff --git a/tests/unit/test_merge_spdx.py b/tests/unit/test_merge_spdx.py index 79e4978c8..0f80f98f6 100644 --- a/tests/unit/test_merge_spdx.py +++ b/tests/unit/test_merge_spdx.py @@ -1,521 +1,287 @@ -from itertools import chain -from typing import cast +from collections import defaultdict +from functools import reduce +from operator import add +from pathlib import Path +from typing import Any import pytest -from cachi2.core.models.sbom import ( - SPDXPackage, - SPDXPackageExternalRefPackageManagerPURL, - SPDXRelation, - SPDXSbom, -) -from cachi2.interface.cli import merge_relationships +from cachi2.core.models.sbom import SPDXSbom + + +def _find_roots(sbom: SPDXSbom) -> list[str]: + direct_rel_map = defaultdict(list) + inverse_map = dict() + for rel in sbom.relationships: + spdx_id, related_spdx = rel.spdxElementId, rel.relatedSpdxElement + direct_rel_map[spdx_id].append(related_spdx) + inverse_map[related_spdx] = spdx_id + unidirectionally_related_package = lambda p: inverse_map.get(p) == sbom.SPDXID # noqa: E731 + roots = list(filter(unidirectionally_related_package, direct_rel_map)) + return roots + + +def _assert_merging_sboms_produces_correct_number_of_packages( + merged_sbom: SPDXSbom, + *sources: SPDXSbom, +) -> None: + # Ignoring mypy because it is cheaper to rebind the name in a local utility. + sources = set(sources) # type: ignore + unqie_packages_across_all_sources = set(sum([s.packages for s in sources], [])) + # Drop one root package per source, add 1 to account for one eventuial root: + expected_num_of_packages = len(unqie_packages_across_all_sources) - len(sources) + 1 + actual_num_of_packages = len(merged_sbom.packages) + difference = expected_num_of_packages - actual_num_of_packages + msg = ( + f"""Number of packages in input SBOMs and resulting SBOM do not add up: + The new SBOM contains {abs(difference)} package{'s' if abs(difference) != 1 else ''} """ + f"""{"more" if difference < 0 else "less"} than the both input SBOMs.""" + ) + assert expected_num_of_packages == actual_num_of_packages, msg + + assert len(merged_sbom.relationships) == len( + set(merged_sbom.relationships) + ), "Relationships length mismatch" + + +def _assert_merging_two_distinct_sboms_produces_correct_number_of_packages( + sbom_left: SPDXSbom, + sbom_right: SPDXSbom, + merged_sbom: SPDXSbom, +) -> None: + # Note the 'distinct' part: sbom_left and sbom_right _do not_ intersect. + # You should never verify intersecting SBOMs with this function. + # -1 for one of the roots that must go. + expected_num_of_packages = len(sbom_left.packages) + len(sbom_right.packages) - 1 + actual_num_of_packages = len(merged_sbom.packages) + difference = expected_num_of_packages - actual_num_of_packages + msg = ( + f""" + Number of packages in input SBOMs and resulting SBOM do not add up: + The new SBOM contains {abs(difference)} package{'s' if abs(difference) != 1 else ''} """ + f"""{"more" if difference < 0 else "less"} than the both input SBOMs.""" + ) + assert expected_num_of_packages == actual_num_of_packages, msg + + +def _assert_merging_two_sboms_produces_correct_number_of_files( + sbom_left: SPDXSbom, + sbom_right: SPDXSbom, + merged_sbom: SPDXSbom, +) -> None: + assert len(sbom_left.files) + len(sbom_right.files) == len(merged_sbom.files) + + +def _assert_root_was_inherited_from_left_sbom( + merged_sbom: SPDXSbom, + sbom_left: SPDXSbom, +) -> None: + msg = f"""Root mismatch! + Expected: {sbom_left.root_id} + Got: {merged_sbom.root_id} + """ + assert merged_sbom.root_id == sbom_left.root_id, msg + + +def _assert_there_is_only_one_root(merged_sbom: SPDXSbom) -> None: + assert len(_find_roots(merged_sbom)) == 1, f"Found several roots in {merged_sbom}" + + +def _assert_all_relationships_are_within_the_document(for_sbom: SPDXSbom) -> None: + external_rels = [] + package_names = [p.SPDXID for p in for_sbom.packages] + file_names = [f.SPDXID for f in for_sbom.files] + known_entities = package_names + file_names + + for r in for_sbom.relationships: + if r.relatedSpdxElement not in known_entities: + external_rels.append(r) + if external_rels: + assert False, f"Found relations that lead outside of a document: {external_rels}" + + +def _assert_root_is_present(sbom: SPDXSbom) -> None: + # DocumentRoot can be File or Directory: + fail_msg = "Document root is missing" + root_pfx = "SPDXRef-DocumentRoot-" + # The inline would be too long otherwise, thus lambda, thus noqa. + is_root = lambda p: p.SPDXID is not None and p.SPDXID.startswith(root_pfx) # noqa: E731 + assert any(is_root(p) for p in sbom.packages), fail_msg + + +def _assert_no_relation_is_missing(sbom: SPDXSbom) -> None: + # I.e. ther are at least as many relations as packages _and_ files + # (each package will relate to at least one other package and that would be + # thr root document). + assert len(sbom.relationships) == len( + set(sbom.relationships) + ), "There are duplicate relationships" + fail_msg = ( + "Some packages are not having relationships: not enough relationships for all packages" + ) + assert len(sbom.packages) + len(sbom.files) <= len(sbom.relationships), fail_msg +def _assert_no_relationship_points_out(sbom: SPDXSbom) -> None: + packages = set(p.SPDXID for p in sbom.packages) + files = set(f.SPDXID for f in sbom.files) + assert all( + (rel := r.relatedSpdxElement) in packages or rel in files for r in sbom.relationships + ), "Found stray relationship(s)" + + +def _assert_no_unrelated_packages(sbom: SPDXSbom) -> None: + ids_related_to = set(r.relatedSpdxElement for r in sbom.relationships) + assert all(p.SPDXID in ids_related_to for p in sbom.packages), "Unrelated packages detecetd" + + +def _assert_no_unrelated_files(sbom: SPDXSbom) -> None: + ids_related_to = set(r.relatedSpdxElement for r in sbom.relationships) + assert all(f.SPDXID in ids_related_to for f in sbom.files), "Unrelated files detected" + + +def _assert_sbom_is_well_formed(sbom: SPDXSbom) -> None: + _assert_root_is_present(sbom) + _assert_no_relation_is_missing(sbom) + _assert_no_relationship_points_out(sbom) + _assert_no_unrelated_packages(sbom) + _assert_no_unrelated_files(sbom) + + +# Data for this test was generated with syft like this: +# For a directory: +# $ ./syft dir:experiments/ -o spdx-json > experiments.json +# $ jq < experiments.json > experiments.pretty.json +# $ ls experiments +# $ ash-0.3.8-20.el4_7.1.x86_64.rpm +# For a container image (sha256:4048db5d36726e313ab8f7ffccf2362a34cba69e4cdd49119713483a68641fce): +# $ ./syft alpine -o spdx-json > alpine.json +# $ jq < alpine.json > alpine.pretty.json +# I used syft v 0.100.0 to be consistent with what I assumed to be correct test data. @pytest.mark.parametrize( - "sbom_files_to_merge", + "sbom_main,sbom_other", [ [ - "./tests/unit/data/sboms/cachi2.bom.spdx.json", - "./tests/unit/data/sboms/syft.bom.spdx.json", + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", + "./tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json", + ], + [ + "./tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json", + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", ], [ - "./tests/unit/data/sboms/syft.bom.spdx.json", - "./tests/unit/data/sboms/cachi2.bom.spdx.json", + "./tests/unit/data/alpine.pretty.json", + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", + ], + [ + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", + "./tests/unit/data/alpine.pretty.json", ], ], ) -def test_merge_spdx_relationships( - sbom_files_to_merge: list[str], +# NOTE: additional tests should be: +# * verifying rules for mixed merging of SPDX and CycloneDX +# * verifying merging of CycloneDX with a conversion to SPDX +# * ensure no change for SPDX + same SPDX, but pre-converted into CDX +# Also it is likely that conversion willl need to be tested as well +# TODO: +# SPDXSbom.from_cyclonedx(SBOM) +# Sbom.from_spdx(SPDXSbom) +# or even beter: (can be both actually) +# Sbom.from_sbom(other): +# if same_class: return other +# else: return convert_to(cls) +# TODO: merging with self +# deduplication must be accounted for (should happen automatically with model_copy) +def test_merging_two_spdx_sboms_works_in_general_independent_of_order( + sbom_main: Any, # 'Any' is used to prevent mypy from having a fit over re-binding + sbom_other: Any, # 'Any' is used to prevent mypy from having a fit over re-binding ) -> None: - sboms_to_merge = [] - for sbom_file in sbom_files_to_merge: - with open(sbom_file, "r") as f: - sbom_json = f.read() - sboms_to_merge.append(SPDXSbom.model_validate_json(sbom_json)) - - packages = list(chain.from_iterable(s.packages for s in sboms_to_merge)) - - doc_ids = cast(list[str], [s.SPDXID for s in sboms_to_merge]) - relationships_to_merge = [s.relationships for s in sboms_to_merge] - merged, packages = merge_relationships(relationships_to_merge, doc_ids, packages) - assert merged == [ - SPDXRelation( - spdxElementId="SPDXRef-DOCUMENT", - comment=None, - relatedSpdxElement="SPDXRef-DocumentRoot-File-", - relationshipType="DESCRIBES", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-go-module-.-terminaltor-1b79094a8c283d88", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-go-module-.-terminaltor-9c8431f4d44b5c65", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-python-PyYAML-0172906cb007d3b6", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-python-aiowsgi-b32dee5d93047994", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-python-appr-93a64d044490691c", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-rpm-bash-1a6619bdab5f8a2d", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-python-cachi2-71a99443e114c112", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-npm-cachito-npm-without-deps-72138119b55a065d", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-go-module-code.gitea.io-sdk-gitea-3172f131171fcbf8", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-npm-fecha-ff4ad17b28d08441", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-go-module-github.com-docker-cli-1671a7feec4073fe", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-go-module-github.com-" - "redhat-appstudio-build-service-5719506d15c0a3dd", - relationshipType="CONTAINS", - ), - SPDXRelation( - spdxElementId="SPDXRef-DocumentRoot-File-", - comment=None, - relatedSpdxElement="SPDXRef-Package-go-module-knative.dev-pkg-8ce424e944b2a02f", - relationshipType="CONTAINS", - ), - ] - assert sorted(packages) == [ - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-.-terminaltor-1b79094a8c283d88", - name="./terminaltor", - versionInfo=None, - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/./terminaltor", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-.-terminaltor-9c8431f4d44b5c65", - name="./terminaltor", - versionInfo="(devel)", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/./terminaltor@(devel)", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ), - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-archive-tar-1ce4dbb5cf96f1c7", - name="archive/tar", - versionInfo=None, - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/archive/tar?type=package", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-code.gitea.io-sdk-gitea-3172f131171fcbf8", - name="code.gitea.io/sdk/gitea", - versionInfo="v0.15.1", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/code.gitea.io/sdk/gitea@v0.15.1", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-code.gitea.io-sdk-gitea-cdc94d3a9074a69b", - name="code.gitea.io/sdk/gitea", - versionInfo="v0.15.1", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/code.gitea.io/sdk/gitea@v0.15.1?type=module", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-github.com-cachito-testing-gomod-pandemon" - "ium-terminaltor-d85aa69f7b0304e3", - name="github.com/cachito-testing/gomod-" "pandemonium/terminaltor", - versionInfo="v1.0.0", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/github.com/cachito-testing/gomod-pandem" - "onium/terminaltor@v1.0.0?type=module", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-github.com-docker-cli-1671a7feec4073fe", - name="github.com/docker/cli", - versionInfo="v23.0.0-rc.3+incompatible", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/github.com/docker/cli@v23.0.0-rc.3+incompatible", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-github.com-docker-cli-cli-config-73cc4b7b8f510817", - name="github.com/docker/cli/cli/config", - versionInfo="v23.0.0-rc.3+incompatible", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/github.com/docker/cli/cli/config@v23.0.0-rc." - "3%2Bincompatible?type=package", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-github.com-docker-cli-ea403731821a081e", - name="github.com/docker/cli", - versionInfo="v23.0.0-rc.3+incompatible", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/github.com/docker/cli@v23.0.0-rc.3%2Binc" - "ompatible?type=module", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-github.com-redhat-appstudio-build-" - "service-5719506d15c0a3dd", - name="github.com/redhat-appstudio/build-service", - versionInfo="(devel)", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/github.com/redhat-appstudio/build-service@(devel)", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-github.com-redhat-appstudio-build-service-" - "574d786c89acf613", - name="github.com/redhat-appstudio/build-service", - versionInfo="v0.0.0-20230503110830-d1a9e858489d", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/github.com/redhat-appstudio/build-service@v0" - ".0.0-20230503110830-d1a9e858489d?type=module", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-knative.dev-pkg-0a00bf33a820e7f1", - name="knative.dev/pkg", - versionInfo="v0.0.0-20230125083639-408ad0773f47", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/knative.dev/pkg@v0.0.0-20230125083639-408ad0" - "773f47?type=module", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-knative.dev-pkg-8ce424e944b2a02f", - name="knative.dev/pkg", - versionInfo="v0.0.0-20230125083639-408ad0773f47", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/knative.dev/pkg@v0.0.0-20230125083639-408ad0773f47", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-go-module-knative.dev-pkg-metrics-c613be23287c5dc4", - name="knative.dev/pkg/metrics", - versionInfo="v0.0.0-20230125083639-408ad0773f47", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:golang/knative.dev/pkg/metrics@v0.0.0-2023012508" - "3639-408ad0773f47?type=package", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-npm-cachito-npm-without-deps-563e3658e3eb288e", - name="cachito-npm-without-deps", - versionInfo=None, - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:npm/cachito-npm-without-deps?vcs_url=git%2" - "Bhttps://github.com/cachito-testing/cachito-npm-without-deps.git" - "%402f0ce1d7b1f8b35572d919428b965285a69583f6", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-npm-cachito-npm-without-deps-72138119b55a065d", - name="cachito-npm-without-deps", - versionInfo="git+https://github.com/cachito-testing/cachito-npm-without-deps." - "git#2f0ce1d7b1f8b35572d919428b965285a69583f6", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:npm/cachito-npm-without-deps@git+https://github.com/" - "cachito-testing/cachito-npm-without-deps.git%232f0ce1d7b1f8b35572d919428b" - "965285a69583f6", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-npm-fecha-874399c7dda48850", - name="fecha", - versionInfo=None, - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:npm/fecha?checksum=sha512:8ae71e98d68e38e1f6e" - "4c629187684dd85e4dc96647c7219b1dd189598ea52865e947f0ad94a7001fa8fb" - "5eccf58467fe34ad10066e831af3374120134604bd5&download_url=https://g" - "ithub.com/taylorhakes/fecha/archive/91680e4db1415fea33eac878cfd889" - "c80a7b55c7.tar.gz", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-npm-fecha-ff4ad17b28d08441", - name="fecha", - versionInfo="https://github.com/taylorhakes/fecha/archive/91680e4db1415fea3" - "3eac878cfd889c80a7b55c7.tar.gz", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:npm/fecha@https://github.com/taylorhakes/fecha/" - "archive/91680e4db1415fea33eac878cfd889c80a7b55c7.tar.gz", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-PyYAML-0172906cb007d3b6", - name="PyYAML", - versionInfo="6.0", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/PyYAML@6.0", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-PyYAML-696696f5e92f1b5e", - name="PyYAML", - versionInfo="6.0", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/pyyaml@6.0", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-aiowsgi-78716bdabf6daae1", - name="aiowsgi", - versionInfo="0.8", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/aiowsgi@0.8", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-aiowsgi-b32dee5d93047994", - name="aiowsgi", - versionInfo="0.8", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/aiowsgi@0.8", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-appr-93a64d044490691c", - name="appr", - versionInfo="0.7.4", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/appr@0.7.4", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-appr-d869da81f0adbece", - name="appr", - versionInfo=None, - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/appr?checksum=sha256:ee6a0a38bed8cff46a56" - "2ed3620bc453141a02262ab0c8dd055824af2829ee5c&download_url=" - "https://github.com/quay/appr/archive/37ff9a487a54ad41b59855ecd76e" - "e092fe206a84.zip", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-cachi2-71a99443e114c112", - name="cachi2", - versionInfo="0.0.post1+gdfd2180.d20230704", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/cachi2@0.0.post1+gdfd2180.d20230704", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-cachi2-865cdb2c6f0ff5c5", - name="cachi2", - versionInfo="0.0.1", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/cachi2@0.0.1?vcs_url=" - "git%2Bssh://git%40github.com/containerbuildsystem/cachi2%40fc0d6079" - "c2dc9b2a491c0848e550ad3509986110", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], - ), - SPDXPackage( - SPDXID="SPDXRef-Package-python-test-package-cachi2-bdec7caf7aac75f3", - name="test_package_cachi2", - versionInfo="1.0.0", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:pypi/test-package-cachi2@1.0.0?vcs_url=git%2B" - "ssh://git%40github.com/brunoapimentel/pip-e2e-test.git%40294df352deed83" - "5cf703ae8a799926418ae5fd3b", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], + # Re-using the names withing a short scope => mypy sad => must distract mypy. + # Simple ignore won't work here so the need for a cast. + sbom_main = SPDXSbom.from_file(Path(sbom_main)) + sbom_other = SPDXSbom.from_file(Path(sbom_other)) + + merged_sbom = sbom_main + sbom_other + + _assert_all_relationships_are_within_the_document(for_sbom=merged_sbom) + _assert_merging_two_distinct_sboms_produces_correct_number_of_packages( + sbom_main, sbom_other, merged_sbom + ) + _assert_merging_sboms_produces_correct_number_of_packages(merged_sbom, sbom_other, sbom_main) + _assert_merging_two_sboms_produces_correct_number_of_files(sbom_main, sbom_other, merged_sbom) + _assert_root_was_inherited_from_left_sbom(merged_sbom, sbom_main) + _assert_there_is_only_one_root(merged_sbom) + + +@pytest.mark.parametrize( + "sboms_to_merge", + [ + pytest.param( + ( + "./tests/unit/data/alpine.pretty.json", + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", + "./tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json", + ), + id="three unique SBOMs", + ), + pytest.param( + ( + "./tests/unit/data/alpine.pretty.json", + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", + "./tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json", + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", + ), + # The same SBOM is attempted to be merged in -- should be a separate test + id="three unique SBOMs and a duplicate", ), - SPDXPackage( - SPDXID="SPDXRef-Package-rpm-bash-1a6619bdab5f8a2d", - name="bash", - versionInfo="4.4.20-4.el8_6", - externalRefs=[ - SPDXPackageExternalRefPackageManagerPURL( - referenceLocator="pkg:rpm/rhel/bash@4.4.20-4.el8_6?arch=x86_64&upstream=" - "bash-4.4.20-4.el8_6.src.rpm&distro=rhel-8.7", - referenceType="purl", - referenceCategory="PACKAGE-MANAGER", - ) - ], - annotations=[], + ], +) +def test_merging_several_spdx_sboms_works_in_general_independent_of_order( + sboms_to_merge: list[Any], # 'Any' is used to prevent mypy from having a fit over re-binding +) -> None: + sboms_to_merge = [SPDXSbom.from_file(Path(s)) for s in sboms_to_merge] + + merged_sbom = reduce(add, sboms_to_merge) + # merged_sbom = sum(sboms_to_merge[1:], sboms_to_merge[0]) ? + + _assert_all_relationships_are_within_the_document(for_sbom=merged_sbom) + # TODO: assert_no_relation_goes_missing(merged_sbom, *sboms) + _assert_merging_sboms_produces_correct_number_of_packages(merged_sbom, *sboms_to_merge) + _assert_root_was_inherited_from_left_sbom(merged_sbom, sboms_to_merge[0]) + _assert_there_is_only_one_root(merged_sbom) + _assert_sbom_is_well_formed(merged_sbom) + + +def _same_order(sbom1: SPDXSbom, sbom2: SPDXSbom) -> bool: + for r1, r2 in zip(sbom1.relationships, sbom2.relationships): + if r1 != r2: + return False + return True + + +@pytest.mark.parametrize( + "sboms_to_merge", + [ + pytest.param( + ( + "./tests/unit/data/something.simple0.100.0.spdx.pretty.json", + "./tests/unit/data/something.more.simple.0.100.0.spdx.pretty.json", + ), + id="two sboms", ), - ] + ], +) +def test_merging_spdx_sboms_produces_consistent_ordering( + sboms_to_merge: list[Any], # 'Any' is used to prevent mypy from having a fit over re-binding +) -> None: + sboms_to_merge = [SPDXSbom.from_file(Path(s)) for s in sboms_to_merge] + + merged_sbom1 = reduce(add, sboms_to_merge) + merged_sbom2 = reduce(add, sboms_to_merge) + merged_sbom3 = reduce(add, sboms_to_merge) + + assert _same_order(merged_sbom1, merged_sbom2), "Order mismatch!" + assert _same_order(merged_sbom2, merged_sbom3), "Order mismatch!" + + _assert_sbom_is_well_formed(merged_sbom1)