diff --git a/internal/constants.go b/internal/constants.go index 4dd27cf79537..469f075c89c5 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.18" + JSONSchemaVersion = "16.0.19" ) diff --git a/internal/task/package_task_factory.go b/internal/task/package_task_factory.go index 5a65a29f040b..d3215f6634ba 100644 --- a/internal/task/package_task_factory.go +++ b/internal/task/package_task_factory.go @@ -110,6 +110,8 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string pkgs, relationships = applyCompliance(cfg.ComplianceConfig, pkgs, relationships) + finalizeDependencyCompleteness(pkgs) + sbom.AddPackages(pkgs...) sbom.AddRelationships(relationships...) t.Add(int64(len(pkgs))) @@ -124,6 +126,13 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string return NewTask(c.Name(), fn, tags...) } +func finalizeDependencyCompleteness(pkgs []pkg.Package) { + // ensure that all packages have a non-empty dependency list + for i := range pkgs { + pkgs[i].Dependencies = pkg.ParseDependencyCompleteness(string(pkgs[i].Dependencies)) + } +} + func finalizePkgCatalogerResults(cfg CatalogingFactoryConfig, resolver file.PathResolver, catalogerName string, pkgs []pkg.Package, relationships []artifact.Relationship) ([]pkg.Package, []artifact.Relationship) { for i, p := range pkgs { if p.FoundBy == "" { diff --git a/schema/json/schema-16.0.19.json b/schema/json/schema-16.0.19.json new file mode 100644 index 000000000000..0ce7f118a297 --- /dev/null +++ b/schema/json/schema-16.0.19.json @@ -0,0 +1,2731 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.19/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixStoreEntry": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "dependencies": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl", + "dependencies" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index 936582e2d22e..0ce7f118a297 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.18/document", + "$id": "anchore.io/schema/syft/json/16.0.19/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { @@ -1610,6 +1610,9 @@ "purl": { "type": "string" }, + "dependencies": { + "type": "string" + }, "metadataType": { "type": "string" }, @@ -1773,7 +1776,8 @@ "licenses", "language", "cpes", - "purl" + "purl", + "dependencies" ] }, "PhpComposerAuthors": { diff --git a/syft/format/internal/testutil/directory_input.go b/syft/format/internal/testutil/directory_input.go index e3ac030778b8..28eba86816d4 100644 --- a/syft/format/internal/testutil/directory_input.go +++ b/syft/format/internal/testutil/directory_input.go @@ -121,7 +121,8 @@ func newDirectoryCatalog() *pkg.Collection { }, }, }, - PURL: "a-purl-2", // intentionally a bad pURL for test fixtures + PURL: "a-purl-2", // intentionally a bad pURL for test fixtures + Dependencies: pkg.CompleteDependencies, CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.Source("")), }, @@ -138,7 +139,8 @@ func newDirectoryCatalog() *pkg.Collection { Package: "package-2", Version: "2.0.1", }, - PURL: "pkg:deb/debian/package-2@2.0.1", + PURL: "pkg:deb/debian/package-2@2.0.1", + Dependencies: pkg.CompleteDependencies, CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.Source("")), }, @@ -163,6 +165,7 @@ func newDirectoryCatalogWithAuthorField() *pkg.Collection { Licenses: pkg.NewLicenseSet( pkg.NewLicense("MIT"), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "package-1", Version: "1.0.1", @@ -190,7 +193,8 @@ func newDirectoryCatalogWithAuthorField() *pkg.Collection { Package: "package-2", Version: "2.0.1", }, - PURL: "pkg:deb/debian/package-2@2.0.1", + Dependencies: pkg.CompleteDependencies, + PURL: "pkg:deb/debian/package-2@2.0.1", CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", "another-test-source"), }, diff --git a/syft/format/internal/testutil/image_input.go b/syft/format/internal/testutil/image_input.go index d033b3cc54bb..61898e5fb141 100644 --- a/syft/format/internal/testutil/image_input.go +++ b/syft/format/internal/testutil/image_input.go @@ -117,7 +117,8 @@ func populateImageCatalog(catalog *pkg.Collection, img *image.Image) { Name: "package-1", Version: "1.0.1", }, - PURL: "a-purl-1", // intentionally a bad pURL for test fixtures + PURL: "a-purl-1", // intentionally a bad pURL for test fixtures + Dependencies: pkg.CompleteDependencies, CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", cpe.GeneratedSource), }, @@ -137,7 +138,8 @@ func populateImageCatalog(catalog *pkg.Collection, img *image.Image) { Package: "package-2", Version: "2.0.1", }, - PURL: "pkg:deb/debian/package-2@2.0.1", + PURL: "pkg:deb/debian/package-2@2.0.1", + Dependencies: pkg.CompleteDependencies, CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, diff --git a/syft/format/syftjson/encoder_test.go b/syft/format/syftjson/encoder_test.go index 292fd6169be6..2c7ddb7f613b 100644 --- a/syft/format/syftjson/encoder_test.go +++ b/syft/format/syftjson/encoder_test.go @@ -141,10 +141,11 @@ func TestEncodeFullJSONDocument(t *testing.T) { RealPath: "/a/place/a", }), ), - Type: pkg.PythonPkg, - FoundBy: "the-cataloger-1", - Language: pkg.Python, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + Type: pkg.PythonPkg, + FoundBy: "the-cataloger-1", + Language: pkg.Python, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "package-1", Version: "1.0.1", @@ -164,8 +165,9 @@ func TestEncodeFullJSONDocument(t *testing.T) { RealPath: "/b/place/b", }), ), - Type: pkg.DebPkg, - FoundBy: "the-cataloger-2", + Type: pkg.DebPkg, + FoundBy: "the-cataloger-2", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DpkgDBEntry{ Package: "package-2", Version: "2.0.1", diff --git a/syft/format/syftjson/model/package.go b/syft/format/syftjson/model/package.go index 503709d1f16b..f05a4aca3917 100644 --- a/syft/format/syftjson/model/package.go +++ b/syft/format/syftjson/model/package.go @@ -24,16 +24,17 @@ type Package struct { // PackageBasicData contains non-ambiguous values (type-wise) from pkg.Package. type PackageBasicData struct { - ID string `json:"id"` - Name string `json:"name"` - Version string `json:"version"` - Type pkg.Type `json:"type"` - FoundBy string `json:"foundBy"` - Locations []file.Location `json:"locations"` - Licenses licenses `json:"licenses"` - Language pkg.Language `json:"language"` - CPEs cpes `json:"cpes"` - PURL string `json:"purl"` + ID string `json:"id"` + Name string `json:"name"` + Version string `json:"version"` + Type pkg.Type `json:"type"` + FoundBy string `json:"foundBy"` + Locations []file.Location `json:"locations"` + Licenses licenses `json:"licenses"` + Language pkg.Language `json:"language"` + CPEs cpes `json:"cpes"` + PURL string `json:"purl"` + Dependencies pkg.DependencyCompleteness `json:"dependencies"` } type cpes []CPE diff --git a/syft/format/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden b/syft/format/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden index 0ae05a3aa5fa..c29d70745b07 100644 --- a/syft/format/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden +++ b/syft/format/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden @@ -28,6 +28,7 @@ } ], "purl": "a-purl-2", + "dependencies": "complete", "metadataType": "python-package", "metadata": { "name": "package-1", @@ -63,6 +64,7 @@ } ], "purl": "pkg:deb/debian/package-2@2.0.1", + "dependencies": "complete", "metadataType": "dpkg-db-entry", "metadata": { "package": "package-2", diff --git a/syft/format/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden b/syft/format/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden index 6fc9041e9f13..a224ce783c69 100644 --- a/syft/format/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden +++ b/syft/format/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden @@ -29,6 +29,7 @@ } ], "purl": "a-purl-1", + "dependencies": "complete", "metadataType": "python-package", "metadata": { "name": "package-1", @@ -60,6 +61,7 @@ } ], "purl": "a-purl-2", + "dependencies": "complete", "metadataType": "dpkg-db-entry", "metadata": { "package": "package-2", diff --git a/syft/format/syftjson/test-fixtures/snapshot/TestImageEncoder.golden b/syft/format/syftjson/test-fixtures/snapshot/TestImageEncoder.golden index f013f2026a05..85f243ce98c3 100644 --- a/syft/format/syftjson/test-fixtures/snapshot/TestImageEncoder.golden +++ b/syft/format/syftjson/test-fixtures/snapshot/TestImageEncoder.golden @@ -30,6 +30,7 @@ } ], "purl": "a-purl-1", + "dependencies": "complete", "metadataType": "python-package", "metadata": { "name": "package-1", @@ -62,6 +63,7 @@ } ], "purl": "pkg:deb/debian/package-2@2.0.1", + "dependencies": "complete", "metadataType": "dpkg-db-entry", "metadata": { "package": "package-2", diff --git a/syft/format/syftjson/to_format_model.go b/syft/format/syftjson/to_format_model.go index a5cd128a8b48..91fc423c51a6 100644 --- a/syft/format/syftjson/to_format_model.go +++ b/syft/format/syftjson/to_format_model.go @@ -259,16 +259,17 @@ func toPackageModel(p pkg.Package, cfg EncoderConfig) model.Package { return model.Package{ PackageBasicData: model.PackageBasicData{ - ID: string(p.ID()), - Name: p.Name, - Version: p.Version, - Type: p.Type, - FoundBy: p.FoundBy, - Locations: p.Locations.ToSlice(), - Licenses: licenses, - Language: p.Language, - CPEs: cpes, - PURL: p.PURL, + ID: string(p.ID()), + Name: p.Name, + Version: p.Version, + Type: p.Type, + FoundBy: p.FoundBy, + Locations: p.Locations.ToSlice(), + Licenses: licenses, + Language: p.Language, + CPEs: cpes, + PURL: p.PURL, + Dependencies: p.Dependencies, }, PackageCustomData: model.PackageCustomData{ MetadataType: metadataType(p.Metadata, cfg.Legacy), diff --git a/syft/format/syftjson/to_syft_model.go b/syft/format/syftjson/to_syft_model.go index 154b8fa8e657..8d12a5449ba4 100644 --- a/syft/format/syftjson/to_syft_model.go +++ b/syft/format/syftjson/to_syft_model.go @@ -338,16 +338,17 @@ func toSyftPackage(p model.Package, idAliases map[string]string) pkg.Package { } out := pkg.Package{ - Name: p.Name, - Version: p.Version, - FoundBy: p.FoundBy, - Locations: file.NewLocationSet(p.Locations...), - Licenses: pkg.NewLicenseSet(toSyftLicenses(p.Licenses)...), - Language: p.Language, - Type: p.Type, - CPEs: cpes, - PURL: p.PURL, - Metadata: p.Metadata, + Name: p.Name, + Version: p.Version, + FoundBy: p.FoundBy, + Locations: file.NewLocationSet(p.Locations...), + Licenses: pkg.NewLicenseSet(toSyftLicenses(p.Licenses)...), + Language: p.Language, + Type: p.Type, + CPEs: cpes, + PURL: p.PURL, + Dependencies: p.Dependencies, + Metadata: p.Metadata, } // we don't know if this package ID is truly unique, however, we need to trust the user input in case there are diff --git a/syft/pkg/cataloger/alpine/cataloger_test.go b/syft/pkg/cataloger/alpine/cataloger_test.go index fff8e77f4ed3..f1a0738ecfa0 100644 --- a/syft/pkg/cataloger/alpine/cataloger_test.go +++ b/syft/pkg/cataloger/alpine/cataloger_test.go @@ -23,7 +23,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL-3.0-or-later", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "bash", OriginPackage: "bash", @@ -52,7 +53,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL-2.0-only", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "busybox-binsh", OriginPackage: "busybox", @@ -81,7 +83,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "musl", OriginPackage: "musl", @@ -108,7 +111,8 @@ func TestApkDBCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL-2.0-or-later", dbLocation), ), - Locations: file.NewLocationSet(dbLocation), + Locations: file.NewLocationSet(dbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "readline", OriginPackage: "readline", diff --git a/syft/pkg/cataloger/alpine/package.go b/syft/pkg/cataloger/alpine/package.go index 69c8a8d185ed..89041553aac6 100644 --- a/syft/pkg/cataloger/alpine/package.go +++ b/syft/pkg/cataloger/alpine/package.go @@ -20,13 +20,14 @@ func newPackage(d parsedData, release *linux.Release, dbLocation file.Location) } p := pkg.Package{ - Name: d.Package, - Version: d.Version, - Locations: file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation, licenseStrings...)...), - PURL: packageURL(d.ApkDBEntry, release), - Type: pkg.ApkPkg, - Metadata: d.ApkDBEntry, + Name: d.Package, + Version: d.Version, + Locations: file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation, licenseStrings...)...), + PURL: packageURL(d.ApkDBEntry, release), + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: d.ApkDBEntry, } p.SetID() diff --git a/syft/pkg/cataloger/alpine/parse_apk_db_test.go b/syft/pkg/cataloger/alpine/parse_apk_db_test.go index 7918f38f652a..be2523fad1e8 100644 --- a/syft/pkg/cataloger/alpine/parse_apk_db_test.go +++ b/syft/pkg/cataloger/alpine/parse_apk_db_test.go @@ -90,7 +90,8 @@ func TestSinglePackageDetails(t *testing.T) { pkg.NewLicense("BSD"), pkg.NewLicense("GPL2+"), ), - Type: pkg.ApkPkg, + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "musl-utils", OriginPackage: "musl", @@ -177,7 +178,8 @@ func TestSinglePackageDetails(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - Type: pkg.ApkPkg, + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "alpine-baselayout-data", OriginPackage: "alpine-baselayout", @@ -221,8 +223,8 @@ func TestSinglePackageDetails(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - Type: pkg.ApkPkg, - PURL: "", + Type: pkg.ApkPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ApkDBEntry{ Package: "alpine-baselayout", OriginPackage: "alpine-baselayout", diff --git a/syft/pkg/cataloger/arch/cataloger_test.go b/syft/pkg/cataloger/arch/cataloger_test.go index e61525246125..919fa1b6d4d6 100644 --- a/syft/pkg/cataloger/arch/cataloger_test.go +++ b/syft/pkg/cataloger/arch/cataloger_test.go @@ -34,7 +34,8 @@ func TestAlpmCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", treeSitterDbLocation), ), - Locations: file.NewLocationSet(treeSitterDbLocation), + Locations: file.NewLocationSet(treeSitterDbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ BasePackage: "tree-sitter", Package: "tree-sitter", @@ -60,7 +61,8 @@ func TestAlpmCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPL3", emacsDbLocation), ), - Locations: file.NewLocationSet(emacsDbLocation), + Locations: file.NewLocationSet(emacsDbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ BasePackage: "emacs", Package: "emacs", @@ -86,6 +88,7 @@ func TestAlpmCataloger(t *testing.T) { fuzzyDbLocation, file.NewLocation("var/lib/pacman/local/fuzzy-1.2-3/files"), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ Package: "fuzzy", Version: "1.2-3", @@ -103,11 +106,12 @@ func TestAlpmCataloger(t *testing.T) { } madeupPkg := pkg.Package{ - Name: "madeup", - Version: "20.30-4", - Type: pkg.AlpmPkg, - FoundBy: "alpm-db-cataloger", - Locations: file.NewLocationSet(madeupDbLocation), + Name: "madeup", + Version: "20.30-4", + Type: pkg.AlpmPkg, + FoundBy: "alpm-db-cataloger", + Locations: file.NewLocationSet(madeupDbLocation), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ Package: "madeup", Version: "20.30-4", @@ -131,6 +135,7 @@ func TestAlpmCataloger(t *testing.T) { file.NewLocation("var/lib/pacman/local/gmp-6.2.1-2/files"), file.NewLocation("var/lib/pacman/local/gmp-6.2.1-2/mtree"), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.AlpmDBEntry{ BasePackage: "gmp", Package: "gmp", diff --git a/syft/pkg/cataloger/arch/package.go b/syft/pkg/cataloger/arch/package.go index 88b557c76f5d..9bb36ff1da4b 100644 --- a/syft/pkg/cataloger/arch/package.go +++ b/syft/pkg/cataloger/arch/package.go @@ -16,13 +16,14 @@ func newPackage(m *parsedData, release *linux.Release, dbLocation file.Location, locs.Add(otherLocations...) p := pkg.Package{ - Name: m.Package, - Version: m.Version, - Locations: locs, - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation.WithoutAnnotations(), licenseCandidates...)...), - Type: pkg.AlpmPkg, - PURL: packageURL(m, release), - Metadata: m.AlpmDBEntry, + Name: m.Package, + Version: m.Version, + Locations: locs, + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation.WithoutAnnotations(), licenseCandidates...)...), + Type: pkg.AlpmPkg, + PURL: packageURL(m, release), + Dependencies: pkg.CompleteDependencies, + Metadata: m.AlpmDBEntry, } p.SetID() diff --git a/syft/pkg/cataloger/binary/classifier_package.go b/syft/pkg/cataloger/binary/classifier_package.go index a2ed4ab6de14..9b68775bf184 100644 --- a/syft/pkg/cataloger/binary/classifier_package.go +++ b/syft/pkg/cataloger/binary/classifier_package.go @@ -35,6 +35,9 @@ func newClassifierPackage(classifier Classifier, location file.Location, matchMe Type: pkg.BinaryPkg, CPEs: cpes, FoundBy: catalogerName, + // classifiers are limited to identifying package identities, but have no information about dependencies. + // Furthermore, we have no understanding about the mechanisms for dependency resolution for these packages. + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.BinarySignature{ Matches: []pkg.ClassifierMatch{ { diff --git a/syft/pkg/cataloger/binary/elf_package.go b/syft/pkg/cataloger/binary/elf_package.go index 81e4384d1c30..58122d10329d 100644 --- a/syft/pkg/cataloger/binary/elf_package.go +++ b/syft/pkg/cataloger/binary/elf_package.go @@ -16,7 +16,10 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p PURL: packageURL(metadata), Type: pkgType(metadata.Type), Locations: locations, - Metadata: metadata.ELFBinaryPackageNoteJSONPayload, + // though we can look for shared libs, we cannot see static dependencies nor dynamic dependencies using dlopen. + // this means that, even in cases where the dep info is actually complete, we can't programmatically determine that. + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: metadata.ELFBinaryPackageNoteJSONPayload, } p.SetID() diff --git a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go index 0325b3083ad3..4e2e90c32419 100644 --- a/syft/pkg/cataloger/binary/elf_package_cataloger_test.go +++ b/syft/pkg/cataloger/binary/elf_package_cataloger_test.go @@ -35,7 +35,8 @@ func Test_ELF_Package_Cataloger(t *testing.T) { pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, ), - Type: pkg.BinaryPkg, + Type: pkg.BinaryPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "testfixture", Vendor: "syft", @@ -56,7 +57,8 @@ func Test_ELF_Package_Cataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"}, ), - Type: pkg.BinaryPkg, + Type: pkg.BinaryPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "testfixture", Vendor: "syft", @@ -80,8 +82,9 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Licenses: pkg.NewLicenseSet(), - Type: pkg.RpmPkg, + Licenses: pkg.NewLicenseSet(), + Type: pkg.RpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "rpm", Architecture: "x86_64", @@ -102,8 +105,9 @@ func Test_ELF_Package_Cataloger(t *testing.T) { file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Licenses: pkg.NewLicenseSet(), - Type: pkg.RpmPkg, + Licenses: pkg.NewLicenseSet(), + Type: pkg.RpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "rpm", Architecture: "arm", diff --git a/syft/pkg/cataloger/binary/elf_package_test.go b/syft/pkg/cataloger/binary/elf_package_test.go index 689e259d1f12..c4b585543b76 100644 --- a/syft/pkg/cataloger/binary/elf_package_test.go +++ b/syft/pkg/cataloger/binary/elf_package_test.go @@ -154,10 +154,11 @@ func Test_newELFPackage(t *testing.T) { }, expected: pkg.Package{ - Name: "syfttestfixture", - Version: "0.01", - Type: "binary", - PURL: "pkg:generic/syftsys/syfttestfixture@0.01", + Name: "syfttestfixture", + Version: "0.01", + Type: "binary", + PURL: "pkg:generic/syftsys/syfttestfixture@0.01", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{ Type: "binary", System: "syftsys", diff --git a/syft/pkg/cataloger/cpp/package.go b/syft/pkg/cataloger/cpp/package.go index bc003ea7f5fe..ff9e4b7f2588 100644 --- a/syft/pkg/cataloger/cpp/package.go +++ b/syft/pkg/cataloger/cpp/package.go @@ -67,35 +67,43 @@ func splitConanRef(ref string) *conanRef { } func newConanfilePackage(m pkg.ConanfileEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) + // though a conanfile is a listing of direct dependencies, we are not capturing these today, so are forced to answer unknown + return newConanPackage(m.Ref, m, pkg.UnknownDependencyCompleteness, locations...) } -func newConanlockPackage(m pkg.ConanV1LockEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) +func newConanlockV1Package(m pkg.ConanV1LockEntry, locations ...file.Location) *pkg.Package { + // conan.lock is primarily used to lock the dependency graph at specific versions to ensure consistent builds, + // and the dependency tree can be inferred from the contents (distinguishing between direct and transitive dependencies) + return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...) } -func newConanReferencePackage(m pkg.ConanV2LockEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) +func newConanLockv2Package(m pkg.ConanV2LockEntry, locations ...file.Location) *pkg.Package { + // conan.lock is primarily used to lock the dependency graph at specific versions to ensure consistent builds, + // and the dependency tree can be inferred from the contents (distinguishing between direct and transitive dependencies) + return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...) } func newConaninfoPackage(m pkg.ConaninfoEntry, locations ...file.Location) *pkg.Package { - return newConanPackage(m.Ref, m, locations...) + // conaninfo.txt is generated during the build and contains detailed information about the entire dependency tree, + // and today the codebase does infer direct dependencies from this source + return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...) } -func newConanPackage(refStr string, metadata any, locations ...file.Location) *pkg.Package { +func newConanPackage(refStr string, metadata any, dep pkg.DependencyCompleteness, locations ...file.Location) *pkg.Package { ref := splitConanRef(refStr) if ref == nil { return nil } p := pkg.Package{ - Name: ref.Name, - Version: ref.Version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(ref), - Language: pkg.CPP, - Type: pkg.ConanPkg, - Metadata: metadata, + Name: ref.Name, + Version: ref.Version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(ref), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: dep, + Metadata: metadata, } p.SetID() diff --git a/syft/pkg/cataloger/cpp/parse_conanfile.go b/syft/pkg/cataloger/cpp/parse_conanfile.go index 2885b6f71b51..eb5f2f6e39f1 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile.go @@ -22,11 +22,12 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment, r := bufio.NewReader(reader) inRequirements := false var pkgs []pkg.Package +loop: for { line, err := r.ReadString('\n') switch { case errors.Is(err, io.EOF): - return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") + break loop case err != nil: return nil, nil, fmt.Errorf("failed to parse conanfile.txt file: %w", err) } @@ -56,4 +57,5 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment, pkgs = append(pkgs, *p) } + return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") } diff --git a/syft/pkg/cataloger/cpp/parse_conanfile_test.go b/syft/pkg/cataloger/cpp/parse_conanfile_test.go index 65a4b9b0dbb3..9267dccccaf1 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile_test.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile_test.go @@ -14,67 +14,73 @@ func TestParseConanfile(t *testing.T) { fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) expected := []pkg.Package{ { - Name: "catch2", - Version: "2.13.8", - PURL: "pkg:conan/catch2@2.13.8", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "catch2", + Version: "2.13.8", + PURL: "pkg:conan/catch2@2.13.8", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ConanfileEntry{ Ref: "catch2/2.13.8", }, }, { - Name: "docopt.cpp", - Version: "0.6.3", - PURL: "pkg:conan/docopt.cpp@0.6.3", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "docopt.cpp", + Version: "0.6.3", + PURL: "pkg:conan/docopt.cpp@0.6.3", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ConanfileEntry{ Ref: "docopt.cpp/0.6.3", }, }, { - Name: "fmt", - Version: "8.1.1", - PURL: "pkg:conan/fmt@8.1.1", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "fmt", + Version: "8.1.1", + PURL: "pkg:conan/fmt@8.1.1", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ConanfileEntry{ Ref: "fmt/8.1.1", }, }, { - Name: "spdlog", - Version: "1.9.2", - PURL: "pkg:conan/my_user/spdlog@1.9.2?channel=my_channel", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "spdlog", + Version: "1.9.2", + PURL: "pkg:conan/my_user/spdlog@1.9.2?channel=my_channel", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ConanfileEntry{ Ref: "spdlog/1.9.2@my_user/my_channel#1234567%%987654", }, }, { - Name: "sdl", - Version: "2.0.20", - PURL: "pkg:conan/sdl@2.0.20", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "sdl", + Version: "2.0.20", + PURL: "pkg:conan/sdl@2.0.20", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ConanfileEntry{ Ref: "sdl/2.0.20#1234567%%987654", }, }, { - Name: "fltk", - Version: "1.3.8", - PURL: "pkg:conan/my_user/fltk@1.3.8?channel=my_channel", - Locations: fixtureLocationSet, - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "fltk", + Version: "1.3.8", + PURL: "pkg:conan/my_user/fltk@1.3.8?channel=my_channel", + Locations: fixtureLocationSet, + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ConanfileEntry{ Ref: "fltk/1.3.8@my_user/my_channel", }, diff --git a/syft/pkg/cataloger/cpp/parse_conaninfo_test.go b/syft/pkg/cataloger/cpp/parse_conaninfo_test.go index 3c7eb1bace56..9f12b09051c6 100644 --- a/syft/pkg/cataloger/cpp/parse_conaninfo_test.go +++ b/syft/pkg/cataloger/cpp/parse_conaninfo_test.go @@ -13,72 +13,78 @@ func TestParseConaninfo(t *testing.T) { fixture := "test-fixtures/conaninfo/mfast/1.2.2/my_user/my_channel/package/9d1f076b471417647c2022a78d5e2c1f834289ac/conaninfo.txt" expected := []pkg.Package{ { - Name: "mfast", - Version: "1.2.2", - PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "mfast", + Version: "1.2.2", + PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39", PackageID: "9d1f076b471417647c2022a78d5e2c1f834289ac", }, }, { - Name: "boost", - Version: "1.75.0", - PURL: "pkg:conan/boost@1.75.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "boost", + Version: "1.75.0", + PURL: "pkg:conan/boost@1.75.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "boost/1.75.0:dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978", PackageID: "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978", }, }, { - Name: "zlib", - Version: "1.2.13", - PURL: "pkg:conan/zlib@1.2.13", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "zlib", + Version: "1.2.13", + PURL: "pkg:conan/zlib@1.2.13", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "zlib/1.2.13:dfbe50feef7f3c6223a476cd5aeadb687084a646", PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646", }, }, { - Name: "bzip2", - Version: "1.0.8", - PURL: "pkg:conan/bzip2@1.0.8", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "bzip2", + Version: "1.0.8", + PURL: "pkg:conan/bzip2@1.0.8", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "bzip2/1.0.8:c32092bf4d4bb47cf962af898e02823f499b017e", PackageID: "c32092bf4d4bb47cf962af898e02823f499b017e", }, }, { - Name: "libbacktrace", - Version: "cci.20210118", - PURL: "pkg:conan/libbacktrace@cci.20210118", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "libbacktrace", + Version: "cci.20210118", + PURL: "pkg:conan/libbacktrace@cci.20210118", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "libbacktrace/cci.20210118:dfbe50feef7f3c6223a476cd5aeadb687084a646", PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646", }, }, { - Name: "tinyxml2", - Version: "9.0.0", - PURL: "pkg:conan/tinyxml2@9.0.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "tinyxml2", + Version: "9.0.0", + PURL: "pkg:conan/tinyxml2@9.0.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConaninfoEntry{ Ref: "tinyxml2/9.0.0:6557f18ca99c0b6a233f43db00e30efaa525e27e", PackageID: "6557f18ca99c0b6a233f43db00e30efaa525e27e", diff --git a/syft/pkg/cataloger/cpp/parse_conanlock.go b/syft/pkg/cataloger/cpp/parse_conanlock.go index 1a1aa4d124d0..cf2ab9e52b2a 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock.go @@ -89,7 +89,7 @@ func handleConanLockV1(cl conanLock, reader file.LocationReadCloser, parsedPkgRe Prev: node.Prev, } - p := newConanlockPackage( + p := newConanlockV1Package( metadata, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) @@ -113,7 +113,7 @@ func handleConanLockV2(cl conanLock, reader file.LocationReadCloser, indexToPkgM continue } - p := newConanReferencePackage( + p := newConanLockv2Package( reference, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) diff --git a/syft/pkg/cataloger/cpp/parse_conanlock_test.go b/syft/pkg/cataloger/cpp/parse_conanlock_test.go index 23fe24c28c4a..628e471b14bc 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock_test.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock_test.go @@ -13,12 +13,13 @@ func TestParseConanLock(t *testing.T) { fixture := "test-fixtures/conan.lock" expected := []pkg.Package{ { - Name: "mfast", - Version: "1.2.2", - PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "mfast", + Version: "1.2.2", + PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39", Options: pkg.KeyValues{ @@ -104,12 +105,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "boost", - Version: "1.75.0", - PURL: "pkg:conan/boost@1.75.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "boost", + Version: "1.75.0", + PURL: "pkg:conan/boost@1.75.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "boost/1.75.0#a9c318f067216f900900e044e7af4ab1", Options: pkg.KeyValues{ @@ -190,12 +192,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "zlib", - Version: "1.2.12", - PURL: "pkg:conan/zlib@1.2.12", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "zlib", + Version: "1.2.12", + PURL: "pkg:conan/zlib@1.2.12", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a", Options: pkg.KeyValues{ @@ -214,12 +217,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "bzip2", - Version: "1.0.8", - PURL: "pkg:conan/bzip2@1.0.8", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "bzip2", + Version: "1.0.8", + PURL: "pkg:conan/bzip2@1.0.8", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef", Options: []pkg.KeyValue{ @@ -242,12 +246,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "libbacktrace", - Version: "cci.20210118", - PURL: "pkg:conan/libbacktrace@cci.20210118", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "libbacktrace", + Version: "cci.20210118", + PURL: "pkg:conan/libbacktrace@cci.20210118", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab", Options: []pkg.KeyValue{ @@ -266,12 +271,13 @@ func TestParseConanLock(t *testing.T) { }, }, { - Name: "tinyxml2", - Version: "9.0.0", - PURL: "pkg:conan/tinyxml2@9.0.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "tinyxml2", + Version: "9.0.0", + PURL: "pkg:conan/tinyxml2@9.0.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV1LockEntry{ Ref: "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1", Options: []pkg.KeyValue{ @@ -337,12 +343,13 @@ func TestParseConanLockV2(t *testing.T) { fixture := "test-fixtures/conanlock-v2/conan.lock" expected := []pkg.Package{ { - Name: "matrix", - Version: "1.1", - PURL: "pkg:conan/matrix@1.1", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "matrix", + Version: "1.1", + PURL: "pkg:conan/matrix@1.1", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV2LockEntry{ Ref: "matrix/1.1#905c3f0babc520684c84127378fefdd0%1675278901.7527816", RecipeRevision: "905c3f0babc520684c84127378fefdd0", @@ -350,12 +357,13 @@ func TestParseConanLockV2(t *testing.T) { }, }, { - Name: "sound32", - Version: "1.0", - PURL: "pkg:conan/sound32@1.0", - Locations: file.NewLocationSet(file.NewLocation(fixture)), - Language: pkg.CPP, - Type: pkg.ConanPkg, + Name: "sound32", + Version: "1.0", + PURL: "pkg:conan/sound32@1.0", + Locations: file.NewLocationSet(file.NewLocation(fixture)), + Language: pkg.CPP, + Type: pkg.ConanPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.ConanV2LockEntry{ Ref: "sound32/1.0#83d4b7bf607b3b60a6546f8b58b5cdd7%1675278904.0791488", RecipeRevision: "83d4b7bf607b3b60a6546f8b58b5cdd7", diff --git a/syft/pkg/cataloger/dart/package.go b/syft/pkg/cataloger/dart/package.go index 99fad41337c1..de0e6807d739 100644 --- a/syft/pkg/cataloger/dart/package.go +++ b/syft/pkg/cataloger/dart/package.go @@ -21,7 +21,9 @@ func newPubspecLockPackage(name string, raw pubspecLockPackage, locations ...fil PURL: packageURL(metadata), Language: pkg.Dart, Type: pkg.DartPubPkg, - Metadata: metadata, + // since we capture no dependencies today we know that the dep info is unknown + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: metadata, } p.SetID() diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go index 5aa5fc702b56..65697ba2dfcb 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock_test.go @@ -14,12 +14,13 @@ func TestParsePubspecLock(t *testing.T) { fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) expected := []pkg.Package{ { - Name: "ale", - Version: "3.3.0", - PURL: "pkg:pub/ale@3.3.0?hosted_url=pub.hosted.org", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "ale", + Version: "3.3.0", + PURL: "pkg:pub/ale@3.3.0?hosted_url=pub.hosted.org", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DartPubspecLockEntry{ Name: "ale", Version: "3.3.0", @@ -27,72 +28,78 @@ func TestParsePubspecLock(t *testing.T) { }, }, { - Name: "analyzer", - Version: "0.40.7", - PURL: "pkg:pub/analyzer@0.40.7", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "analyzer", + Version: "0.40.7", + PURL: "pkg:pub/analyzer@0.40.7", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DartPubspecLockEntry{ Name: "analyzer", Version: "0.40.7", }, }, { - Name: "ansicolor", - Version: "1.1.1", - PURL: "pkg:pub/ansicolor@1.1.1", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "ansicolor", + Version: "1.1.1", + PURL: "pkg:pub/ansicolor@1.1.1", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DartPubspecLockEntry{ Name: "ansicolor", Version: "1.1.1", }, }, { - Name: "archive", - Version: "2.0.13", - PURL: "pkg:pub/archive@2.0.13", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "archive", + Version: "2.0.13", + PURL: "pkg:pub/archive@2.0.13", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DartPubspecLockEntry{ Name: "archive", Version: "2.0.13", }, }, { - Name: "args", - Version: "1.6.0", - PURL: "pkg:pub/args@1.6.0", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "args", + Version: "1.6.0", + PURL: "pkg:pub/args@1.6.0", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DartPubspecLockEntry{ Name: "args", Version: "1.6.0", }, }, { - Name: "flutter", - Version: "0.0.0", - PURL: "pkg:pub/flutter@0.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "flutter", + Version: "0.0.0", + PURL: "pkg:pub/flutter@0.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DartPubspecLockEntry{ Name: "flutter", Version: "0.0.0", }, }, { - Name: "key_binder", - Version: "1.11.20", - PURL: "pkg:pub/key_binder@1.11.20?vcs_url=git%40github.com:Workiva/key_binder.git%403f7b3a6350e73c7dcac45301c0e18fbd42af02f7", - Locations: fixtureLocationSet, - Language: pkg.Dart, - Type: pkg.DartPubPkg, + Name: "key_binder", + Version: "1.11.20", + PURL: "pkg:pub/key_binder@1.11.20?vcs_url=git%40github.com:Workiva/key_binder.git%403f7b3a6350e73c7dcac45301c0e18fbd42af02f7", + Locations: fixtureLocationSet, + Language: pkg.Dart, + Type: pkg.DartPubPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DartPubspecLockEntry{ Name: "key_binder", Version: "1.11.20", diff --git a/syft/pkg/cataloger/debian/cataloger_test.go b/syft/pkg/cataloger/debian/cataloger_test.go index 299d7338d442..40ed0bcf32db 100644 --- a/syft/pkg/cataloger/debian/cataloger_test.go +++ b/syft/pkg/cataloger/debian/cataloger_test.go @@ -36,7 +36,8 @@ func TestDpkgCataloger(t *testing.T) { file.NewLocation("/var/lib/dpkg/info/libpam-runtime.conffiles"), file.NewLocation("/usr/share/doc/libpam-runtime/copyright"), ), - Type: pkg.DebPkg, + Type: pkg.DebPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DpkgDBEntry{ Package: "libpam-runtime", Source: "pam", @@ -109,7 +110,8 @@ func TestDpkgCataloger(t *testing.T) { file.NewLocation("/var/lib/dpkg/status.d/libsqlite3-0.preinst"), file.NewLocation("/usr/share/doc/libsqlite3-0/copyright"), ), - Type: pkg.DebPkg, + Type: pkg.DebPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DpkgDBEntry{ Package: "libsqlite3-0", Source: "sqlite3", diff --git a/syft/pkg/cataloger/debian/package.go b/syft/pkg/cataloger/debian/package.go index db93ba8ebd15..3b1d24b66516 100644 --- a/syft/pkg/cataloger/debian/package.go +++ b/syft/pkg/cataloger/debian/package.go @@ -30,13 +30,14 @@ func newDpkgPackage(d pkg.DpkgDBEntry, dbLocation file.Location, resolver file.R locations.Add(evidence...) p := pkg.Package{ - Name: d.Package, - Version: d.Version, - Licenses: pkg.NewLicenseSet(licenses...), - Locations: locations, - PURL: packageURL(d, release), - Type: pkg.DebPkg, - Metadata: d, + Name: d.Package, + Version: d.Version, + Licenses: pkg.NewLicenseSet(licenses...), + Locations: locations, + PURL: packageURL(d, release), + Type: pkg.DebPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: d, } if resolver != nil { diff --git a/syft/pkg/cataloger/debian/parse_dpkg_db_test.go b/syft/pkg/cataloger/debian/parse_dpkg_db_test.go index 50ab3485ba4d..6a4b99436d9c 100644 --- a/syft/pkg/cataloger/debian/parse_dpkg_db_test.go +++ b/syft/pkg/cataloger/debian/parse_dpkg_db_test.go @@ -349,11 +349,12 @@ Installed-Size: 10kib `, want: []pkg.Package{ { - Name: "apt", - Type: "deb", - PURL: "pkg:deb/debian/apt?distro=debian-10", - Licenses: pkg.NewLicenseSet(), - Locations: file.NewLocationSet(file.NewLocation("place")), + Name: "apt", + Type: "deb", + PURL: "pkg:deb/debian/apt?distro=debian-10", + Licenses: pkg.NewLicenseSet(), + Locations: file.NewLocationSet(file.NewLocation("place")), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DpkgDBEntry{ Package: "apt", InstalledSize: 10240, diff --git a/syft/pkg/cataloger/dotnet/package.go b/syft/pkg/cataloger/dotnet/package.go index 0d1563cd7dfa..6c59f089c209 100644 --- a/syft/pkg/cataloger/dotnet/package.go +++ b/syft/pkg/cataloger/dotnet/package.go @@ -22,13 +22,14 @@ func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations . } p := &pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(m), - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, - Metadata: m, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(m), + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go b/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go index 84878c86c1c8..20f81ae9cd89 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_deps_test.go @@ -20,36 +20,39 @@ func TestParseDotnetDeps(t *testing.T) { fixture := "test-fixtures/TestLibrary.deps.json" fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture)) rootPkg := pkg.Package{ - Name: "TestLibrary", - Version: "1.0.0", - PURL: "pkg:nuget/TestLibrary@1.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "TestLibrary", + Version: "1.0.0", + PURL: "pkg:nuget/TestLibrary@1.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "TestLibrary", Version: "1.0.0", }, } testCommon := pkg.Package{ - Name: "TestCommon", - Version: "1.0.0", - PURL: "pkg:nuget/TestCommon@1.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "TestCommon", + Version: "1.0.0", + PURL: "pkg:nuget/TestCommon@1.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "TestCommon", Version: "1.0.0", }, } awssdkcore := pkg.Package{ - Name: "AWSSDK.Core", - Version: "3.7.10.6", - PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "AWSSDK.Core", + Version: "3.7.10.6", + PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "AWSSDK.Core", Version: "3.7.10.6", @@ -59,12 +62,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftDependencyInjectionAbstractions := pkg.Package{ - Name: "Microsoft.Extensions.DependencyInjection.Abstractions", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.DependencyInjection.Abstractions", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.DependencyInjection.Abstractions", Version: "6.0.0", @@ -74,12 +78,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftDependencyInjection := pkg.Package{ - Name: "Microsoft.Extensions.DependencyInjection", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.DependencyInjection", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.DependencyInjection", Version: "6.0.0", @@ -89,12 +94,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftLoggingAbstractions := pkg.Package{ - Name: "Microsoft.Extensions.Logging.Abstractions", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Logging.Abstractions", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Logging.Abstractions", Version: "6.0.0", @@ -104,12 +110,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftExtensionsLogging := pkg.Package{ - Name: "Microsoft.Extensions.Logging", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Logging", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Logging", Version: "6.0.0", @@ -119,12 +126,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftExtensionsOptions := pkg.Package{ - Name: "Microsoft.Extensions.Options", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Options", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Options", Version: "6.0.0", @@ -134,12 +142,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } msftExtensionsPrimitives := pkg.Package{ - Name: "Microsoft.Extensions.Primitives", - Version: "6.0.0", - PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Microsoft.Extensions.Primitives", + Version: "6.0.0", + PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Microsoft.Extensions.Primitives", Version: "6.0.0", @@ -149,12 +158,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } newtonsoftJson := pkg.Package{ - Name: "Newtonsoft.Json", - Version: "13.0.1", - PURL: "pkg:nuget/Newtonsoft.Json@13.0.1", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Newtonsoft.Json", + Version: "13.0.1", + PURL: "pkg:nuget/Newtonsoft.Json@13.0.1", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Newtonsoft.Json", Version: "13.0.1", @@ -164,12 +174,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } serilogSinksConsole := pkg.Package{ - Name: "Serilog.Sinks.Console", - Version: "4.0.1", - PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Serilog.Sinks.Console", + Version: "4.0.1", + PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Serilog.Sinks.Console", Version: "4.0.1", @@ -179,12 +190,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } serilog := pkg.Package{ - Name: "Serilog", - Version: "2.10.0", - PURL: "pkg:nuget/Serilog@2.10.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "Serilog", + Version: "2.10.0", + PURL: "pkg:nuget/Serilog@2.10.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "Serilog", Version: "2.10.0", @@ -194,12 +206,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } systemDiagnosticsDiagnosticsource := pkg.Package{ - Name: "System.Diagnostics.DiagnosticSource", - Version: "6.0.0", - PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "System.Diagnostics.DiagnosticSource", + Version: "6.0.0", + PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "System.Diagnostics.DiagnosticSource", Version: "6.0.0", @@ -209,12 +222,13 @@ func TestParseDotnetDeps(t *testing.T) { }, } systemRuntimeCompilerServicesUnsafe := pkg.Package{ - Name: "System.Runtime.CompilerServices.Unsafe", - Version: "6.0.0", - PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0", - Locations: fixtureLocationSet, - Language: pkg.Dotnet, - Type: pkg.DotnetPkg, + Name: "System.Runtime.CompilerServices.Unsafe", + Version: "6.0.0", + PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0", + Locations: fixtureLocationSet, + Language: pkg.Dotnet, + Type: pkg.DotnetPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.DotnetDepsEntry{ Name: "System.Runtime.CompilerServices.Unsafe", Version: "6.0.0", diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go index 4ea4d1c18d72..40fa6c68cda8 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable.go @@ -9,7 +9,7 @@ import ( "github.com/saferwall/pe" - version "github.com/anchore/go-version" + "github.com/anchore/go-version" "github.com/anchore/packageurl-go" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" @@ -44,7 +44,7 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi return nil, nil, fmt.Errorf("unable to parse version resources in PE file: %w", err) } - dotNetPkg, err := buildDotNetPackage(versionResources, f) + dotNetPkg, err := buildDotNetPEPackage(versionResources, f) if err != nil { log.Tracef("unable to build dotnet package for: %v %v", f.RealPath, err) return nil, nil, err @@ -53,14 +53,14 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi return []pkg.Package{dotNetPkg}, nil, nil } -func buildDotNetPackage(versionResources map[string]string, f file.LocationReadCloser) (dnpkg pkg.Package, err error) { +func buildDotNetPEPackage(versionResources map[string]string, f file.LocationReadCloser) (dnpkg pkg.Package, err error) { name := findName(versionResources) if name == "" { return dnpkg, fmt.Errorf("unable to find PE name in file") } - version := findVersion(versionResources) - if version == "" { + ver := findVersion(versionResources) + if ver == "" { return dnpkg, fmt.Errorf("unable to find PE version in file") } @@ -76,12 +76,14 @@ func buildDotNetPackage(versionResources map[string]string, f file.LocationReadC dnpkg = pkg.Package{ Name: name, - Version: version, + Version: ver, Locations: file.NewLocationSet(f.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), Type: pkg.DotnetPkg, Language: pkg.Dotnet, - PURL: portableExecutablePackageURL(name, version), - Metadata: metadata, + PURL: portableExecutablePackageURL(name, ver), + // by nature PE file metadata does not have any dependency information, thus we are forced to claim unknown completeness + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: metadata, } dnpkg.SetID() diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go index 2be417d6a8e3..08f499e2d02d 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_portable_executable_test.go @@ -32,8 +32,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "Assembly Version": "3.14.2.11", }, expectedPackage: pkg.Package{ - Name: "Active Directory Authentication Library", - Version: "3.14.40721.0918", + Name: "Active Directory Authentication Library", + Version: "3.14.40721.0918", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DotnetPortableExecutableEntry{ AssemblyVersion: "3.14.2.11", LegalCopyright: "Copyright (c) Microsoft Corporation. All rights reserved.", @@ -57,9 +58,10 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "4.6.25512.01 built by: dlab-DDVSOWINAGE016. Commit Hash: d0d5c7b49271cadb6d97de26d8e623e98abdc8db", }, expectedPackage: pkg.Package{ - Name: "äbFileVersi on", - Version: "4.6.25512.01", - PURL: "pkg:nuget/%C3%A4bFileVersi%20on@4.6.25512.01", + Name: "äbFileVersi on", + Version: "4.6.25512.01", + PURL: "pkg:nuget/%C3%A4bFileVersi%20on@4.6.25512.01", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.DotnetPortableExecutableEntry{ LegalCopyright: "© Microsoft Corporation. All rights reserved.", InternalName: "äb\x01FileVersion", @@ -82,8 +84,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "4.7.3190.0", }, expectedPackage: pkg.Package{ - Name: "System.Data.Linq.dll", - Version: "4.7.3190.0", + Name: "System.Data.Linq.dll", + Version: "4.7.3190.0", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -99,8 +102,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "8.4.0", }, expectedPackage: pkg.Package{ - Name: "The curl executable", - Version: "8.4.0", + Name: "The curl executable", + Version: "8.4.0", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -116,8 +120,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "8.0.1", }, expectedPackage: pkg.Package{ - Name: "Prometheus.AspNetCore.dll", - Version: "8.0.1", + Name: "Prometheus.AspNetCore.dll", + Version: "8.0.1", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -132,8 +137,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "1, 0, 0, 0", }, expectedPackage: pkg.Package{ - Name: "Hidden Input", - Version: "1, 0, 0, 0", + Name: "Hidden Input", + Version: "1, 0, 0, 0", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -148,8 +154,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.23.2", }, expectedPackage: pkg.Package{ - Name: "SQLite", - Version: "3.23.2", + Name: "SQLite", + Version: "3.23.2", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -165,8 +172,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "80.1.7.92", }, expectedPackage: pkg.Package{ - Name: "Brave Browser", - Version: "80.1.7.92", + Name: "Brave Browser", + Version: "80.1.7.92", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -177,8 +185,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "80.1.7.92", }, expectedPackage: pkg.Package{ - Name: "Better version", - Version: "80.1.7.92", + Name: "Better version", + Version: "80.1.7.92", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -189,8 +198,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "80.1.7", }, expectedPackage: pkg.Package{ - Name: "Better version", - Version: "80.1.7.92", + Name: "Better version", + Version: "80.1.7.92", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -201,8 +211,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", }, expectedPackage: pkg.Package{ - Name: "Higher semantic version Product Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Higher semantic version Product Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -213,8 +224,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.0", }, expectedPackage: pkg.Package{ - Name: "Higher semantic version File Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Higher semantic version File Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -225,8 +237,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", }, expectedPackage: pkg.Package{ - Name: "Invalid semantic version File Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Invalid semantic version File Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -237,8 +250,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", }, expectedPackage: pkg.Package{ - Name: "Invalid semantic version File Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Invalid semantic version File Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -249,8 +263,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "A", }, expectedPackage: pkg.Package{ - Name: "Invalid semantic version Product Version", - Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Name: "Invalid semantic version Product Version", + Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, { @@ -261,8 +276,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) { "ProductVersion": "3.0.0", }, expectedPackage: pkg.Package{ - Name: "Semantically equal falls through, chooses File Version with more components", - Version: "3.0.0.0", + Name: "Semantically equal falls through, chooses File Version with more components", + Version: "3.0.0.0", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, } @@ -273,7 +289,7 @@ func TestParseDotnetPortableExecutable(t *testing.T) { f := file.LocationReadCloser{ Location: location, } - got, err := buildDotNetPackage(tc.versionResources, f) + got, err := buildDotNetPEPackage(tc.versionResources, f) assert.NoErrorf(t, err, "failed to build package from version resources: %+v", tc.versionResources) // ignore certain metadata diff --git a/syft/pkg/cataloger/elixir/package.go b/syft/pkg/cataloger/elixir/package.go index 50cd3f28f12c..6eb48efa3205 100644 --- a/syft/pkg/cataloger/elixir/package.go +++ b/syft/pkg/cataloger/elixir/package.go @@ -14,7 +14,9 @@ func newPackage(d pkg.ElixirMixLockEntry, locations ...file.Location) pkg.Packag Locations: file.NewLocationSet(locations...), PURL: packageURL(d), Type: pkg.HexPkg, - Metadata: d, + // we do not attempt to parse dependencies from the mix.lock file + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: d, } p.SetID() diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go index a8e09e257172..e933b09e5225 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go @@ -13,12 +13,13 @@ func TestParseMixLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation("test-fixtures/mix.lock")) expected := []pkg.Package{ { - Name: "castore", - Version: "0.1.17", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/castore@0.1.17", + Name: "castore", + Version: "0.1.17", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/castore@0.1.17", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "castore", Version: "0.1.17", @@ -27,12 +28,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "connection", - Version: "1.1.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/connection@1.1.0", + Name: "connection", + Version: "1.1.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/connection@1.1.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "connection", Version: "1.1.0", @@ -41,12 +43,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "cowboy", - Version: "2.9.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/cowboy@2.9.0", + Name: "cowboy", + Version: "2.9.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/cowboy@2.9.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "cowboy", Version: "2.9.0", @@ -55,12 +58,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "cowboy_telemetry", - Version: "0.4.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/cowboy_telemetry@0.4.0", + Name: "cowboy_telemetry", + Version: "0.4.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/cowboy_telemetry@0.4.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "cowboy_telemetry", Version: "0.4.0", @@ -69,12 +73,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "cowlib", - Version: "2.11.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/cowlib@2.11.0", + Name: "cowlib", + Version: "2.11.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/cowlib@2.11.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "cowlib", Version: "2.11.0", @@ -83,12 +88,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "db_connection", - Version: "2.4.2", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/db_connection@2.4.2", + Name: "db_connection", + Version: "2.4.2", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/db_connection@2.4.2", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "db_connection", Version: "2.4.2", @@ -97,12 +103,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "decimal", - Version: "2.0.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/decimal@2.0.0", + Name: "decimal", + Version: "2.0.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/decimal@2.0.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "decimal", Version: "2.0.0", @@ -111,12 +118,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "earmark_parser", - Version: "1.4.25", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/earmark_parser@1.4.25", + Name: "earmark_parser", + Version: "1.4.25", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/earmark_parser@1.4.25", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "earmark_parser", Version: "1.4.25", @@ -125,12 +133,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "ecto", - Version: "3.8.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/ecto@3.8.1", + Name: "ecto", + Version: "3.8.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/ecto@3.8.1", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "ecto", Version: "3.8.1", @@ -139,12 +148,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "ecto_sql", - Version: "3.8.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/ecto_sql@3.8.1", + Name: "ecto_sql", + Version: "3.8.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/ecto_sql@3.8.1", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "ecto_sql", Version: "3.8.1", @@ -153,12 +163,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "esbuild", - Version: "0.5.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/esbuild@0.5.0", + Name: "esbuild", + Version: "0.5.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/esbuild@0.5.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "esbuild", Version: "0.5.0", @@ -167,12 +178,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "ex_doc", - Version: "0.28.4", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/ex_doc@0.28.4", + Name: "ex_doc", + Version: "0.28.4", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/ex_doc@0.28.4", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "ex_doc", Version: "0.28.4", @@ -181,12 +193,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "gettext", - Version: "0.19.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/gettext@0.19.1", + Name: "gettext", + Version: "0.19.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/gettext@0.19.1", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "gettext", Version: "0.19.1", @@ -195,12 +208,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "hpax", - Version: "0.1.1", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/hpax@0.1.1", + Name: "hpax", + Version: "0.1.1", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/hpax@0.1.1", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "hpax", Version: "0.1.1", @@ -209,12 +223,13 @@ func TestParseMixLock(t *testing.T) { }, }, { - Name: "jason", - Version: "1.3.0", - Language: pkg.Elixir, - Type: pkg.HexPkg, - Locations: locations, - PURL: "pkg:hex/jason@1.3.0", + Name: "jason", + Version: "1.3.0", + Language: pkg.Elixir, + Type: pkg.HexPkg, + Locations: locations, + PURL: "pkg:hex/jason@1.3.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ElixirMixLockEntry{ Name: "jason", Version: "1.3.0", diff --git a/syft/pkg/cataloger/erlang/package.go b/syft/pkg/cataloger/erlang/package.go index 60157996ce47..f6d9ef3203d5 100644 --- a/syft/pkg/cataloger/erlang/package.go +++ b/syft/pkg/cataloger/erlang/package.go @@ -14,7 +14,9 @@ func newPackageFromRebar(d pkg.ErlangRebarLockEntry, locations ...file.Location) Locations: file.NewLocationSet(locations...), PURL: packageURLFromRebar(d), Type: pkg.HexPkg, - Metadata: d, + // we do not attempt to parse dependencies from the rebar.lock file + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: d, } p.SetID() @@ -42,7 +44,9 @@ func newPackageFromOTP(name, version string, locations ...file.Location) pkg.Pac Language: pkg.Erlang, Locations: file.NewLocationSet(locations...), PURL: packageURLFromOTP(name, version), - Type: pkg.ErlangOTPPkg, + // we do not attempt to parse dependencies from app files + Dependencies: pkg.UnknownDependencyCompleteness, + Type: pkg.ErlangOTPPkg, } p.SetID() diff --git a/syft/pkg/cataloger/erlang/parse_otp_app_test.go b/syft/pkg/cataloger/erlang/parse_otp_app_test.go index 93c0aa238a92..2886dd554bbd 100644 --- a/syft/pkg/cataloger/erlang/parse_otp_app_test.go +++ b/syft/pkg/cataloger/erlang/parse_otp_app_test.go @@ -18,11 +18,12 @@ func TestParseOTPApplication(t *testing.T) { fixture: "test-fixtures/rabbitmq.app", expected: []pkg.Package{ { - Name: "rabbit", - Version: "3.12.10", - Language: pkg.Erlang, - Type: pkg.ErlangOTPPkg, - PURL: "pkg:otp/rabbit@3.12.10", + Name: "rabbit", + Version: "3.12.10", + Language: pkg.Erlang, + Type: pkg.ErlangOTPPkg, + PURL: "pkg:otp/rabbit@3.12.10", + Dependencies: pkg.UnknownDependencyCompleteness, }, }, }, diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go index 67e309cd313c..aa7234986d10 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go @@ -18,11 +18,12 @@ func TestParseRebarLock(t *testing.T) { fixture: "test-fixtures/rebar.lock", expected: []pkg.Package{ { - Name: "certifi", - Version: "2.9.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/certifi@2.9.0", + Name: "certifi", + Version: "2.9.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/certifi@2.9.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "certifi", Version: "2.9.0", @@ -31,11 +32,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "idna", - Version: "6.1.1", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/idna@6.1.1", + Name: "idna", + Version: "6.1.1", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/idna@6.1.1", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "idna", Version: "6.1.1", @@ -44,11 +46,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "metrics", - Version: "1.0.1", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/metrics@1.0.1", + Name: "metrics", + Version: "1.0.1", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/metrics@1.0.1", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "metrics", Version: "1.0.1", @@ -57,11 +60,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "mimerl", - Version: "1.2.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/mimerl@1.2.0", + Name: "mimerl", + Version: "1.2.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/mimerl@1.2.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "mimerl", Version: "1.2.0", @@ -70,11 +74,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "parse_trans", - Version: "3.3.1", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/parse_trans@3.3.1", + Name: "parse_trans", + Version: "3.3.1", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/parse_trans@3.3.1", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "parse_trans", Version: "3.3.1", @@ -83,11 +88,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "ssl_verify_fun", - Version: "1.1.6", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/ssl_verify_fun@1.1.6", + Name: "ssl_verify_fun", + Version: "1.1.6", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/ssl_verify_fun@1.1.6", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "ssl_verify_fun", Version: "1.1.6", @@ -96,11 +102,12 @@ func TestParseRebarLock(t *testing.T) { }, }, { - Name: "unicode_util_compat", - Version: "0.7.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/unicode_util_compat@0.7.0", + Name: "unicode_util_compat", + Version: "0.7.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/unicode_util_compat@0.7.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "unicode_util_compat", Version: "0.7.0", @@ -117,11 +124,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"bcrypt">>, <<"A6763BD4E1AF46D34776F85B7995E63A02978DE110C077E9570ED17006E03386">>}, // {<<"bcrypt">>, <<"3418821BC17CE6E96A4A77D1A88D7485BF783E212069FACFC79510AFBFF95352">>}, { - Name: "bcrypt", - Version: "1.1.5", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/bcrypt@1.1.5", + Name: "bcrypt", + Version: "1.1.5", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/bcrypt@1.1.5", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "bcrypt", Version: "1.1.5", @@ -134,11 +142,12 @@ func TestParseRebarLock(t *testing.T) { // {ref,"14308ab927cfa69324742c3de720578094e0bb19"}}, // 1}, { - Name: "bson", - Version: "14308ab927cfa69324742c3de720578094e0bb19", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19", + Name: "bson", + Version: "14308ab927cfa69324742c3de720578094e0bb19", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "bson", Version: "14308ab927cfa69324742c3de720578094e0bb19", @@ -148,11 +157,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"certifi">>, <<"6F2A475689DD47F19FB74334859D460A2DC4E3252A3324BD2111B8F0429E7E21">>}, {<<"stdout_formatter">>, <<"EC24868D8619757A68F0798357C7190807A1CFC42CE90C18C23760E59249A21A">>}, // {<<"certifi">>, <<"266DA46BDB06D6C6D35FDE799BCB28D36D985D424AD7C08B5BB48F5B5CDD4641">>}, { - Name: "certifi", - Version: "2.9.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/certifi@2.9.0", + Name: "certifi", + Version: "2.9.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/certifi@2.9.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "certifi", Version: "2.9.0", @@ -164,11 +174,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"stdout_formatter">>, <<"EC24868D8619757A68F0798357C7190807A1CFC42CE90C18C23760E59249A21A">>}, // {<<"stdout_formatter">>, <<"6B9CAAD8930006F9BB35680C5D3311917AC67690C3AF1BA018623324C015ABE5">>}, { - Name: "stdout_formatter", - Version: "0.2.3", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/stdout_formatter@0.2.3", + Name: "stdout_formatter", + Version: "0.2.3", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/stdout_formatter@0.2.3", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "stdout_formatter", Version: "0.2.3", @@ -181,11 +192,12 @@ func TestParseRebarLock(t *testing.T) { // {ref,"4835239dca5a5f4ac7202dd94d7effcaa617d575"}}, // 0}, { - Name: "swc", - Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575", + Name: "swc", + Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "swc", Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", @@ -195,11 +207,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"syslog">>, <<"6419A232BEA84F07B56DC575225007FFE34D9FDC91ABE6F1B2F254FD71D8EFC2">>}, // {<<"syslog">>, <<"4C6A41373C7E20587BE33EF841D3DE6F3BEBA08519809329ECC4D27B15B659E1">>}, { - Name: "syslog", - Version: "1.1.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/syslog@1.1.0", + Name: "syslog", + Version: "1.1.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/syslog@1.1.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "syslog", Version: "1.1.0", @@ -211,11 +224,12 @@ func TestParseRebarLock(t *testing.T) { // {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}]}, // {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}]} { - Name: "unicode_util_compat", - Version: "0.7.0", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/unicode_util_compat@0.7.0", + Name: "unicode_util_compat", + Version: "0.7.0", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/unicode_util_compat@0.7.0", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "unicode_util_compat", Version: "0.7.0", @@ -228,11 +242,12 @@ func TestParseRebarLock(t *testing.T) { // {ref,"6d622aa8c901ae7777433aef2bd049e380c474a6"}}, // 0}]}. { - Name: "vernemq_dev", - Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", - Language: pkg.Erlang, - Type: pkg.HexPkg, - PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6", + Name: "vernemq_dev", + Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", + Language: pkg.Erlang, + Type: pkg.HexPkg, + PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.ErlangRebarLockEntry{ Name: "vernemq_dev", Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", diff --git a/syft/pkg/cataloger/gentoo/cataloger_test.go b/syft/pkg/cataloger/gentoo/cataloger_test.go index 6fb80e78078d..772069c20014 100644 --- a/syft/pkg/cataloger/gentoo/cataloger_test.go +++ b/syft/pkg/cataloger/gentoo/cataloger_test.go @@ -22,8 +22,9 @@ func TestPortageCataloger(t *testing.T) { file.NewLocation("var/db/pkg/app-containers/skopeo-1.5.1/SIZE"), expectedLicenseLocation, ), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(expectedLicenseLocation, "Apache-2.0", "BSD", "BSD-2", "CC-BY-SA-4.0", "ISC", "MIT")...), - Type: pkg.PortagePkg, + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(expectedLicenseLocation, "Apache-2.0", "BSD", "BSD-2", "CC-BY-SA-4.0", "ISC", "MIT")...), + Type: pkg.PortagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PortageEntry{ InstalledSize: 27937835, Files: []pkg.PortageFileRecord{ diff --git a/syft/pkg/cataloger/gentoo/parse_portage_contents.go b/syft/pkg/cataloger/gentoo/parse_portage_contents.go index 56370d0124bf..47447c91abb0 100644 --- a/syft/pkg/cataloger/gentoo/parse_portage_contents.go +++ b/syft/pkg/cataloger/gentoo/parse_portage_contents.go @@ -45,7 +45,8 @@ func parsePortageContents(_ context.Context, resolver file.Resolver, _ *generic. Locations: file.NewLocationSet( reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Type: pkg.PortagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Type: pkg.PortagePkg, Metadata: pkg.PortageEntry{ // ensure the default value for a collection is never nil since this may be shown as JSON Files: make([]pkg.PortageFileRecord, 0), diff --git a/syft/pkg/cataloger/githubactions/package.go b/syft/pkg/cataloger/githubactions/package.go index ff1567a913af..1bc1b9a08103 100644 --- a/syft/pkg/cataloger/githubactions/package.go +++ b/syft/pkg/cataloger/githubactions/package.go @@ -31,7 +31,9 @@ func newGithubActionWorkflowPackageUsage(name, version string, workflowLocation Version: version, Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), - Type: pkg.GithubActionWorkflowPkg, + // we have full visibility into the dependencies of a workflow file except for when using shared workflows + Dependencies: pkg.CompleteDependencies, + Type: pkg.GithubActionWorkflowPkg, } p.SetID() @@ -45,7 +47,9 @@ func newGithubActionPackageUsage(name, version string, workflowLocation file.Loc Version: version, Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), - Type: pkg.GithubActionPkg, + // we cannot see what the dependencies are for a github action are locally from workflow yaml files + Dependencies: pkg.UnknownDependencyCompleteness, + Type: pkg.GithubActionPkg, } p.SetID() diff --git a/syft/pkg/cataloger/githubactions/parse_composite_action_test.go b/syft/pkg/cataloger/githubactions/parse_composite_action_test.go index 080d80816676..a73ecd2679fd 100644 --- a/syft/pkg/cataloger/githubactions/parse_composite_action_test.go +++ b/syft/pkg/cataloger/githubactions/parse_composite_action_test.go @@ -15,18 +15,20 @@ func Test_parseCompositeActionForActionUsage(t *testing.T) { expected := []pkg.Package{ { - Name: "actions/setup-go", - Version: "v4", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/setup-go@v4", + Name: "actions/setup-go", + Version: "v4", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/setup-go@v4", + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "actions/cache", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3", + Name: "actions/cache", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3", + Dependencies: pkg.UnknownDependencyCompleteness, }, } diff --git a/syft/pkg/cataloger/githubactions/parse_workflow_test.go b/syft/pkg/cataloger/githubactions/parse_workflow_test.go index 52c4e1ebd0ce..38c918901ce6 100644 --- a/syft/pkg/cataloger/githubactions/parse_workflow_test.go +++ b/syft/pkg/cataloger/githubactions/parse_workflow_test.go @@ -15,39 +15,44 @@ func Test_parseWorkflowForActionUsage(t *testing.T) { expected := []pkg.Package{ { - Name: "./.github/actions/bootstrap", - Version: "", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Name: "./.github/actions/bootstrap", + Version: "", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "actions/cache", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3", + Name: "actions/cache", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3", + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "actions/cache/restore", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3#restore", + Name: "actions/cache/restore", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3#restore", + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "actions/cache/save", - Version: "v3", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/cache@v3#save", + Name: "actions/cache/save", + Version: "v3", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/cache@v3#save", + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "actions/checkout", - Version: "v4", - Type: pkg.GithubActionPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/actions/checkout@v4", + Name: "actions/checkout", + Version: "v4", + Type: pkg.GithubActionPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/actions/checkout@v4", + Dependencies: pkg.UnknownDependencyCompleteness, }, } @@ -61,25 +66,28 @@ func Test_parseWorkflowForWorkflowUsage(t *testing.T) { expected := []pkg.Package{ { - Name: "octo-org/this-repo/.github/workflows/workflow-1.yml", - Version: "172239021f7ba04fe7327647b213799853a9eb89", - Type: pkg.GithubActionWorkflowPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/octo-org/this-repo@172239021f7ba04fe7327647b213799853a9eb89#.github/workflows/workflow-1.yml", + Name: "octo-org/this-repo/.github/workflows/workflow-1.yml", + Version: "172239021f7ba04fe7327647b213799853a9eb89", + Type: pkg.GithubActionWorkflowPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/octo-org/this-repo@172239021f7ba04fe7327647b213799853a9eb89#.github/workflows/workflow-1.yml", + Dependencies: pkg.CompleteDependencies, }, { - Name: "./.github/workflows/workflow-2.yml", - Version: "", - Type: pkg.GithubActionWorkflowPkg, - Locations: fixtureLocationSet, - PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Name: "./.github/workflows/workflow-2.yml", + Version: "", + Type: pkg.GithubActionWorkflowPkg, + Locations: fixtureLocationSet, + PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate + Dependencies: pkg.CompleteDependencies, }, { - Name: "octo-org/another-repo/.github/workflows/workflow.yml", - Version: "v1", - Type: pkg.GithubActionWorkflowPkg, - Locations: fixtureLocationSet, - PURL: "pkg:github/octo-org/another-repo@v1#.github/workflows/workflow.yml", + Name: "octo-org/another-repo/.github/workflows/workflow.yml", + Version: "v1", + Type: pkg.GithubActionWorkflowPkg, + Locations: fixtureLocationSet, + PURL: "pkg:github/octo-org/another-repo@v1#.github/workflows/workflow.yml", + Dependencies: pkg.CompleteDependencies, }, } diff --git a/syft/pkg/cataloger/golang/package.go b/syft/pkg/cataloger/golang/package.go index c3071420c40a..0c6faacb0c65 100644 --- a/syft/pkg/cataloger/golang/package.go +++ b/syft/pkg/cataloger/golang/package.go @@ -9,19 +9,20 @@ import ( "github.com/anchore/syft/syft/pkg" ) -func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string, licenses []pkg.License, locations ...file.Location) pkg.Package { +func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string, licenses []pkg.License, dependencies pkg.DependencyCompleteness, locations ...file.Location) pkg.Package { if dep.Replace != nil { dep = dep.Replace } p := pkg.Package{ - Name: dep.Path, - Version: dep.Version, - Licenses: pkg.NewLicenseSet(licenses...), - PURL: packageURL(dep.Path, dep.Version), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Locations: file.NewLocationSet(locations...), + Name: dep.Path, + Version: dep.Version, + Licenses: pkg.NewLicenseSet(licenses...), + PURL: packageURL(dep.Path, dep.Version), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Locations: file.NewLocationSet(locations...), + Dependencies: dependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goVersion, H1Digest: dep.Sum, diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index b0fe56a4e4c5..c78ea66c685b 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -134,6 +134,10 @@ func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, licenseScanner l mod.cryptoSettings, experiments, lics, + // the buildinfo section is a flat list of dependencies missing all edge information. So all direct and indirect + // dependencies are related directly to the main module. This means that we don't have any way to discover + // the completeness of the dependency's dependencies, thus they are unknown. + pkg.UnknownDependencyCompleteness, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if pkg.IsValid(&p) { @@ -178,6 +182,11 @@ func (c *goBinaryCataloger) makeGoMainPackage(ctx context.Context, licenseScanne mod.cryptoSettings, experiments, lics, + // the buildinfo section is a flat list of dependencies missing all edge information. So all direct and indirect + // dependencies are related directly to the main module. Also, we don't have a way to express on a package or + // relationship the nature of "//indirect" markings on dependencies so though the dependencies are complete + // and separable with the raw data, the data in the SBOM is not separable. + pkg.CompleteWithIndirectDependencies, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 565fda090464..3b5dec5f120d 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -161,6 +161,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -208,7 +209,8 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), - Metadata: pkg.GolangBinaryBuildinfoEntry{}, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangBinaryBuildinfoEntry{}, }, }, }, @@ -253,6 +255,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -291,6 +294,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -365,6 +369,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -432,6 +437,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -497,6 +503,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -554,6 +561,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -611,6 +619,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -669,6 +678,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -741,6 +751,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -762,6 +773,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -819,12 +831,14 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, H1Digest: "h1:PjhxBct4MZii8FFR8+oeS7QOvxKOTZXgk63EU2XpfJE=", MainModule: "github.com/anchore/syft", - }}, + }, + }, { Name: "golang.org/x/term", Version: "v0.0.0-20210916214954-140adaaadfaf", @@ -839,6 +853,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -882,6 +897,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: goCompiledVersion, Architecture: archDetails, @@ -941,6 +957,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: "go1.22.2", Architecture: archDetails, @@ -993,6 +1010,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: "go1.22.2", Architecture: archDetails, @@ -1013,6 +1031,7 @@ func TestBuildGoPkgInfo(t *testing.T) { }, ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), + Dependencies: pkg.CompleteWithIndirectDependencies, Metadata: pkg.GolangBinaryBuildinfoEntry{ GoCompiledVersion: "go1.22.2", BuildSettings: []pkg.KeyValue{ diff --git a/syft/pkg/cataloger/golang/parse_go_mod.go b/syft/pkg/cataloger/golang/parse_go_mod.go index cfb373e90489..c68bf269a375 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod.go +++ b/syft/pkg/cataloger/golang/parse_go_mod.go @@ -66,6 +66,9 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol PURL: packageURL(m.Mod.Path, m.Mod.Version), Language: pkg.Go, Type: pkg.GoModulePkg, + // we don't have a way to express on a package or relationship the nature of "//indirect" markings on dependencies + // so though the dependencies are complete and separable with the raw data, the data in the SBOM is not separable. + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangModuleEntry{ H1Digest: digests[fmt.Sprintf("%s %s", m.Mod.Path, m.Mod.Version)], }, @@ -91,6 +94,9 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol PURL: packageURL(m.New.Path, m.New.Version), Language: pkg.Go, Type: pkg.GoModulePkg, + // we don't have a way to express on a package or relationship the nature of "//indirect" markings on dependencies + // so though the dependencies are complete and separable with the raw data, the data in the SBOM is not separable. + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangModuleEntry{ H1Digest: digests[fmt.Sprintf("%s %s", m.New.Path, m.New.Version)], }, diff --git a/syft/pkg/cataloger/golang/parse_go_mod_test.go b/syft/pkg/cataloger/golang/parse_go_mod_test.go index 20538e4c78d1..9b4f319e78c2 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod_test.go +++ b/syft/pkg/cataloger/golang/parse_go_mod_test.go @@ -18,13 +18,14 @@ func TestParseGoMod(t *testing.T) { fixture: "test-fixtures/one-package", expected: []pkg.Package{ { - Name: "github.com/bmatcuk/doublestar", - Version: "v1.3.1", - PURL: "pkg:golang/github.com/bmatcuk/doublestar@v1.3.1", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/one-package")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/bmatcuk/doublestar", + Version: "v1.3.1", + PURL: "pkg:golang/github.com/bmatcuk/doublestar@v1.3.1", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/one-package")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, }, }, @@ -33,58 +34,64 @@ func TestParseGoMod(t *testing.T) { fixture: "test-fixtures/many-packages", expected: []pkg.Package{ { - Name: "github.com/anchore/archiver/v3", - Version: "v3.5.2", - PURL: "pkg:golang/github.com/anchore/archiver@v3.5.2#v3", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/archiver/v3", + Version: "v3.5.2", + PURL: "pkg:golang/github.com/anchore/archiver@v3.5.2#v3", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/anchore/go-testutils", - Version: "v0.0.0-20200624184116-66aa578126db", - PURL: "pkg:golang/github.com/anchore/go-testutils@v0.0.0-20200624184116-66aa578126db", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/go-testutils", + Version: "v0.0.0-20200624184116-66aa578126db", + PURL: "pkg:golang/github.com/anchore/go-testutils@v0.0.0-20200624184116-66aa578126db", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/anchore/go-version", - Version: "v1.2.2-0.20200701162849-18adb9c92b9b", - PURL: "pkg:golang/github.com/anchore/go-version@v1.2.2-0.20200701162849-18adb9c92b9b", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/go-version", + Version: "v1.2.2-0.20200701162849-18adb9c92b9b", + PURL: "pkg:golang/github.com/anchore/go-version@v1.2.2-0.20200701162849-18adb9c92b9b", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/anchore/stereoscope", - Version: "v0.0.0-20200706164556-7cf39d7f4639", - PURL: "pkg:golang/github.com/anchore/stereoscope@v0.0.0-20200706164556-7cf39d7f4639", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/anchore/stereoscope", + Version: "v0.0.0-20200706164556-7cf39d7f4639", + PURL: "pkg:golang/github.com/anchore/stereoscope@v0.0.0-20200706164556-7cf39d7f4639", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/bmatcuk/doublestar", - Version: "v8.8.8", - PURL: "pkg:golang/github.com/bmatcuk/doublestar@v8.8.8", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/bmatcuk/doublestar", + Version: "v8.8.8", + PURL: "pkg:golang/github.com/bmatcuk/doublestar@v8.8.8", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/go-test/deep", - Version: "v1.0.6", - PURL: "pkg:golang/github.com/go-test/deep@v1.0.6", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/go-test/deep", + Version: "v1.0.6", + PURL: "pkg:golang/github.com/go-test/deep@v1.0.6", + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, }, }, @@ -111,35 +118,38 @@ func Test_GoSumHashes(t *testing.T) { fixture: "test-fixtures/go-sum-hashes", expected: []pkg.Package{ { - Name: "github.com/CycloneDX/cyclonedx-go", - Version: "v0.6.0", - PURL: "pkg:golang/github.com/CycloneDX/cyclonedx-go@v0.6.0", - Locations: file.NewLocationSet(file.NewLocation("go.mod")), - FoundBy: "go-module-file-cataloger", - Language: pkg.Go, - Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{}, + Name: "github.com/CycloneDX/cyclonedx-go", + Version: "v0.6.0", + PURL: "pkg:golang/github.com/CycloneDX/cyclonedx-go@v0.6.0", + Locations: file.NewLocationSet(file.NewLocation("go.mod")), + FoundBy: "go-module-file-cataloger", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.GolangModuleEntry{}, }, { - Name: "github.com/acarl005/stripansi", - Version: "v0.0.0-20180116102854-5a71ef0e047d", - PURL: "pkg:golang/github.com/acarl005/stripansi@v0.0.0-20180116102854-5a71ef0e047d", - Locations: file.NewLocationSet(file.NewLocation("go.mod")), - FoundBy: "go-module-file-cataloger", - Language: pkg.Go, - Type: pkg.GoModulePkg, + Name: "github.com/acarl005/stripansi", + Version: "v0.0.0-20180116102854-5a71ef0e047d", + PURL: "pkg:golang/github.com/acarl005/stripansi@v0.0.0-20180116102854-5a71ef0e047d", + Locations: file.NewLocationSet(file.NewLocation("go.mod")), + FoundBy: "go-module-file-cataloger", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangModuleEntry{ H1Digest: "h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=", }, }, { - Name: "github.com/mgutz/ansi", - Version: "v0.0.0-20200706080929-d51e80ef957d", - PURL: "pkg:golang/github.com/mgutz/ansi@v0.0.0-20200706080929-d51e80ef957d", - Locations: file.NewLocationSet(file.NewLocation("go.mod")), - FoundBy: "go-module-file-cataloger", - Language: pkg.Go, - Type: pkg.GoModulePkg, + Name: "github.com/mgutz/ansi", + Version: "v0.0.0-20200706080929-d51e80ef957d", + PURL: "pkg:golang/github.com/mgutz/ansi@v0.0.0-20200706080929-d51e80ef957d", + Locations: file.NewLocationSet(file.NewLocation("go.mod")), + FoundBy: "go-module-file-cataloger", + Language: pkg.Go, + Type: pkg.GoModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.GolangModuleEntry{ H1Digest: "h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=", }, diff --git a/syft/pkg/cataloger/haskell/package.go b/syft/pkg/cataloger/haskell/package.go index 6594ce216051..425f75e4fd3e 100644 --- a/syft/pkg/cataloger/haskell/package.go +++ b/syft/pkg/cataloger/haskell/package.go @@ -14,7 +14,9 @@ func newPackage(name, version string, m any, location file.Location) pkg.Package PURL: packageURL(name, version), Language: pkg.Haskell, Type: pkg.HackagePkg, - Metadata: m, + // in all cases (cabal, stack, etc.) we do not attempt to glean dependency information + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go b/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go index acb58b74e97d..cd3e70814bb9 100644 --- a/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go +++ b/syft/pkg/cataloger/haskell/parse_cabal_freeze_test.go @@ -15,92 +15,103 @@ func TestParseCabalFreeze(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "Cabal", - Version: "3.2.1.0", - PURL: "pkg:hackage/Cabal@3.2.1.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Cabal", + Version: "3.2.1.0", + PURL: "pkg:hackage/Cabal@3.2.1.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "Diff", - Version: "0.4.1", - PURL: "pkg:hackage/Diff@0.4.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Diff", + Version: "0.4.1", + PURL: "pkg:hackage/Diff@0.4.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "HTTP", - Version: "4000.3.16", - PURL: "pkg:hackage/HTTP@4000.3.16", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "HTTP", + Version: "4000.3.16", + PURL: "pkg:hackage/HTTP@4000.3.16", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "HUnit", - Version: "1.6.2.0", - PURL: "pkg:hackage/HUnit@1.6.2.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "HUnit", + Version: "1.6.2.0", + PURL: "pkg:hackage/HUnit@1.6.2.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "OneTuple", - Version: "0.3.1", - PURL: "pkg:hackage/OneTuple@0.3.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "OneTuple", + Version: "0.3.1", + PURL: "pkg:hackage/OneTuple@0.3.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "Only", - Version: "0.1", - PURL: "pkg:hackage/Only@0.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Only", + Version: "0.1", + PURL: "pkg:hackage/Only@0.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "PyF", - Version: "0.10.2.0", - PURL: "pkg:hackage/PyF@0.10.2.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "PyF", + Version: "0.10.2.0", + PURL: "pkg:hackage/PyF@0.10.2.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "QuickCheck", - Version: "2.14.2", - PURL: "pkg:hackage/QuickCheck@2.14.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "QuickCheck", + Version: "2.14.2", + PURL: "pkg:hackage/QuickCheck@2.14.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "RSA", - Version: "2.4.1", - PURL: "pkg:hackage/RSA@2.4.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "RSA", + Version: "2.4.1", + PURL: "pkg:hackage/RSA@2.4.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "SHA", - Version: "1.6.4.4", - PURL: "pkg:hackage/SHA@1.6.4.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "SHA", + Version: "1.6.4.4", + PURL: "pkg:hackage/SHA@1.6.4.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "Spock", - Version: "0.14.0.0", - PURL: "pkg:hackage/Spock@0.14.0.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "Spock", + Version: "0.14.0.0", + PURL: "pkg:hackage/Spock@0.14.0.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, } diff --git a/syft/pkg/cataloger/haskell/parse_stack_lock_test.go b/syft/pkg/cataloger/haskell/parse_stack_lock_test.go index ee84ae092a6e..f431f31f8a50 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_lock_test.go +++ b/syft/pkg/cataloger/haskell/parse_stack_lock_test.go @@ -16,108 +16,117 @@ func TestParseStackLock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "HTTP", - Version: "4000.3.16", - PURL: "pkg:hackage/HTTP@4000.3.16", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "HTTP", + Version: "4000.3.16", + PURL: "pkg:hackage/HTTP@4000.3.16", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "6042643c15a0b43e522a6693f1e322f05000d519543a84149cb80aeffee34f71", SnapshotURL: url, }, }, { - Name: "configurator-pg", - Version: "0.2.6", - PURL: "pkg:hackage/configurator-pg@0.2.6", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "configurator-pg", + Version: "0.2.6", + PURL: "pkg:hackage/configurator-pg@0.2.6", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "cd9b06a458428e493a4d6def725af7ab1ab0fef678fbd871f9586fc7f9aa70be", SnapshotURL: url, }, }, { - Name: "hasql-dynamic-statements", - Version: "0.3.1.1", - PURL: "pkg:hackage/hasql-dynamic-statements@0.3.1.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hasql-dynamic-statements", + Version: "0.3.1.1", + PURL: "pkg:hackage/hasql-dynamic-statements@0.3.1.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "2cfe6e75990e690f595a87cbe553f2e90fcd738610f6c66749c81cc4396b2cc4", SnapshotURL: url, }, }, { - Name: "hasql-implicits", - Version: "0.1.0.4", - PURL: "pkg:hackage/hasql-implicits@0.1.0.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hasql-implicits", + Version: "0.1.0.4", + PURL: "pkg:hackage/hasql-implicits@0.1.0.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "0848d3cbc9d94e1e539948fa0be4d0326b26335034161bf8076785293444ca6f", SnapshotURL: url, }, }, { - Name: "hasql-pool", - Version: "0.5.2.2", - PURL: "pkg:hackage/hasql-pool@0.5.2.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hasql-pool", + Version: "0.5.2.2", + PURL: "pkg:hackage/hasql-pool@0.5.2.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "b56d4dea112d97a2ef4b2749508c0ca646828cb2d77b827e8dc433d249bb2062", SnapshotURL: url, }, }, { - Name: "lens-aeson", - Version: "1.1.3", - PURL: "pkg:hackage/lens-aeson@1.1.3", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "lens-aeson", + Version: "1.1.3", + PURL: "pkg:hackage/lens-aeson@1.1.3", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "52c8eaecd2d1c2a969c0762277c4a8ee72c339a686727d5785932e72ef9c3050", SnapshotURL: url, }, }, { - Name: "optparse-applicative", - Version: "0.16.1.0", - PURL: "pkg:hackage/optparse-applicative@0.16.1.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "optparse-applicative", + Version: "0.16.1.0", + PURL: "pkg:hackage/optparse-applicative@0.16.1.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "418c22ed6a19124d457d96bc66bd22c93ac22fad0c7100fe4972bbb4ac989731", SnapshotURL: url, }, }, { - Name: "protolude", - Version: "0.3.2", - PURL: "pkg:hackage/protolude@0.3.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "protolude", + Version: "0.3.2", + PURL: "pkg:hackage/protolude@0.3.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "2a38b3dad40d238ab644e234b692c8911423f9d3ed0e36b62287c4a698d92cd1", SnapshotURL: url, }, }, { - Name: "ptr", - Version: "0.16.8.2", - PURL: "pkg:hackage/ptr@0.16.8.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "ptr", + Version: "0.16.8.2", + PURL: "pkg:hackage/ptr@0.16.8.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlLockEntry{ PkgHash: "708ebb95117f2872d2c5a554eb6804cf1126e86abe793b2673f913f14e5eb1ac", SnapshotURL: url, diff --git a/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go b/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go index ee458639648f..7572316cc109 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go +++ b/syft/pkg/cataloger/haskell/parse_stack_yaml_test.go @@ -15,89 +15,97 @@ func TestParseStackYaml(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "ShellCheck", - Version: "0.8.0", - PURL: "pkg:hackage/ShellCheck@0.8.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "ShellCheck", + Version: "0.8.0", + PURL: "pkg:hackage/ShellCheck@0.8.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "353c9322847b661e4c6f7c83c2acf8e5c08b682fbe516c7d46c29605937543df", }, }, { - Name: "colourista", - Version: "0.1.0.1", - PURL: "pkg:hackage/colourista@0.1.0.1", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "colourista", + Version: "0.1.0.1", + PURL: "pkg:hackage/colourista@0.1.0.1", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "98353ee0e2f5d97d2148513f084c1cd37dfda03e48aa9dd7a017c9d9c0ba710e", }, }, { - Name: "language-docker", - Version: "11.0.0", - PURL: "pkg:hackage/language-docker@11.0.0", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "language-docker", + Version: "11.0.0", + PURL: "pkg:hackage/language-docker@11.0.0", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "3406ff0c1d592490f53ead8cf2cd22bdf3d79fd125ccaf3add683f6d71c24d55", }, }, { - Name: "spdx", - Version: "1.0.0.2", - PURL: "pkg:hackage/spdx@1.0.0.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "spdx", + Version: "1.0.0.2", + PURL: "pkg:hackage/spdx@1.0.0.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "7dfac9b454ff2da0abb7560f0ffbe00ae442dd5cb76e8be469f77e6988a70fed", }, }, { - Name: "hspec", - Version: "2.9.4", - PURL: "pkg:hackage/hspec@2.9.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hspec", + Version: "2.9.4", + PURL: "pkg:hackage/hspec@2.9.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "658a6a74d5a70c040edd6df2a12228c6d9e63082adaad1ed4d0438ad082a0ef3", }, }, { - Name: "hspec-core", - Version: "2.9.4", - PURL: "pkg:hackage/hspec-core@2.9.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hspec-core", + Version: "2.9.4", + PURL: "pkg:hackage/hspec-core@2.9.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "a126e9087409fef8dcafcd2f8656456527ac7bb163ed4d9cb3a57589042a5fe8", }, }, { - Name: "hspec-discover", - Version: "2.9.4", - PURL: "pkg:hackage/hspec-discover@2.9.4", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "hspec-discover", + Version: "2.9.4", + PURL: "pkg:hackage/hspec-discover@2.9.4", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "fbcf49ecfc3d4da53e797fd0275264cba776ffa324ee223e2a3f4ec2d2c9c4a6", }, }, { - Name: "stm", - Version: "2.5.0.2", - PURL: "pkg:hackage/stm@2.5.0.2", - Locations: locationSet, - Language: pkg.Haskell, - Type: pkg.HackagePkg, + Name: "stm", + Version: "2.5.0.2", + PURL: "pkg:hackage/stm@2.5.0.2", + Locations: locationSet, + Language: pkg.Haskell, + Type: pkg.HackagePkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.HackageStackYamlEntry{ PkgHash: "e4dc6473faaa75fbd7eccab4e3ee1d651d75bb0e49946ef0b8b751ccde771a55", }, diff --git a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go index 96bd79450fb8..4041de280c2f 100644 --- a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go +++ b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go @@ -44,6 +44,7 @@ type CatalogTester struct { licenseComparer cmptest.LicenseComparer packageStringer func(pkg.Package) string customAssertions []func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) + ctx context.Context } func NewCatalogTester() *CatalogTester { @@ -106,6 +107,11 @@ func (p *CatalogTester) WithLinuxRelease(r linux.Release) *CatalogTester { return p } +func (p *CatalogTester) WithContext(ctx context.Context) *CatalogTester { + p.ctx = ctx + return p +} + func (p *CatalogTester) WithEnv(env *generic.Environment) *CatalogTester { p.env = env return p @@ -236,7 +242,14 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) { resolver := NewObservingResolver(p.resolver) - pkgs, relationships, err := cataloger.Catalog(context.Background(), resolver) + var ctx context.Context + if p.ctx != nil { + ctx = p.ctx + } else { + ctx = context.Background() + } + + pkgs, relationships, err := cataloger.Catalog(ctx, resolver) // this is a minimum set, the resolver may return more that just this list for _, path := range p.expectedPathResponses { diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index b1779bbf1852..cf243994d843 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -437,6 +437,7 @@ func TestParseJar(t *testing.T) { } func TestParseNestedJar(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) tests := []struct { fixture string expected []pkg.Package @@ -638,7 +639,7 @@ func TestParseNestedJar(t *testing.T) { require.NoError(t, err) gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{}) - actual, _, err := gap.processJavaArchive(context.Background(), file.LocationReadCloser{ + actual, _, err := gap.processJavaArchive(ctx, file.LocationReadCloser{ Location: file.NewLocation(fixture.Name()), ReadCloser: fixture, }, nil) @@ -1166,6 +1167,8 @@ func Test_parseJavaArchive_regressions(t *testing.T) { }, } + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) + tests := []struct { name string fixtureName string @@ -1355,6 +1358,7 @@ func Test_parseJavaArchive_regressions(t *testing.T) { pkgtest.NewCatalogTester(). FromFile(t, generateJavaMetadataJarFixture(t, tt.fixtureName, tt.fileExtension)). Expects(tt.expectedPkgs, tt.expectedRelationships). + WithContext(ctx). WithCompareOptions( cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests"), cmp.Comparer(func(x, y pkg.KeyValue) bool { diff --git a/syft/pkg/cataloger/java/cataloger_test.go b/syft/pkg/cataloger/java/cataloger_test.go index 9df9825dfa7b..438aa52498de 100644 --- a/syft/pkg/cataloger/java/cataloger_test.go +++ b/syft/pkg/cataloger/java/cataloger_test.go @@ -1,8 +1,10 @@ package java import ( + "context" "testing" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/file" @@ -11,6 +13,8 @@ import ( ) func Test_ArchiveCataloger_Globs(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner()) + tests := []struct { name string fixture string @@ -59,6 +63,7 @@ func Test_ArchiveCataloger_Globs(t *testing.T) { pkgtest.NewCatalogTester(). FromDirectory(t, test.fixture). ExpectsResolverContentQueries(test.expected). + WithContext(ctx). TestCataloger(t, NewArchiveCataloger( ArchiveCatalogerConfig{ @@ -128,7 +133,8 @@ func TestJvmDistributionCataloger(t *testing.T) { cpe.Must("cpe:2.3:a:oracle:jre:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource), cpe.Must("cpe:2.3:a:oracle:jdk:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource), }, - PURL: "pkg:generic/oracle/jdk@1.8.0_411-b25", + PURL: "pkg:generic/oracle/jdk@1.8.0_411-b25", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaVMInstallation{ Release: pkg.JavaVMRelease{ JavaRuntimeVersion: "1.8.0_411-b25", @@ -150,14 +156,15 @@ func TestJvmDistributionCataloger(t *testing.T) { name: "valid post-jep223", fixture: "test-fixtures/jvm-installs/valid-post-jep223", expected: pkg.Package{ - Name: "openjdk", - Version: "21.0.4+7-LTS", - FoundBy: "java-jvm-cataloger", - Locations: file.NewLocationSet(file.NewLocation("jvm/openjdk/release")), - Licenses: pkg.NewLicenseSet(), - Type: pkg.BinaryPkg, - CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:oracle:openjdk:21.0.4:*:*:*:*:*:*:*", cpe.DeclaredSource)}, - PURL: "pkg:generic/oracle/openjdk@21.0.4%2B7-LTS?repository_url=https://github.com/adoptium/jdk21u.git", + Name: "openjdk", + Version: "21.0.4+7-LTS", + FoundBy: "java-jvm-cataloger", + Locations: file.NewLocationSet(file.NewLocation("jvm/openjdk/release")), + Licenses: pkg.NewLicenseSet(), + Type: pkg.BinaryPkg, + CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:oracle:openjdk:21.0.4:*:*:*:*:*:*:*", cpe.DeclaredSource)}, + PURL: "pkg:generic/oracle/openjdk@21.0.4%2B7-LTS?repository_url=https://github.com/adoptium/jdk21u.git", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaVMInstallation{ Release: pkg.JavaVMRelease{ Implementor: "Eclipse Adoptium", diff --git a/syft/pkg/cataloger/java/parse_gradle_lockfile.go b/syft/pkg/cataloger/java/parse_gradle_lockfile.go index a2aa11b5d3d7..3de6d20ca87c 100644 --- a/syft/pkg/cataloger/java/parse_gradle_lockfile.go +++ b/syft/pkg/cataloger/java/parse_gradle_lockfile.go @@ -23,17 +23,17 @@ type lockfileDependency struct { func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { var pkgs []pkg.Package - // Create a new scanner to read the file + // create a new scanner to read the file scanner := bufio.NewScanner(reader) - // Create slices to hold the dependencies and plugins + // create slices to hold the dependencies and plugins dependencies := []lockfileDependency{} - // Loop over all lines in the file + // loop over all lines in the file for scanner.Scan() { line := scanner.Text() - // Trim leading and trailing whitespace from the line + // trim leading and trailing whitespace from the line line = strings.TrimSpace(line) groupNameVersion := line @@ -42,7 +42,7 @@ func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environm // we have a version directly specified if len(parts) == 3 { - // Create a new Dependency struct and add it to the dependencies slice + // create a new Dependency struct and add it to the dependencies slice dep := lockfileDependency{Group: parts[0], Name: parts[1], Version: parts[2]} dependencies = append(dependencies, dep) } @@ -68,7 +68,9 @@ func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environm Language: pkg.Java, Type: pkg.JavaPkg, PURL: packageURL(dep.Name, dep.Version, archive), - Metadata: archive, + // though we do have dependencies listed, we do not have them related to one another, thus we must answer unknown + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: archive, } mappedPkg.SetID() pkgs = append(pkgs, mappedPkg) diff --git a/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go b/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go index 3208d937d20b..31c1a646a799 100644 --- a/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go +++ b/syft/pkg/cataloger/java/parse_gradle_lockfile_test.go @@ -17,41 +17,45 @@ func Test_parserGradleLockfile(t *testing.T) { input: "test-fixtures/gradle/gradle.lockfile", expected: []pkg.Package{ { - Name: "commons-text", - Version: "1.8", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/org.apache.commons/commons-text@1.8", + Name: "commons-text", + Version: "1.8", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/org.apache.commons/commons-text@1.8", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "org.apache.commons", ArtifactID: "commons-text", Version: "1.8", Name: "commons-text"}, }, }, { - Name: "hamcrest-core", - Version: "1.3", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/org.hamcrest/hamcrest-core@1.3", + Name: "hamcrest-core", + Version: "1.3", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/org.hamcrest/hamcrest-core@1.3", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "org.hamcrest", ArtifactID: "hamcrest-core", Version: "1.3", Name: "hamcrest-core"}, }, }, { - Name: "joda-time", - Version: "2.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/joda-time/joda-time@2.2", + Name: "joda-time", + Version: "2.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/joda-time/joda-time@2.2", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "joda-time", ArtifactID: "joda-time", Version: "2.2", Name: "joda-time"}, }, }, { - Name: "junit", - Version: "4.12", - Language: pkg.Java, - Type: pkg.JavaPkg, - PURL: "pkg:maven/junit/junit@4.12", + Name: "junit", + Version: "4.12", + Language: pkg.Java, + Type: pkg.JavaPkg, + PURL: "pkg:maven/junit/junit@4.12", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{GroupID: "junit", ArtifactID: "junit", Version: "4.12", Name: "junit"}, }, diff --git a/syft/pkg/cataloger/java/parse_jvm_release.go b/syft/pkg/cataloger/java/parse_jvm_release.go index e39be4779a7f..ae475c9c30d0 100644 --- a/syft/pkg/cataloger/java/parse_jvm_release.go +++ b/syft/pkg/cataloger/java/parse_jvm_release.go @@ -98,6 +98,8 @@ func parseJVMRelease(_ context.Context, resolver file.Resolver, _ *generic.Envir PURL: jvmPurl(*ri, version, vendor, product), Licenses: licenses, Type: pkg.BinaryPkg, + // we don't have any dependency information about the JVM package itself + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaVMInstallation{ Release: *ri, Files: files, diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index dc4922774b20..a16adfcaf603 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -51,7 +51,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver r.AddPom(ctx, pom, pomLocation) } - var pkgs []pkg.Package + var pkgs []*pkg.Package var relationships []artifact.Relationship resolved := map[maven.ID]*pkg.Package{} @@ -65,7 +65,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver continue } resolved[id] = mainPkg - pkgs = append(pkgs, *mainPkg) + pkgs = append(pkgs, mainPkg) } // catalog all dependencies @@ -81,7 +81,27 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver errs = unknown.Join(errs, newErrs) } - return pkgs, relationships, errs + return finalizePackages(pkgs), finalizeRelationships(relationships), errs +} + +func finalizeRelationships(relationships []artifact.Relationship) []artifact.Relationship { + for i := range relationships { + if f, ok := relationships[i].From.(*pkg.Package); ok { + relationships[i].From = *f + } + if t, ok := relationships[i].To.(*pkg.Package); ok { + relationships[i].To = *t + } + } + return relationships +} + +func finalizePackages(pkgs []*pkg.Package) []pkg.Package { + var values []pkg.Package + for i := range pkgs { + values = append(values, *pkgs[i]) + } + return values } func readPomFromLocation(fileResolver file.Resolver, pomLocation file.Location) (*maven.Project, error) { @@ -142,7 +162,10 @@ func newPackageFromMavenPom(ctx context.Context, r *maven.Resolver, pom *maven.P Type: pkg.JavaPkg, FoundBy: pomCatalogerName, PURL: packageURL(id.ArtifactID, id.Version, m), - Metadata: m, + // later in processing we may resolve the dependencies for this package (e.g. online enrichment) + // but at this point there is not enough information to claim we have complete dependency information + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: m, } finalizePackage(p) @@ -150,9 +173,9 @@ func newPackageFromMavenPom(ctx context.Context, r *maven.Resolver, pom *maven.P return p } -func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[maven.ID]*pkg.Package, parentPkg *pkg.Package, pom *maven.Project, loc file.Location, includeTransitiveDependencies bool) ([]pkg.Package, []artifact.Relationship, error) { +func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[maven.ID]*pkg.Package, parentPkg *pkg.Package, pom *maven.Project, loc file.Location, includeTransitiveDependencies bool) ([]*pkg.Package, []artifact.Relationship, error) { var errs error - var pkgs []pkg.Package + var pkgs []*pkg.Package var relationships []artifact.Relationship pomID := r.ResolveID(ctx, pom) @@ -196,16 +219,25 @@ func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[ma } } - pkgs = append(pkgs, *depPkg) + pkgs = append(pkgs, depPkg) if parentPkg != nil { - relationships = append(relationships, artifact.Relationship{ - From: *depPkg, - To: *parentPkg, + relationships = append(relationships, artifact.Relationship{ //nolint:gocritic // we intentionally want to use the reference to the package which will still be mutated and finalized to a value later + // both the to and from packages may be mutated based on the resolved dependencies, so we need references to these values + // to ensure the nodes used are consistent with the final state of the packages. + // note: it is VITAL that these references are replaced with values by the caller of this function before using + // these relationships in the cataloger output. + From: depPkg, + To: parentPkg, Type: artifact.DependencyOfRelationship, }) } } + // as long as we have no errors, we can claim we have complete direct dependencies (even if there are none) + if errs == nil { + parentPkg.Dependencies = pkg.CompleteDependencies + } + return pkgs, relationships, errs } @@ -270,7 +302,10 @@ func newPackageFromDependency(ctx context.Context, r *maven.Resolver, pom *maven Language: pkg.Java, Type: pkg.JavaPkg, // TODO: should we differentiate between packages from jar/war/zip versus packages from a pom.xml that were not installed yet? FoundBy: pomCatalogerName, - Metadata: m, + // later in processing we may resolve the dependencies for this package (e.g. online enrichment) but + // by default we cannot claim we have complete dependency information + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: m, } finalizePackage(p) diff --git a/syft/pkg/cataloger/java/parse_pom_xml_test.go b/syft/pkg/cataloger/java/parse_pom_xml_test.go index 6bd0a5f2382c..03e200d57913 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml_test.go +++ b/syft/pkg/cataloger/java/parse_pom_xml_test.go @@ -24,13 +24,14 @@ func Test_parsePomXML(t *testing.T) { pomLocation := file.NewLocationSet(file.NewLocation("pom.xml")) exampleJavaAppMaven := pkg.Package{ - Name: "example-java-app-maven", - Version: "0.1.0", - PURL: "pkg:maven/org.anchore/example-java-app-maven@0.1.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, - Locations: pomLocation, + Name: "example-java-app-maven", + Version: "0.1.0", + PURL: "pkg:maven/org.anchore/example-java-app-maven@0.1.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Locations: pomLocation, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "org.anchore", @@ -42,13 +43,14 @@ func Test_parsePomXML(t *testing.T) { finalizePackage(&exampleJavaAppMaven) jodaTime := pkg.Package{ - Name: "joda-time", - Version: "2.9.2", - PURL: "pkg:maven/com.joda/joda-time@2.9.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, - Locations: pomLocation, + Name: "joda-time", + Version: "2.9.2", + PURL: "pkg:maven/com.joda/joda-time@2.9.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Locations: pomLocation, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "com.joda", @@ -59,13 +61,14 @@ func Test_parsePomXML(t *testing.T) { finalizePackage(&jodaTime) junit := pkg.Package{ - Name: "junit", - Version: "4.12", - PURL: "pkg:maven/junit/junit@4.12", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, - Locations: pomLocation, + Name: "junit", + Version: "4.12", + PURL: "pkg:maven/junit/junit@4.12", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Locations: pomLocation, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "junit", @@ -472,12 +475,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { pomXmlLocation := file.NewLocationSet(file.NewLocation("pom.xml")) commonsText := pkg.Package{ - Name: "commons-text", - Version: "1.10.0", - PURL: "pkg:maven/org.apache.commons/commons-text@1.10.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-text", + Version: "1.10.0", + PURL: "pkg:maven/org.apache.commons/commons-text@1.10.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ Parent: &pkg.JavaPomParent{ @@ -496,12 +500,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } commonsLang3 := pkg.Package{ - Name: "commons-lang3", - Version: "3.12.0", - PURL: "pkg:maven/org.apache.commons/commons-lang3@3.12.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-lang3", + Version: "3.12.0", + PURL: "pkg:maven/org.apache.commons/commons-lang3@3.12.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -511,12 +516,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } junitJupiter := pkg.Package{ - Name: "junit-jupiter", - Version: "", - PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "junit-jupiter", + Version: "", + PURL: "pkg:maven/org.junit.jupiter/junit-jupiter", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.junit.jupiter", @@ -527,12 +533,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } assertjCore := pkg.Package{ - Name: "assertj-core", - Version: "3.23.1", - PURL: "pkg:maven/org.assertj/assertj-core@3.23.1", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "assertj-core", + Version: "3.23.1", + PURL: "pkg:maven/org.assertj/assertj-core@3.23.1", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.assertj", @@ -543,12 +550,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } commonsIO := pkg.Package{ - Name: "commons-io", - Version: "2.11.0", - PURL: "pkg:maven/commons-io/commons-io@2.11.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-io", + Version: "2.11.0", + PURL: "pkg:maven/commons-io/commons-io@2.11.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "commons-io", @@ -559,12 +567,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } mockitoInline := pkg.Package{ - Name: "mockito-inline", - Version: "4.8.0", - PURL: "pkg:maven/org.mockito/mockito-inline@4.8.0", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "mockito-inline", + Version: "4.8.0", + PURL: "pkg:maven/org.mockito/mockito-inline@4.8.0", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.mockito", @@ -575,12 +584,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } js := pkg.Package{ - Name: "js", - Version: "22.0.0.2", - PURL: "pkg:maven/org.graalvm.js/js@22.0.0.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "js", + Version: "22.0.0.2", + PURL: "pkg:maven/org.graalvm.js/js@22.0.0.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.graalvm.js", @@ -591,12 +601,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } jsScriptengine := pkg.Package{ - Name: "js-scriptengine", - Version: "22.0.0.2", - PURL: "pkg:maven/org.graalvm.js/js-scriptengine@22.0.0.2", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "js-scriptengine", + Version: "22.0.0.2", + PURL: "pkg:maven/org.graalvm.js/js-scriptengine@22.0.0.2", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.graalvm.js", @@ -607,12 +618,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } commonsRngSimple := pkg.Package{ - Name: "commons-rng-simple", - Version: "1.4", - PURL: "pkg:maven/org.apache.commons/commons-rng-simple@1.4", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "commons-rng-simple", + Version: "1.4", + PURL: "pkg:maven/org.apache.commons/commons-rng-simple@1.4", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -623,12 +635,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } jmhCore := pkg.Package{ - Name: "jmh-core", - Version: "1.35", - PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "jmh-core", + Version: "1.35", + PURL: "pkg:maven/org.openjdk.jmh/jmh-core@1.35", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.openjdk.jmh", @@ -639,12 +652,13 @@ func getCommonsTextExpectedPackages(resolved bool) expected { } jmhGeneratorAnnprocess := pkg.Package{ - Name: "jmh-generator-annprocess", - Version: "1.35", - PURL: "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35", - Language: pkg.Java, - Type: pkg.JavaPkg, - FoundBy: pomCatalogerName, + Name: "jmh-generator-annprocess", + Version: "1.35", + PURL: "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35", + Language: pkg.Java, + Type: pkg.JavaPkg, + FoundBy: pomCatalogerName, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.openjdk.jmh", @@ -699,6 +713,8 @@ func expectedTransientPackageData() expected { transitiveTopLevel := pkg.Package{ Name: "transitive-top-level", Version: "99", + // one of the children is missing a pom in the test fixtures, this is a search miss + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "my.other.group", @@ -708,9 +724,10 @@ func expectedTransientPackageData() expected { }, } childOne := pkg.Package{ - Name: "child-one", - Version: "1.3.6", - Licenses: epl2, + Name: "child-one", + Version: "1.3.6", + Licenses: epl2, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "my.org", @@ -729,9 +746,10 @@ func expectedTransientPackageData() expected { }, } childTwo := pkg.Package{ - Name: "child-two", - Version: "2.1.90", - Licenses: epl2, + Name: "child-two", + Version: "2.1.90", + Licenses: epl2, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.JavaArchive{ PomProject: &pkg.JavaPomProject{ GroupID: "my.org", @@ -753,6 +771,8 @@ func expectedTransientPackageData() expected { commonsLang3_113_7_8_0 := pkg.Package{ Name: "commons-lang3", Version: "3.113.7.8.0", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -763,6 +783,8 @@ func expectedTransientPackageData() expected { commonsLang3_12_0 := pkg.Package{ Name: "commons-lang3", Version: "3.12.0", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -773,6 +795,8 @@ func expectedTransientPackageData() expected { commonsMath3 := pkg.Package{ Name: "commons-math3.11.0", Version: "3.5", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", @@ -783,6 +807,8 @@ func expectedTransientPackageData() expected { commonsExec := pkg.Package{ Name: "commons-exec", Version: "1.3", + // missing pom in test fixtures, this is a search miss + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.JavaArchive{ PomProperties: &pkg.JavaPomProperties{ GroupID: "org.apache.commons", diff --git a/syft/pkg/cataloger/javascript/cataloger_test.go b/syft/pkg/cataloger/javascript/cataloger_test.go index 0adf2b4fd623..33d0896a4f92 100644 --- a/syft/pkg/cataloger/javascript/cataloger_test.go +++ b/syft/pkg/cataloger/javascript/cataloger_test.go @@ -12,120 +12,131 @@ func Test_JavascriptCataloger(t *testing.T) { locationSet := file.NewLocationSet(file.NewLocation("package-lock.json")) expectedPkgs := []pkg.Package{ { - Name: "@actions/core", - Version: "1.6.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/%40actions/core@1.6.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@actions/core", + Version: "1.6.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/%40actions/core@1.6.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("package-lock.json")), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="}, }, { - Name: "ansi-regex", - Version: "3.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/ansi-regex@3.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, + Name: "ansi-regex", + Version: "3.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/ansi-regex@3.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, }, { - Name: "cowsay", - Version: "1.4.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/cowsay@1.4.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "cowsay", + Version: "1.4.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/cowsay@1.4.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("package-lock.json")), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="}, }, { - Name: "get-stdin", - Version: "5.0.1", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/get-stdin@5.0.1", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, + Name: "get-stdin", + Version: "5.0.1", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/get-stdin@5.0.1", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, }, { - Name: "is-fullwidth-code-point", - Version: "2.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, + Name: "is-fullwidth-code-point", + Version: "2.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, }, { - Name: "minimist", - Version: "0.0.10", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/minimist@0.0.10", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, + Name: "minimist", + Version: "0.0.10", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/minimist@0.0.10", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, }, { - Name: "optimist", - Version: "0.6.1", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/optimist@0.6.1", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, + Name: "optimist", + Version: "0.6.1", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/optimist@0.6.1", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, }, { - Name: "string-width", - Version: "2.1.1", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/string-width@2.1.1", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, + Name: "string-width", + Version: "2.1.1", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/string-width@2.1.1", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, }, { - Name: "strip-ansi", - Version: "4.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/strip-ansi@4.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, + Name: "strip-ansi", + Version: "4.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/strip-ansi@4.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, }, { - Name: "strip-eof", - Version: "1.0.0", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/strip-eof@1.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, + Name: "strip-eof", + Version: "1.0.0", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/strip-eof@1.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, }, { - Name: "wordwrap", - Version: "0.0.3", - FoundBy: "javascript-lock-cataloger", - PURL: "pkg:npm/wordwrap@0.0.3", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, + Name: "wordwrap", + Version: "0.0.3", + FoundBy: "javascript-lock-cataloger", + PURL: "pkg:npm/wordwrap@0.0.3", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, }, } diff --git a/syft/pkg/cataloger/javascript/package.go b/syft/pkg/cataloger/javascript/package.go index 19114c99f55a..522b095c873d 100644 --- a/syft/pkg/cataloger/javascript/package.go +++ b/syft/pkg/cataloger/javascript/package.go @@ -32,6 +32,9 @@ func newPackageJSONPackage(u packageJSON, indexLocation file.Location) pkg.Packa Language: pkg.JavaScript, Licenses: pkg.NewLicenseSet(license...), Type: pkg.NpmPkg, + // though we could glean dependency information from the package.json and surrounding packages found in a node_modules directory, + // we do not do so today, so we record "unknown" for this package's dependency completeness field. + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: u.Name, Version: u.Version, @@ -88,7 +91,10 @@ func newPackageLockV1Package(cfg CatalogerConfig, resolver file.Resolver, locati PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, + // though we could glean dependency information from the package-lock.json, + // we do not do so today, so we record "unknown" for this package's dependency completeness field. + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, }, ) } @@ -120,7 +126,10 @@ func newPackageLockV2Package(cfg CatalogerConfig, resolver file.Resolver, locati PURL: packageURL(name, u.Version), Language: pkg.JavaScript, Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, + // though we could glean dependency information from the package-lock.json, + // we do not do so today, so we record "unknown" for this package's dependency completeness field. + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: u.Resolved, Integrity: u.Integrity}, }, ) } @@ -136,6 +145,9 @@ func newPnpmPackage(resolver file.Resolver, location file.Location, name, versio PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, + // though we could glean dependency information from the pnpm files, + // we do not do so today, so we record "unknown" for this package's dependency completeness field. + Dependencies: pkg.UnknownDependencyCompleteness, }, ) } @@ -164,7 +176,10 @@ func newYarnLockPackage(cfg CatalogerConfig, resolver file.Resolver, location fi PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{Resolved: resolved, Integrity: integrity}, + // though we could glean dependency information from the yarn.lock, + // we do not do so today, so we record "unknown" for this package's dependency completeness field. + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{Resolved: resolved, Integrity: integrity}, }, ) } diff --git a/syft/pkg/cataloger/javascript/parse_package_json_test.go b/syft/pkg/cataloger/javascript/parse_package_json_test.go index ea0102d98415..9e84a1a9f749 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_json_test.go @@ -26,6 +26,7 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package.json")), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -47,6 +48,7 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("ISC", file.NewLocation("test-fixtures/pkg-json/package-license-object.json")), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -68,7 +70,8 @@ func TestParsePackageJSON(t *testing.T) { pkg.NewLicenseFromLocations("MIT", file.NewLocation("test-fixtures/pkg-json/package-license-objects.json")), pkg.NewLicenseFromLocations("Apache-2.0", file.NewLocation("test-fixtures/pkg-json/package-license-objects.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -82,11 +85,12 @@ func TestParsePackageJSON(t *testing.T) { { Fixture: "test-fixtures/pkg-json/package-malformed-license.json", ExpectedPkg: pkg.Package{ - Name: "npm", - Version: "6.14.6", - PURL: "pkg:npm/npm@6.14.6", - Type: pkg.NpmPkg, - Language: pkg.JavaScript, + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Language: pkg.JavaScript, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -100,11 +104,12 @@ func TestParsePackageJSON(t *testing.T) { { Fixture: "test-fixtures/pkg-json/package-no-license.json", ExpectedPkg: pkg.Package{ - Name: "npm", - Version: "6.14.6", - PURL: "pkg:npm/npm@6.14.6", - Type: pkg.NpmPkg, - Language: pkg.JavaScript, + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Language: pkg.JavaScript, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -125,7 +130,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-nested-author.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -146,7 +152,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("test-fixtures/pkg-json/package-repo-string.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "function-bind", Version: "1.1.1", @@ -167,7 +174,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-private.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -189,7 +197,8 @@ func TestParsePackageJSON(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-author-non-standard.json")), ), - Language: pkg.JavaScript, + Language: pkg.JavaScript, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NpmPackage{ Name: "npm", Version: "6.14.6", @@ -224,11 +233,12 @@ func TestParsePackageJSON_Partial(t *testing.T) { // see https://github.com/anch // according to compliance rules later expectedPkgs := []pkg.Package{ { - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: packageURL("", ""), - Metadata: pkg.NpmPackage{}, - Locations: file.NewLocationSet(file.NewLocation(fixtureFile)), + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + PURL: packageURL("", ""), + Locations: file.NewLocationSet(file.NewLocation(fixtureFile)), + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackage{}, }, } pkgtest.TestFileParser(t, fixtureFile, parsePackageJSON, expectedPkgs, nil) diff --git a/syft/pkg/cataloger/javascript/parse_package_lock_test.go b/syft/pkg/cataloger/javascript/parse_package_lock_test.go index b3ba527bb7bb..ee7712b43ce8 100644 --- a/syft/pkg/cataloger/javascript/parse_package_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_lock_test.go @@ -13,92 +13,103 @@ func TestParsePackageLock(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "@actions/core", - Version: "1.6.0", - PURL: "pkg:npm/%40actions/core@1.6.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="}, + Name: "@actions/core", + Version: "1.6.0", + PURL: "pkg:npm/%40actions/core@1.6.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", Integrity: "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw=="}, }, { - Name: "ansi-regex", - Version: "3.0.0", - PURL: "pkg:npm/ansi-regex@3.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, + Name: "ansi-regex", + Version: "3.0.0", + PURL: "pkg:npm/ansi-regex@3.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", Integrity: "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="}, }, { - Name: "cowsay", - Version: "1.4.0", - PURL: "pkg:npm/cowsay@1.4.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="}, + Name: "cowsay", + Version: "1.4.0", + PURL: "pkg:npm/cowsay@1.4.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/cowsay/-/cowsay-1.4.0.tgz", Integrity: "sha512-rdg5k5PsHFVJheO/pmE3aDg2rUDDTfPJau6yYkZYlHFktUz+UxbE+IgnUAEyyCyv4noL5ltxXD0gZzmHPCy/9g=="}, }, { - Name: "get-stdin", - Version: "5.0.1", - PURL: "pkg:npm/get-stdin@5.0.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, + Name: "get-stdin", + Version: "5.0.1", + PURL: "pkg:npm/get-stdin@5.0.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", Integrity: "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="}, }, { - Name: "is-fullwidth-code-point", - Version: "2.0.0", - PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, + Name: "is-fullwidth-code-point", + Version: "2.0.0", + PURL: "pkg:npm/is-fullwidth-code-point@2.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", Integrity: "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="}, }, { - Name: "minimist", - Version: "0.0.10", - PURL: "pkg:npm/minimist@0.0.10", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, + Name: "minimist", + Version: "0.0.10", + PURL: "pkg:npm/minimist@0.0.10", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", Integrity: "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="}, }, { - Name: "optimist", - Version: "0.6.1", - PURL: "pkg:npm/optimist@0.6.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, + Name: "optimist", + Version: "0.6.1", + PURL: "pkg:npm/optimist@0.6.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", Integrity: "sha1-2j6nRob6IaGaERwybpDrFaAZZoY="}, }, { - Name: "string-width", - Version: "2.1.1", - PURL: "pkg:npm/string-width@2.1.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, + Name: "string-width", + Version: "2.1.1", + PURL: "pkg:npm/string-width@2.1.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", Integrity: "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw=="}, }, { - Name: "strip-ansi", - Version: "4.0.0", - PURL: "pkg:npm/strip-ansi@4.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, + Name: "strip-ansi", + Version: "4.0.0", + PURL: "pkg:npm/strip-ansi@4.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", Integrity: "sha1-qEeQIusaw2iocTibY1JixQXuNo8="}, }, { - Name: "strip-eof", - Version: "1.0.0", - PURL: "pkg:npm/strip-eof@1.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, + Name: "strip-eof", + Version: "1.0.0", + PURL: "pkg:npm/strip-eof@1.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", Integrity: "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="}, }, { - Name: "wordwrap", - Version: "0.0.3", - PURL: "pkg:npm/wordwrap@0.0.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, + Name: "wordwrap", + Version: "0.0.3", + PURL: "pkg:npm/wordwrap@0.0.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", Integrity: "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="}, }, } fixture := "test-fixtures/pkg-lock/package-lock.json" @@ -115,52 +126,57 @@ func TestParsePackageLockV2(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "npm", - Version: "6.14.6", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/npm@6.14.6", - Metadata: pkg.NpmPackageLockEntry{}, + Name: "npm", + Version: "6.14.6", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + PURL: "pkg:npm/npm@6.14.6", + Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "@types/prop-types", - Version: "15.7.5", - PURL: "pkg:npm/%40types/prop-types@15.7.5", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/prop-types", + Version: "15.7.5", + PURL: "pkg:npm/%40types/prop-types@15.7.5", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha1-XxnSuFqY6VWANvajysyIGUIPBc8="}, }, { - Name: "@types/react", - Version: "18.0.17", - PURL: "pkg:npm/%40types/react@18.0.17", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/react", + Version: "18.0.17", + PURL: "pkg:npm/%40types/react@18.0.17", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz", Integrity: "sha1-RYPZwyLWfv5LOak10iPtzHBQzPQ="}, }, { - Name: "@types/scheduler", - Version: "0.16.2", - PURL: "pkg:npm/%40types/scheduler@0.16.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/scheduler", + Version: "0.16.2", + PURL: "pkg:npm/%40types/scheduler@0.16.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk="}, }, { - Name: "csstype", - Version: "3.1.0", - PURL: "pkg:npm/csstype@3.1.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "csstype", + Version: "3.1.0", + PURL: "pkg:npm/csstype@3.1.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), @@ -179,44 +195,49 @@ func TestParsePackageLockV3(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "lock-v3-fixture", - Version: "1.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/lock-v3-fixture@1.0.0", - Metadata: pkg.NpmPackageLockEntry{}, + Name: "lock-v3-fixture", + Version: "1.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + PURL: "pkg:npm/lock-v3-fixture@1.0.0", + Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "@types/prop-types", - Version: "15.7.5", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/%40types/prop-types@15.7.5", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="}, + Name: "@types/prop-types", + Version: "15.7.5", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + PURL: "pkg:npm/%40types/prop-types@15.7.5", + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", Integrity: "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="}, }, { - Name: "@types/react", - Version: "18.0.20", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/%40types/react@18.0.20", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", Integrity: "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA=="}, + Name: "@types/react", + Version: "18.0.20", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + PURL: "pkg:npm/%40types/react@18.0.20", + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", Integrity: "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA=="}, }, { - Name: "@types/scheduler", - Version: "0.16.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/%40types/scheduler@0.16.2", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="}, + Name: "@types/scheduler", + Version: "0.16.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + PURL: "pkg:npm/%40types/scheduler@0.16.2", + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", Integrity: "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="}, }, { - Name: "csstype", - Version: "3.1.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - PURL: "pkg:npm/csstype@3.1.1", - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", Integrity: "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="}, + Name: "csstype", + Version: "3.1.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + PURL: "pkg:npm/csstype@3.1.1", + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", Integrity: "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="}, }, } for i := range expectedPkgs { @@ -230,28 +251,31 @@ func TestParsePackageLockAlias(t *testing.T) { var expectedRelationships []artifact.Relationship commonPkgs := []pkg.Package{ { - Name: "case", - Version: "1.6.2", - PURL: "pkg:npm/case@1.6.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.2.tgz", Integrity: "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="}, + Name: "case", + Version: "1.6.2", + PURL: "pkg:npm/case@1.6.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.2.tgz", Integrity: "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="}, }, { - Name: "case", - Version: "1.6.3", - PURL: "pkg:npm/case@1.6.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.3.tgz", Integrity: "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="}, + Name: "case", + Version: "1.6.3", + PURL: "pkg:npm/case@1.6.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/case/-/case-1.6.3.tgz", Integrity: "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="}, }, { - Name: "@bundled-es-modules/chai", - Version: "4.2.2", - PURL: "pkg:npm/%40bundled-es-modules/chai@4.2.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz", Integrity: "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="}, + Name: "@bundled-es-modules/chai", + Version: "4.2.2", + PURL: "pkg:npm/%40bundled-es-modules/chai@4.2.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz", Integrity: "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="}, }, } @@ -268,7 +292,8 @@ func TestParsePackageLockAlias(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("ISC", file.NewLocation(packageLockV2)), ), - Metadata: pkg.NpmPackageLockEntry{}, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.NpmPackageLockEntry{}, } for _, pl := range packageLocks { @@ -292,10 +317,11 @@ func TestParsePackageLockLicenseWithArray(t *testing.T) { var expectedRelationships []artifact.Relationship expectedPkgs := []pkg.Package{ { - Name: "tmp", - Version: "1.0.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "tmp", + Version: "1.0.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("ISC", file.NewLocation(fixture)), ), @@ -303,11 +329,11 @@ func TestParsePackageLockLicenseWithArray(t *testing.T) { Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "pause-stream", - Version: "0.0.11", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - + Name: "pause-stream", + Version: "0.0.11", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), pkg.NewLicenseFromLocations("Apache2", file.NewLocation(fixture)), @@ -316,10 +342,11 @@ func TestParsePackageLockLicenseWithArray(t *testing.T) { Metadata: pkg.NpmPackageLockEntry{}, }, { - Name: "through", - Version: "2.3.8", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "through", + Version: "2.3.8", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), diff --git a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go index 8b5ed7d0ae0f..c8b30aa72cf6 100644 --- a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go @@ -17,36 +17,40 @@ func TestParsePnpmLock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "nanoid", - Version: "3.3.4", - PURL: "pkg:npm/nanoid@3.3.4", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "nanoid", + Version: "3.3.4", + PURL: "pkg:npm/nanoid@3.3.4", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "picocolors", - Version: "1.0.0", - PURL: "pkg:npm/picocolors@1.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "picocolors", + Version: "1.0.0", + PURL: "pkg:npm/picocolors@1.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "source-map-js", - Version: "1.0.2", - PURL: "pkg:npm/source-map-js@1.0.2", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "source-map-js", + Version: "1.0.2", + PURL: "pkg:npm/source-map-js@1.0.2", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "@bcoe/v8-coverage", - Version: "0.2.3", - PURL: "pkg:npm/%40bcoe/v8-coverage@0.2.3", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@bcoe/v8-coverage", + Version: "0.2.3", + PURL: "pkg:npm/%40bcoe/v8-coverage@0.2.3", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, } @@ -61,84 +65,94 @@ func TestParsePnpmV6Lock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "@testing-library/jest-dom", - Version: "5.16.5", - PURL: "pkg:npm/%40testing-library/jest-dom@5.16.5", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@testing-library/jest-dom", + Version: "5.16.5", + PURL: "pkg:npm/%40testing-library/jest-dom@5.16.5", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "@testing-library/react", - Version: "13.4.0", - PURL: "pkg:npm/%40testing-library/react@13.4.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@testing-library/react", + Version: "13.4.0", + PURL: "pkg:npm/%40testing-library/react@13.4.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "@testing-library/user-event", - Version: "13.5.0", - PURL: "pkg:npm/%40testing-library/user-event@13.5.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@testing-library/user-event", + Version: "13.5.0", + PURL: "pkg:npm/%40testing-library/user-event@13.5.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "react", - Version: "18.2.0", - PURL: "pkg:npm/react@18.2.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "react", + Version: "18.2.0", + PURL: "pkg:npm/react@18.2.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "react-dom", - Version: "18.2.0", - PURL: "pkg:npm/react-dom@18.2.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "react-dom", + Version: "18.2.0", + PURL: "pkg:npm/react-dom@18.2.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "web-vitals", - Version: "2.1.4", - PURL: "pkg:npm/web-vitals@2.1.4", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "web-vitals", + Version: "2.1.4", + PURL: "pkg:npm/web-vitals@2.1.4", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "@babel/core", - Version: "7.21.4", - PURL: "pkg:npm/%40babel/core@7.21.4", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@babel/core", + Version: "7.21.4", + PURL: "pkg:npm/%40babel/core@7.21.4", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "@types/eslint", - Version: "8.37.0", - PURL: "pkg:npm/%40types/eslint@8.37.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/eslint", + Version: "8.37.0", + PURL: "pkg:npm/%40types/eslint@8.37.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "read-cache", - Version: "1.0.0", - PURL: "pkg:npm/read-cache@1.0.0", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "read-cache", + Version: "1.0.0", + PURL: "pkg:npm/read-cache@1.0.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "schema-utils", - Version: "3.1.2", - PURL: "pkg:npm/schema-utils@3.1.2", - Locations: locationSet, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "schema-utils", + Version: "3.1.2", + PURL: "pkg:npm/schema-utils@3.1.2", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, } diff --git a/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go b/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go index 20fac12fe6c3..93dbbb6c1e32 100644 --- a/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go @@ -22,85 +22,94 @@ func TestParseYarnBerry(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "@babel/code-frame", - Version: "7.10.4", - Locations: locations, - PURL: "pkg:npm/%40babel/code-frame@7.10.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "@types/minimatch", - Version: "3.0.3", - Locations: locations, - PURL: "pkg:npm/%40types/minimatch@3.0.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "@types/qs", - Version: "6.9.4", - Locations: locations, - PURL: "pkg:npm/%40types/qs@6.9.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "ajv", - Version: "6.12.3", - Locations: locations, - PURL: "pkg:npm/ajv@6.12.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "asn1.js", - Version: "4.10.1", - Locations: locations, - PURL: "pkg:npm/asn1.js@4.10.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "atob", - Version: "2.1.2", - Locations: locations, - PURL: "pkg:npm/atob@2.1.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "aws-sdk", - Version: "2.706.0", - PURL: "pkg:npm/aws-sdk@2.706.0", - Locations: locations, - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "c0n-fab_u.laTION", - Version: "7.7.7", - Locations: locations, - PURL: "pkg:npm/c0n-fab_u.laTION@7.7.7", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, - }, - { - Name: "jhipster-core", - Version: "7.3.4", - Locations: locations, - PURL: "pkg:npm/jhipster-core@7.3.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, - Metadata: pkg.YarnLockEntry{}, + Name: "@babel/code-frame", + Version: "7.10.4", + Locations: locations, + PURL: "pkg:npm/%40babel/code-frame@7.10.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "@types/minimatch", + Version: "3.0.3", + Locations: locations, + PURL: "pkg:npm/%40types/minimatch@3.0.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "@types/qs", + Version: "6.9.4", + Locations: locations, + PURL: "pkg:npm/%40types/qs@6.9.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "ajv", + Version: "6.12.3", + Locations: locations, + PURL: "pkg:npm/ajv@6.12.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "asn1.js", + Version: "4.10.1", + Locations: locations, + PURL: "pkg:npm/asn1.js@4.10.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "atob", + Version: "2.1.2", + Locations: locations, + PURL: "pkg:npm/atob@2.1.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "aws-sdk", + Version: "2.706.0", + PURL: "pkg:npm/aws-sdk@2.706.0", + Locations: locations, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "c0n-fab_u.laTION", + Version: "7.7.7", + Locations: locations, + PURL: "pkg:npm/c0n-fab_u.laTION@7.7.7", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, + }, + { + Name: "jhipster-core", + Version: "7.3.4", + Locations: locations, + PURL: "pkg:npm/jhipster-core@7.3.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pkg.YarnLockEntry{}, }, } @@ -115,60 +124,65 @@ func TestParseYarnLock(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "@babel/code-frame", - Version: "7.10.4", - Locations: locations, - PURL: "pkg:npm/%40babel/code-frame@7.10.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@babel/code-frame", + Version: "7.10.4", + Locations: locations, + PURL: "pkg:npm/%40babel/code-frame@7.10.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a", Integrity: "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", }, }, { - Name: "@types/minimatch", - Version: "3.0.3", - Locations: locations, - PURL: "pkg:npm/%40types/minimatch@3.0.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/minimatch", + Version: "3.0.3", + Locations: locations, + PURL: "pkg:npm/%40types/minimatch@3.0.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d", Integrity: "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", }, }, { - Name: "@types/qs", - Version: "6.9.4", - Locations: locations, - PURL: "pkg:npm/%40types/qs@6.9.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@types/qs", + Version: "6.9.4", + Locations: locations, + PURL: "pkg:npm/%40types/qs@6.9.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a", Integrity: "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==", }, }, { - Name: "ajv", - Version: "6.12.3", - Locations: locations, - PURL: "pkg:npm/ajv@6.12.3", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "ajv", + Version: "6.12.3", + Locations: locations, + PURL: "pkg:npm/ajv@6.12.3", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706", Integrity: "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", }, }, { - Name: "asn1.js", - Version: "4.10.1", - Locations: locations, - PURL: "pkg:npm/asn1.js@4.10.1", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "asn1.js", + Version: "4.10.1", + Locations: locations, + PURL: "pkg:npm/asn1.js@4.10.1", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0", Integrity: "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", @@ -179,45 +193,49 @@ func TestParseYarnLock(t *testing.T) { Version: "2.1.2", Locations: locations, - PURL: "pkg:npm/atob@2.1.2", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + PURL: "pkg:npm/atob@2.1.2", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9", Integrity: "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", }, }, { - Name: "aws-sdk", - Version: "2.706.0", - Locations: locations, - PURL: "pkg:npm/aws-sdk@2.706.0", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "aws-sdk", + Version: "2.706.0", + Locations: locations, + PURL: "pkg:npm/aws-sdk@2.706.0", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.706.0.tgz#09f65e9a91ecac5a635daf934082abae30eca953", Integrity: "sha512-7GT+yrB5Wb/zOReRdv/Pzkb2Qt+hz6B/8FGMVaoysX3NryHvQUdz7EQWi5yhg9CxOjKxdw5lFwYSs69YlSp1KA==", }, }, { - Name: "jhipster-core", - Version: "7.3.4", - Locations: locations, - PURL: "pkg:npm/jhipster-core@7.3.4", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "jhipster-core", + Version: "7.3.4", + Locations: locations, + PURL: "pkg:npm/jhipster-core@7.3.4", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/jhipster-core/-/jhipster-core-7.3.4.tgz#c34b8c97c7f4e8b7518dae015517e2112c73cc80", Integrity: "sha512-AUhT69kNkqppaJZVfan/xnKG4Gs9Ggj7YLtTZFVe+xg+THrbMb5Ng7PL07PDlDw4KAEA33GMCwuAf65E8EpC4g==", }, }, { - Name: "something-i-made-up", - Version: "7.7.7", - Locations: locations, - PURL: "pkg:npm/something-i-made-up@7.7.7", - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "something-i-made-up", + Version: "7.7.7", + Locations: locations, + PURL: "pkg:npm/something-i-made-up@7.7.7", + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/something-i-made-up/-/c0n-fab_u.laTION-7.7.7.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0", Integrity: "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", @@ -258,13 +276,14 @@ func TestSearchYarnForLicenses(t *testing.T) { }, expectedPackages: []pkg.Package{ { - Name: "@babel/code-frame", - Version: "7.10.4", - Locations: locations, - PURL: "pkg:npm/%40babel/code-frame@7.10.4", - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), - Language: pkg.JavaScript, - Type: pkg.NpmPkg, + Name: "@babel/code-frame", + Version: "7.10.4", + Locations: locations, + PURL: "pkg:npm/%40babel/code-frame@7.10.4", + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.YarnLockEntry{ Resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a", Integrity: "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", diff --git a/syft/pkg/cataloger/kernel/cataloger_test.go b/syft/pkg/cataloger/kernel/cataloger_test.go index a440c79813f1..a62f7132a31e 100644 --- a/syft/pkg/cataloger/kernel/cataloger_test.go +++ b/syft/pkg/cataloger/kernel/cataloger_test.go @@ -21,9 +21,10 @@ func Test_KernelCataloger(t *testing.T) { "/lib/modules/6.0.7-301.fc37.x86_64/vmlinuz", ), ), - Type: pkg.LinuxKernelPkg, - PURL: "pkg:generic/linux-kernel@6.0.7-301.fc37.x86_64", - CPEs: []cpe.CPE{cpe.Must("cpe:2.3:o:linux:linux_kernel:6.0.7-301.fc37.x86_64:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)}, + Type: pkg.LinuxKernelPkg, + PURL: "pkg:generic/linux-kernel@6.0.7-301.fc37.x86_64", + CPEs: []cpe.CPE{cpe.Must("cpe:2.3:o:linux:linux_kernel:6.0.7-301.fc37.x86_64:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)}, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.LinuxKernel{ Name: "", Architecture: "x86", @@ -56,8 +57,9 @@ func Test_KernelCataloger(t *testing.T) { ), ), ), - Type: pkg.LinuxKernelModulePkg, - PURL: "pkg:generic/ttynull", + Type: pkg.LinuxKernelModulePkg, + PURL: "pkg:generic/ttynull", + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.LinuxKernelModule{ Name: "ttynull", Version: "", diff --git a/syft/pkg/cataloger/kernel/package.go b/syft/pkg/cataloger/kernel/package.go index 28e9d6a99e04..97e250f7e39d 100644 --- a/syft/pkg/cataloger/kernel/package.go +++ b/syft/pkg/cataloger/kernel/package.go @@ -26,13 +26,14 @@ func createLinuxKernelCPEs(version string) []cpe.CPE { func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Location) pkg.Package { p := pkg.Package{ - Name: linuxKernelPackageName, - Version: metadata.Version, - Locations: file.NewLocationSet(archiveLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - PURL: packageURL(linuxKernelPackageName, metadata.Version), - Type: pkg.LinuxKernelPkg, - Metadata: metadata, - CPEs: createLinuxKernelCPEs(metadata.Version), + Name: linuxKernelPackageName, + Version: metadata.Version, + Locations: file.NewLocationSet(archiveLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + PURL: packageURL(linuxKernelPackageName, metadata.Version), + Type: pkg.LinuxKernelPkg, + Metadata: metadata, + Dependencies: pkg.UnknownDependencyCompleteness, + CPEs: createLinuxKernelCPEs(metadata.Version), } p.SetID() @@ -42,13 +43,14 @@ func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Locati func newLinuxKernelModulePackage(metadata pkg.LinuxKernelModule, kmLocation file.Location) pkg.Package { p := pkg.Package{ - Name: metadata.Name, - Version: metadata.Version, - Locations: file.NewLocationSet(kmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(kmLocation, metadata.License)...), - PURL: packageURL(metadata.Name, metadata.Version), - Type: pkg.LinuxKernelModulePkg, - Metadata: metadata, + Name: metadata.Name, + Version: metadata.Version, + Locations: file.NewLocationSet(kmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(kmLocation, metadata.License)...), + PURL: packageURL(metadata.Name, metadata.Version), + Type: pkg.LinuxKernelModulePkg, + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: metadata, } p.SetID() diff --git a/syft/pkg/cataloger/lua/package.go b/syft/pkg/cataloger/lua/package.go index c9eaa4da9955..485367d49552 100644 --- a/syft/pkg/cataloger/lua/package.go +++ b/syft/pkg/cataloger/lua/package.go @@ -16,6 +16,8 @@ func newLuaRocksPackage(u luaRocksPackage, indexLocation file.Location) pkg.Pack Language: pkg.Lua, Licenses: pkg.NewLicenseSet(license...), Type: pkg.LuaRocksPkg, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.LuaRocksPackage{ Name: u.Name, Version: u.Version, diff --git a/syft/pkg/cataloger/lua/parse_rockspec_test.go b/syft/pkg/cataloger/lua/parse_rockspec_test.go index a85cda58c3a1..bc0b5578c7ac 100644 --- a/syft/pkg/cataloger/lua/parse_rockspec_test.go +++ b/syft/pkg/cataloger/lua/parse_rockspec_test.go @@ -24,6 +24,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache-2.0", file.NewLocation("test-fixtures/rockspec/kong-3.7.0-0.rockspec")), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.LuaRocksPackage{ Name: "kong", Version: "3.7.0-0", @@ -45,6 +46,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT/X11", file.NewLocation("test-fixtures/rockspec/lpeg-1.0.2-1.rockspec")), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.LuaRocksPackage{ Name: "LPeg", Version: "1.0.2-1", @@ -66,6 +68,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation("test-fixtures/rockspec/kong-pgmoon-1.16.2-1.rockspec")), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.LuaRocksPackage{ Name: "kong-pgmoon", Version: "1.16.2-1", @@ -87,6 +90,7 @@ func TestParseRockspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT/X11", file.NewLocation("test-fixtures/rockspec/luasyslog-2.0.1-1.rockspec")), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.LuaRocksPackage{ Name: "luasyslog", Version: "2.0.1-1", diff --git a/syft/pkg/cataloger/nix/cataloger_test.go b/syft/pkg/cataloger/nix/cataloger_test.go index ff929b9f8a38..a287930c15d7 100644 --- a/syft/pkg/cataloger/nix/cataloger_test.go +++ b/syft/pkg/cataloger/nix/cataloger_test.go @@ -20,12 +20,13 @@ func TestCataloger_Catalog(t *testing.T) { fixture: "test-fixtures/fixture-1", wantPkgs: []pkg.Package{ { - Name: "glibc", - Version: "2.34-210", - PURL: "pkg:nix/glibc@2.34-210?output=bin&outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga", - Locations: file.NewLocationSet(file.NewLocation("nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin")), - FoundBy: catalogerName, - Type: pkg.NixPkg, + Name: "glibc", + Version: "2.34-210", + PURL: "pkg:nix/glibc@2.34-210?output=bin&outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga", + Locations: file.NewLocationSet(file.NewLocation("nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin")), + FoundBy: catalogerName, + Type: pkg.NixPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NixStoreEntry{ OutputHash: "h0cnbmfcn93xm5dg2x27ixhag1cwndga", Output: "bin", diff --git a/syft/pkg/cataloger/nix/package.go b/syft/pkg/cataloger/nix/package.go index 56f8acfa9075..dbf2315c6ad0 100644 --- a/syft/pkg/cataloger/nix/package.go +++ b/syft/pkg/cataloger/nix/package.go @@ -14,6 +14,8 @@ func newNixStorePackage(storePath nixStorePath, locations ...file.Location) pkg. Locations: file.NewLocationSet(locations...), Type: pkg.NixPkg, PURL: packageURL(storePath), + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.NixStoreEntry{ OutputHash: storePath.outputHash, Output: storePath.output, diff --git a/syft/pkg/cataloger/ocaml/package.go b/syft/pkg/cataloger/ocaml/package.go index 5144add41077..b4818ba5d8be 100644 --- a/syft/pkg/cataloger/ocaml/package.go +++ b/syft/pkg/cataloger/ocaml/package.go @@ -15,7 +15,9 @@ func newOpamPackage(m pkg.OpamPackage, fileLocation file.Location) pkg.Package { Locations: file.NewLocationSet(fileLocation), Type: pkg.OpamPkg, Language: pkg.OCaml, - Metadata: m, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/ocaml/parse_opam_test.go b/syft/pkg/cataloger/ocaml/parse_opam_test.go index 63b5fc9d37b3..7faf129517bc 100644 --- a/syft/pkg/cataloger/ocaml/parse_opam_test.go +++ b/syft/pkg/cataloger/ocaml/parse_opam_test.go @@ -36,8 +36,9 @@ func TestParseOpamPackage(t *testing.T) { "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception", )..., ), - Language: pkg.OCaml, - Type: pkg.OpamPkg, + Language: pkg.OCaml, + Type: pkg.OpamPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.OpamPackage{ Name: "ocaml-base-compiler", Version: "4.14.0", @@ -65,8 +66,9 @@ func TestParseOpamPackage(t *testing.T) { "ISC", )..., ), - Language: pkg.OCaml, - Type: pkg.OpamPkg, + Language: pkg.OCaml, + Type: pkg.OpamPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.OpamPackage{ Name: "alcotest", Version: "1.5.0", diff --git a/syft/pkg/cataloger/php/package.go b/syft/pkg/cataloger/php/package.go index f359603735d1..ff8a67a7acf7 100644 --- a/syft/pkg/cataloger/php/package.go +++ b/syft/pkg/cataloger/php/package.go @@ -17,7 +17,9 @@ func newComposerLockPackage(pd parsedLockData, indexLocation file.Location) pkg. PURL: packageURL(pd.Name, pd.Version), Language: pkg.PHP, Type: pkg.PhpComposerPkg, - Metadata: pd.PhpComposerLockEntry, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pd.PhpComposerLockEntry, } p.SetID() @@ -33,7 +35,9 @@ func newComposerInstalledPackage(pd parsedInstalledData, indexLocation file.Loca PURL: packageURL(pd.Name, pd.Version), Language: pkg.PHP, Type: pkg.PhpComposerPkg, - Metadata: pd.PhpComposerInstalledEntry, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pd.PhpComposerInstalledEntry, } p.SetID() @@ -49,7 +53,9 @@ func newPeclPackage(pd pkg.PhpPeclEntry, indexLocation file.Location) pkg.Packag PURL: packageURLFromPecl(pd.Name, pd.Version), Language: pkg.PHP, Type: pkg.PhpPeclPkg, - Metadata: pd, + // no attempt is made by the parser function to raise up dependency relationships + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pd, } p.SetID() diff --git a/syft/pkg/cataloger/php/parse_composer_lock_test.go b/syft/pkg/cataloger/php/parse_composer_lock_test.go index 1da97c42d2e0..b85fdb83a282 100644 --- a/syft/pkg/cataloger/php/parse_composer_lock_test.go +++ b/syft/pkg/cataloger/php/parse_composer_lock_test.go @@ -22,8 +22,9 @@ func TestParseComposerFileLock(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), - Language: pkg.PHP, - Type: pkg.PhpComposerPkg, + Language: pkg.PHP, + Type: pkg.PhpComposerPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PhpComposerLockEntry{ Name: "adoy/fastcgi-client", Version: "1.0.2", @@ -62,7 +63,8 @@ func TestParseComposerFileLock(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), - Type: pkg.PhpComposerPkg, + Type: pkg.PhpComposerPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PhpComposerLockEntry{ Name: "alcaeus/mongo-php-adapter", Version: "1.1.11", diff --git a/syft/pkg/cataloger/php/parse_installed_json_test.go b/syft/pkg/cataloger/php/parse_installed_json_test.go index 7e0c06c3203c..40bdb90079f8 100644 --- a/syft/pkg/cataloger/php/parse_installed_json_test.go +++ b/syft/pkg/cataloger/php/parse_installed_json_test.go @@ -26,6 +26,7 @@ func TestParseInstalledJsonComposerV1(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("MIT"), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PhpComposerInstalledEntry{ Name: "asm89/stack-cors", Version: "1.3.0", @@ -75,6 +76,7 @@ func TestParseInstalledJsonComposerV1(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicense("MIT"), ), + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PhpComposerInstalledEntry{ Name: "behat/mink", Version: "v1.8.1", diff --git a/syft/pkg/cataloger/php/parse_pecl_serialized_test.go b/syft/pkg/cataloger/php/parse_pecl_serialized_test.go index 84f84ea72820..cba1dfc96e5b 100644 --- a/syft/pkg/cataloger/php/parse_pecl_serialized_test.go +++ b/syft/pkg/cataloger/php/parse_pecl_serialized_test.go @@ -22,8 +22,9 @@ func TestParsePeclSerialized(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("PHP License", file.NewLocation(fixture)), ), - Language: pkg.PHP, - Type: pkg.PhpPeclPkg, + Language: pkg.PHP, + Type: pkg.PhpPeclPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PhpPeclEntry{ Name: "memcached", Version: "3.2.0", diff --git a/syft/pkg/cataloger/python/cataloger_test.go b/syft/pkg/cataloger/python/cataloger_test.go index 8e827322ebfd..5d508b01277b 100644 --- a/syft/pkg/cataloger/python/cataloger_test.go +++ b/syft/pkg/cataloger/python/cataloger_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" @@ -23,11 +24,12 @@ func Test_PackageCataloger(t *testing.T) { name: "egg-file-no-version", fixtures: []string{"test-fixtures/no-version-py3.8.egg-info"}, expectedPackage: pkg.Package{ - Name: "no-version", - PURL: "pkg:pypi/no-version", - Type: pkg.PythonPkg, - Language: pkg.Python, - FoundBy: "python-installed-package-cataloger", + Name: "no-version", + PURL: "pkg:pypi/no-version", + Type: pkg.PythonPkg, + Language: pkg.Python, + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "no-version", SitePackagesRootPath: "test-fixtures", @@ -50,7 +52,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache 2.0", file.NewLocation("test-fixtures/egg-info/PKG-INFO")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "requests", Version: "2.22.0", @@ -88,7 +91,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache 2.0", file.NewLocation("test-fixtures/casesensitive/EGG-INFO/PKG-INFO")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "requests", Version: "2.22.0", @@ -127,7 +131,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/dist-info/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -169,7 +174,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/casesensitive/DIST-INFO/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -207,7 +213,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/malformed-record/dist-info/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -239,7 +246,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("BSD License", file.NewLocation("test-fixtures/partial.dist-info/METADATA")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "Pygments", Version: "2.6.1", @@ -263,7 +271,8 @@ func Test_PackageCataloger(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("Apache 2.0", file.NewLocation("test-fixtures/test.egg-info")), ), - FoundBy: "python-installed-package-cataloger", + FoundBy: "python-installed-package-cataloger", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPackage{ Name: "requests", Version: "2.22.0", @@ -278,6 +287,8 @@ func Test_PackageCataloger(t *testing.T) { }, } + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) + for _, test := range tests { t.Run(test.name, func(t *testing.T) { resolver := file.NewMockResolverForPaths(test.fixtures...) @@ -289,6 +300,7 @@ func Test_PackageCataloger(t *testing.T) { pkgtest.NewCatalogTester(). WithResolver(resolver). + WithContext(ctx). Expects([]pkg.Package{test.expectedPackage}, nil). TestCataloger(t, NewInstalledPackageCataloger()) }) @@ -296,6 +308,8 @@ func Test_PackageCataloger(t *testing.T) { } func Test_PackageCataloger_IgnorePackage(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) + tests := []struct { MetadataFixture string }{ @@ -311,7 +325,7 @@ func Test_PackageCataloger_IgnorePackage(t *testing.T) { t.Run(test.MetadataFixture, func(t *testing.T) { resolver := file.NewMockResolverForPaths(test.MetadataFixture) - actual, _, err := NewInstalledPackageCataloger().Catalog(context.Background(), resolver) + actual, _, err := NewInstalledPackageCataloger().Catalog(ctx, resolver) require.NoError(t, err) if len(actual) != 0 { @@ -353,6 +367,7 @@ func Test_IndexCataloger_Globs(t *testing.T) { } func Test_PackageCataloger_Globs(t *testing.T) { + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) tests := []struct { name string fixture string @@ -375,6 +390,7 @@ func Test_PackageCataloger_Globs(t *testing.T) { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). FromDirectory(t, test.fixture). + WithContext(ctx). ExpectsResolverContentQueries(test.expected). IgnoreUnfulfilledPathResponses("**/pyvenv.cfg"). TestCataloger(t, NewInstalledPackageCataloger()) @@ -670,10 +686,13 @@ func Test_PackageCataloger_SitePackageRelationships(t *testing.T) { }, } + ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.NewDefaultScanner()) + for _, test := range tests { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). WithImageResolver(t, test.fixture). + WithContext(ctx). WithPackageStringer(stringPackage). ExpectsRelationshipStrings(test.expectedRelationships). TestCataloger(t, NewInstalledPackageCataloger()) diff --git a/syft/pkg/cataloger/python/package.go b/syft/pkg/cataloger/python/package.go index e7c86125651d..79f0672e11c1 100644 --- a/syft/pkg/cataloger/python/package.go +++ b/syft/pkg/cataloger/python/package.go @@ -20,16 +20,17 @@ func normalize(name string) string { return strings.ToLower(normalized) } -func newPackageForIndex(name, version string, locations ...file.Location) pkg.Package { +func newPackageForIndex(name, version string, dep pkg.DependencyCompleteness, locations ...file.Location) pkg.Package { name = normalize(name) p := pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(name, version, nil), - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(name, version, nil), + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, } p.SetID() @@ -37,17 +38,18 @@ func newPackageForIndex(name, version string, locations ...file.Location) pkg.Pa return p } -func newPackageForIndexWithMetadata(name, version string, metadata interface{}, locations ...file.Location) pkg.Package { +func newPackageForIndexWithMetadata(name, version string, metadata interface{}, dep pkg.DependencyCompleteness, locations ...file.Location) pkg.Package { name = normalize(name) p := pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(name, version, nil), - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: metadata, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(name, version, nil), + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, + Metadata: metadata, } p.SetID() @@ -55,17 +57,18 @@ func newPackageForIndexWithMetadata(name, version string, metadata interface{}, return p } -func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsEntry, locations ...file.Location) pkg.Package { +func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsEntry, dep pkg.DependencyCompleteness, locations ...file.Location) pkg.Package { name = normalize(name) p := pkg.Package{ - Name: name, - Version: version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(name, version, nil), - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: metadata, + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(name, version, nil), + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, + Metadata: metadata, } p.SetID() @@ -73,18 +76,19 @@ func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.Py return p } -func newPackageForPackage(m parsedData, licenses pkg.LicenseSet, sources ...file.Location) pkg.Package { +func newPackageForPackage(m parsedData, licenses pkg.LicenseSet, dep pkg.DependencyCompleteness, sources ...file.Location) pkg.Package { name := normalize(m.Name) p := pkg.Package{ - Name: name, - Version: m.Version, - PURL: packageURL(name, m.Version, &m.PythonPackage), - Locations: file.NewLocationSet(sources...), - Licenses: licenses, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: m.PythonPackage, + Name: name, + Version: m.Version, + PURL: packageURL(name, m.Version, &m.PythonPackage), + Locations: file.NewLocationSet(sources...), + Licenses: licenses, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: dep, + Metadata: m.PythonPackage, } p.SetID() diff --git a/syft/pkg/cataloger/python/parse_pipfile_lock.go b/syft/pkg/cataloger/python/parse_pipfile_lock.go index b2100060a5d8..8d940aa0ed16 100644 --- a/syft/pkg/cataloger/python/parse_pipfile_lock.go +++ b/syft/pkg/cataloger/python/parse_pipfile_lock.go @@ -66,7 +66,13 @@ func parsePipfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment index = "https://pypi.org/simple" } version := strings.TrimPrefix(pkgMeta.Version, "==") - pkgs = append(pkgs, newPackageForIndexWithMetadata(name, version, pkg.PythonPipfileLockEntry{Index: index, Hashes: pkgMeta.Hashes}, reader.Location)) + pkgs = append(pkgs, newPackageForIndexWithMetadata( + name, + version, + pkg.PythonPipfileLockEntry{Index: index, Hashes: pkgMeta.Hashes}, + pkg.UnknownDependencyCompleteness, // no attempt is made to resolve dependencies from the lock file + reader.Location, + )) } } diff --git a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go index 051bfd78ae2e..1facaf8bf4c8 100644 --- a/syft/pkg/cataloger/python/parse_pipfile_lock_test.go +++ b/syft/pkg/cataloger/python/parse_pipfile_lock_test.go @@ -15,12 +15,13 @@ func TestParsePipFileLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "aio-pika", - Version: "6.8.0", - PURL: "pkg:pypi/aio-pika@6.8.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aio-pika", + Version: "6.8.0", + PURL: "pkg:pypi/aio-pika@6.8.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://pypi.org/simple", Hashes: []string{ @@ -29,12 +30,13 @@ func TestParsePipFileLock(t *testing.T) { }}, }, { - Name: "aiodns", - Version: "2.0.0", - PURL: "pkg:pypi/aiodns@2.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aiodns", + Version: "2.0.0", + PURL: "pkg:pypi/aiodns@2.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://test.pypi.org/simple", Hashes: []string{ @@ -44,12 +46,13 @@ func TestParsePipFileLock(t *testing.T) { }, }, { - Name: "aiohttp", - Version: "3.7.4.post0", - PURL: "pkg:pypi/aiohttp@3.7.4.post0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aiohttp", + Version: "3.7.4.post0", + PURL: "pkg:pypi/aiohttp@3.7.4.post0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://pypi.org/simple", Hashes: []string{ @@ -59,12 +62,13 @@ func TestParsePipFileLock(t *testing.T) { }, }, { - Name: "aiohttp-jinja2", - Version: "1.4.2", - PURL: "pkg:pypi/aiohttp-jinja2@1.4.2", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "aiohttp-jinja2", + Version: "1.4.2", + PURL: "pkg:pypi/aiohttp-jinja2@1.4.2", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonPipfileLockEntry{ Index: "https://pypi.org/simple", Hashes: []string{ diff --git a/syft/pkg/cataloger/python/parse_poetry_lock.go b/syft/pkg/cataloger/python/parse_poetry_lock.go index 2b75f51b8719..10ea43980e7a 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock.go @@ -99,6 +99,7 @@ func poetryLockPackages(reader file.LocationReadCloser) ([]pkg.Package, error) { p.Name, p.Version, newPythonPoetryLockEntry(p), + pkg.CompleteDependencies, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) diff --git a/syft/pkg/cataloger/python/parse_poetry_lock_test.go b/syft/pkg/cataloger/python/parse_poetry_lock_test.go index 0cb0030a2e53..533a3a77d008 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock_test.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock_test.go @@ -14,12 +14,13 @@ func TestParsePoetryLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "added-value", - Version: "0.14.2", - PURL: "pkg:pypi/added-value@0.14.2", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "added-value", + Version: "0.14.2", + PURL: "pkg:pypi/added-value@0.14.2", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, Metadata: pkg.PythonPoetryLockEntry{ Index: "https://test.pypi.org/simple", Dependencies: []pkg.PythonPoetryLockDependencyEntry{ @@ -49,31 +50,34 @@ func TestParsePoetryLock(t *testing.T) { }, }, { - Name: "alabaster", - Version: "0.7.12", - PURL: "pkg:pypi/alabaster@0.7.12", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, + Name: "alabaster", + Version: "0.7.12", + PURL: "pkg:pypi/alabaster@0.7.12", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, }, { - Name: "appnope", - Version: "0.1.0", - PURL: "pkg:pypi/appnope@0.1.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, + Name: "appnope", + Version: "0.1.0", + PURL: "pkg:pypi/appnope@0.1.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, }, { - Name: "asciitree", - Version: "0.3.3", - PURL: "pkg:pypi/asciitree@0.3.3", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, - Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, + Name: "asciitree", + Version: "0.3.3", + PURL: "pkg:pypi/asciitree@0.3.3", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: pkg.PythonPoetryLockEntry{Index: "https://pypi.org/simple"}, }, } diff --git a/syft/pkg/cataloger/python/parse_requirements.go b/syft/pkg/cataloger/python/parse_requirements.go index 7d5d1d8a4ef5..bb356614133e 100644 --- a/syft/pkg/cataloger/python/parse_requirements.go +++ b/syft/pkg/cataloger/python/parse_requirements.go @@ -153,6 +153,7 @@ func (rp requirementsParser) parseRequirementsTxt(_ context.Context, _ file.Reso URL: parseURL(req.URL), Markers: req.Markers, }, + pkg.UnknownDependencyCompleteness, // not attempt is made by the parser function to resolve dependencies reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) diff --git a/syft/pkg/cataloger/python/parse_requirements_test.go b/syft/pkg/cataloger/python/parse_requirements_test.go index 6573b13d6200..6e918bab961f 100644 --- a/syft/pkg/cataloger/python/parse_requirements_test.go +++ b/syft/pkg/cataloger/python/parse_requirements_test.go @@ -17,36 +17,39 @@ func TestParseRequirementsTxt(t *testing.T) { pinnedPkgs := []pkg.Package{ { - Name: "flask", - Version: "4.0.0", - PURL: "pkg:pypi/flask@4.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "flask", + Version: "4.0.0", + PURL: "pkg:pypi/flask@4.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "flask", VersionConstraint: "== 4.0.0", }, }, { - Name: "foo", - Version: "1.0.0", - PURL: "pkg:pypi/foo@1.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "foo", + Version: "1.0.0", + PURL: "pkg:pypi/foo@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "foo", VersionConstraint: "== 1.0.0", }, }, { - Name: "someproject", - Version: "5.4", - PURL: "pkg:pypi/someproject@5.4", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "someproject", + Version: "5.4", + PURL: "pkg:pypi/someproject@5.4", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "SomeProject", VersionConstraint: "==5.4", @@ -54,48 +57,52 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "dots-allowed", - Version: "1.0.0", - PURL: "pkg:pypi/dots-allowed@1.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "dots-allowed", + Version: "1.0.0", + PURL: "pkg:pypi/dots-allowed@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "dots-._allowed", VersionConstraint: "== 1.0.0", }, }, { - Name: "argh", - Version: "0.26.2", - PURL: "pkg:pypi/argh@0.26.2", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "argh", + Version: "0.26.2", + PURL: "pkg:pypi/argh@0.26.2", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "argh", VersionConstraint: "==0.26.2", }, }, { - Name: "argh", - Version: "0.26.3", - PURL: "pkg:pypi/argh@0.26.3", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "argh", + Version: "0.26.3", + PURL: "pkg:pypi/argh@0.26.3", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "argh", VersionConstraint: "==0.26.3", }, }, { - Name: "celery", - Version: "4.4.7", - PURL: "pkg:pypi/celery@4.4.7", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "celery", + Version: "4.4.7", + PURL: "pkg:pypi/celery@4.4.7", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "celery", Extras: []string{"redis", "pytest"}, @@ -103,12 +110,13 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "githubsampleproject", - Version: "3.7.1", - PURL: "pkg:pypi/githubsampleproject@3.7.1", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "githubsampleproject", + Version: "3.7.1", + PURL: "pkg:pypi/githubsampleproject@3.7.1", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "GithubSampleProject", VersionConstraint: "== 3.7.1", @@ -116,12 +124,13 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "friendly-bard", - Version: "1.0.0", - PURL: "pkg:pypi/friendly-bard@1.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "friendly-bard", + Version: "1.0.0", + PURL: "pkg:pypi/friendly-bard@1.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "FrIeNdLy-_-bArD", VersionConstraint: "== 1.0.0", @@ -152,48 +161,52 @@ func TestParseRequirementsTxt(t *testing.T) { }, expectedPkgs: append([]pkg.Package{ { - Name: "mopidy-dirble", - Version: "1.1", - PURL: "pkg:pypi/mopidy-dirble@1.1", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mopidy-dirble", + Version: "1.1", + PURL: "pkg:pypi/mopidy-dirble@1.1", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "Mopidy-Dirble", VersionConstraint: "~= 1.1", }, }, { - Name: "sqlalchemy", - Version: "2.0.0", - PURL: "pkg:pypi/sqlalchemy@2.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "sqlalchemy", + Version: "2.0.0", + PURL: "pkg:pypi/sqlalchemy@2.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "sqlalchemy", VersionConstraint: ">= 1.0.0, <= 2.0.0, != 3.0.0, <= 3.0.0", }, }, { - Name: "bar", - Version: "2.0.0", - PURL: "pkg:pypi/bar@2.0.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "bar", + Version: "2.0.0", + PURL: "pkg:pypi/bar@2.0.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "bar", VersionConstraint: ">= 1.0.0, <= 2.0.0, != 3.0.0, <= 3.0.0", }, }, { - Name: "numpy", - Version: "3.4.1", - PURL: "pkg:pypi/numpy@3.4.1", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "numpy", + Version: "3.4.1", + PURL: "pkg:pypi/numpy@3.4.1", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "numpy", VersionConstraint: ">= 3.4.1", @@ -201,12 +214,13 @@ func TestParseRequirementsTxt(t *testing.T) { }, }, { - Name: "requests", - Version: "2.8.0", - PURL: "pkg:pypi/requests@2.8.0", - Locations: locations, - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "requests", + Version: "2.8.0", + PURL: "pkg:pypi/requests@2.8.0", + Locations: locations, + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.PythonRequirementsEntry{ Name: "requests", Extras: []string{"security"}, diff --git a/syft/pkg/cataloger/python/parse_setup.go b/syft/pkg/cataloger/python/parse_setup.go index ccbe916f5449..71813946079e 100644 --- a/syft/pkg/cataloger/python/parse_setup.go +++ b/syft/pkg/cataloger/python/parse_setup.go @@ -59,6 +59,7 @@ func parseSetup(_ context.Context, _ file.Resolver, _ *generic.Environment, read newPackageForIndex( name, version, + pkg.UnknownDependencyCompleteness, // no attempt is made by the parser function to resolve dependencies reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) diff --git a/syft/pkg/cataloger/python/parse_setup_test.go b/syft/pkg/cataloger/python/parse_setup_test.go index 665007296312..e35759de801b 100644 --- a/syft/pkg/cataloger/python/parse_setup_test.go +++ b/syft/pkg/cataloger/python/parse_setup_test.go @@ -20,39 +20,44 @@ func TestParseSetup(t *testing.T) { fixture: "test-fixtures/setup/setup.py", expected: []pkg.Package{ { - Name: "pathlib3", - Version: "2.2.0", - PURL: "pkg:pypi/pathlib3@2.2.0", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "pathlib3", + Version: "2.2.0", + PURL: "pkg:pypi/pathlib3@2.2.0", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "mypy", - Version: "v0.770", - PURL: "pkg:pypi/mypy@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy", + Version: "v0.770", + PURL: "pkg:pypi/mypy@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "mypy1", - Version: "v0.770", - PURL: "pkg:pypi/mypy1@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy1", + Version: "v0.770", + PURL: "pkg:pypi/mypy1@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "mypy2", - Version: "v0.770", - PURL: "pkg:pypi/mypy2@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy2", + Version: "v0.770", + PURL: "pkg:pypi/mypy2@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, { - Name: "mypy3", - Version: "v0.770", - PURL: "pkg:pypi/mypy3@v0.770", - Language: pkg.Python, - Type: pkg.PythonPkg, + Name: "mypy3", + Version: "v0.770", + PURL: "pkg:pypi/mypy3@v0.770", + Language: pkg.Python, + Type: pkg.PythonPkg, + Dependencies: pkg.UnknownDependencyCompleteness, }, }, }, diff --git a/syft/pkg/cataloger/python/parse_wheel_egg.go b/syft/pkg/cataloger/python/parse_wheel_egg.go index 2d2b9487c1a0..62a7afd70771 100644 --- a/syft/pkg/cataloger/python/parse_wheel_egg.go +++ b/syft/pkg/cataloger/python/parse_wheel_egg.go @@ -40,6 +40,7 @@ func parseWheelOrEgg(ctx context.Context, resolver file.Resolver, _ *generic.Env newPackageForPackage( *pd, findLicenses(ctx, licenseScanner, resolver, *pd), + pkg.CompleteDependencies, sources..., ), } diff --git a/syft/pkg/cataloger/r/cataloger_test.go b/syft/pkg/cataloger/r/cataloger_test.go index 18452cf8887c..cf3e6ae52e51 100644 --- a/syft/pkg/cataloger/r/cataloger_test.go +++ b/syft/pkg/cataloger/r/cataloger_test.go @@ -12,14 +12,15 @@ import ( func TestRPackageCataloger(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "base", - Version: "4.3.0", - FoundBy: "r-package-cataloger", - Locations: file.NewLocationSet(file.NewLocation("base/DESCRIPTION")), - Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("Part of R 4.3.0")}...), - Language: pkg.R, - Type: pkg.Rpkg, - PURL: "pkg:cran/base@4.3.0", + Name: "base", + Version: "4.3.0", + FoundBy: "r-package-cataloger", + Locations: file.NewLocationSet(file.NewLocation("base/DESCRIPTION")), + Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("Part of R 4.3.0")}...), + Language: pkg.R, + Type: pkg.Rpkg, + Dependencies: pkg.UnknownDependencyCompleteness, + PURL: "pkg:cran/base@4.3.0", Metadata: pkg.RDescription{ Title: "The R Base Package", Description: "Base R functions.", @@ -30,14 +31,15 @@ func TestRPackageCataloger(t *testing.T) { }, }, { - Name: "stringr", - Version: "1.5.0.9000", - FoundBy: "r-package-cataloger", - Locations: file.NewLocationSet(file.NewLocation("stringr/DESCRIPTION")), - Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("MIT")}...), - Language: pkg.R, - Type: pkg.Rpkg, - PURL: "pkg:cran/stringr@1.5.0.9000", + Name: "stringr", + Version: "1.5.0.9000", + FoundBy: "r-package-cataloger", + Locations: file.NewLocationSet(file.NewLocation("stringr/DESCRIPTION")), + Licenses: pkg.NewLicenseSet([]pkg.License{pkg.NewLicense("MIT")}...), + Language: pkg.R, + Type: pkg.Rpkg, + Dependencies: pkg.UnknownDependencyCompleteness, + PURL: "pkg:cran/stringr@1.5.0.9000", Metadata: pkg.RDescription{ Title: "Simple, Consistent Wrappers for Common String Operations", Description: "A consistent, simple and easy to use set of wrappers around the fantastic 'stringi' package. All function and argument names (and positions) are consistent, all functions deal with \"NA\"'s and zero length vectors in the same way, and the output from one function is easy to feed into the input of another.", diff --git a/syft/pkg/cataloger/r/package.go b/syft/pkg/cataloger/r/package.go index e5ca3c486792..683a1bece13d 100644 --- a/syft/pkg/cataloger/r/package.go +++ b/syft/pkg/cataloger/r/package.go @@ -24,7 +24,9 @@ func newPackage(pd parseData, locations ...file.Location) pkg.Package { Language: pkg.R, Type: pkg.Rpkg, PURL: packageURL(pd), - Metadata: pd.RDescription, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: pd.RDescription, } result.SetID() diff --git a/syft/pkg/cataloger/redhat/cataloger_test.go b/syft/pkg/cataloger/redhat/cataloger_test.go index 5dbb133b1610..5f233d7ecb3e 100644 --- a/syft/pkg/cataloger/redhat/cataloger_test.go +++ b/syft/pkg/cataloger/redhat/cataloger_test.go @@ -20,13 +20,14 @@ func Test_DBCataloger(t *testing.T) { locations := file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) basePkg := pkg.Package{ - Name: "basesystem", - Version: "11-13.el9", - Type: pkg.RpmPkg, - Locations: locations, - Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), - FoundBy: "rpm-db-cataloger", - PURL: "pkg:rpm/basesystem@11-13.el9?arch=noarch&upstream=basesystem-11-13.el9.src.rpm", + Name: "basesystem", + Version: "11-13.el9", + Type: pkg.RpmPkg, + Locations: locations, + Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), + FoundBy: "rpm-db-cataloger", + PURL: "pkg:rpm/basesystem@11-13.el9?arch=noarch&upstream=basesystem-11-13.el9.src.rpm", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "basesystem", Version: "11", @@ -50,13 +51,14 @@ func Test_DBCataloger(t *testing.T) { basePkg.SetID() bashPkg := pkg.Package{ - Name: "bash", - Version: "5.1.8-6.el9_1", - Type: pkg.RpmPkg, - Locations: locations, - Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("GPLv3+", dbLocation)), - FoundBy: "rpm-db-cataloger", - PURL: "pkg:rpm/bash@5.1.8-6.el9_1?arch=x86_64&upstream=bash-5.1.8-6.el9_1.src.rpm", + Name: "bash", + Version: "5.1.8-6.el9_1", + Type: pkg.RpmPkg, + Locations: locations, + Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("GPLv3+", dbLocation)), + FoundBy: "rpm-db-cataloger", + PURL: "pkg:rpm/bash@5.1.8-6.el9_1?arch=x86_64&upstream=bash-5.1.8-6.el9_1.src.rpm", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "bash", Version: "5.1.8", @@ -102,13 +104,14 @@ func Test_DBCataloger(t *testing.T) { bashPkg.SetID() filesystemPkg := pkg.Package{ - Name: "filesystem", - Version: "3.16-2.el9", - Type: pkg.RpmPkg, - Locations: locations, - Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), - FoundBy: "rpm-db-cataloger", - PURL: "pkg:rpm/filesystem@3.16-2.el9?arch=x86_64&upstream=filesystem-3.16-2.el9.src.rpm", + Name: "filesystem", + Version: "3.16-2.el9", + Type: pkg.RpmPkg, + Locations: locations, + Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", dbLocation)), + FoundBy: "rpm-db-cataloger", + PURL: "pkg:rpm/filesystem@3.16-2.el9?arch=x86_64&upstream=filesystem-3.16-2.el9.src.rpm", + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "filesystem", Version: "3.16", diff --git a/syft/pkg/cataloger/redhat/package.go b/syft/pkg/cataloger/redhat/package.go index 8bbcfe9a074a..dd75ba4d71fc 100644 --- a/syft/pkg/cataloger/redhat/package.go +++ b/syft/pkg/cataloger/redhat/package.go @@ -11,15 +11,16 @@ import ( "github.com/anchore/syft/syft/pkg" ) -func newDBPackage(dbOrRpmLocation file.Location, m pkg.RpmDBEntry, distro *linux.Release, licenses []string) pkg.Package { +func newDBPackage(dbOrRpmLocation file.Location, m pkg.RpmDBEntry, distro *linux.Release, licenses []string, deps pkg.DependencyCompleteness) pkg.Package { p := pkg.Package{ - Name: m.Name, - Version: toELVersion(m.Epoch, m.Version, m.Release), - Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbOrRpmLocation, licenses...)...), - PURL: packageURL(m.Name, m.Arch, m.Epoch, m.SourceRpm, m.Version, m.Release, distro), - Locations: file.NewLocationSet(dbOrRpmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - Type: pkg.RpmPkg, - Metadata: m, + Name: m.Name, + Version: toELVersion(m.Epoch, m.Version, m.Release), + Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbOrRpmLocation, licenses...)...), + PURL: packageURL(m.Name, m.Arch, m.Epoch, m.SourceRpm, m.Version, m.Release, distro), + Locations: file.NewLocationSet(dbOrRpmLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Type: pkg.RpmPkg, + Dependencies: deps, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/redhat/parse_rpm_db.go b/syft/pkg/cataloger/redhat/parse_rpm_db.go index 785b2c9adc3f..7448432d3983 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_db.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_db.go @@ -89,6 +89,7 @@ func parseRpmDB(_ context.Context, resolver file.Resolver, env *generic.Environm metadata, distro, []string{entry.License}, + pkg.CompleteDependencies, ) if !pkg.IsValid(&p) { diff --git a/syft/pkg/cataloger/redhat/parse_rpm_db_test.go b/syft/pkg/cataloger/redhat/parse_rpm_db_test.go index 7572642c88a5..d7f80eef7945 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_db_test.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_db_test.go @@ -100,6 +100,7 @@ func TestParseRpmDB(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", packagesLocation), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "dive", Epoch: nil, @@ -130,6 +131,7 @@ func TestParseRpmDB(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", packagesLocation), ), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RpmDBEntry{ Name: "dive", Epoch: nil, diff --git a/syft/pkg/cataloger/redhat/parse_rpm_manifest.go b/syft/pkg/cataloger/redhat/parse_rpm_manifest.go index 3e44ba8fdfe0..e763f0da8abf 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_manifest.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_manifest.go @@ -44,7 +44,10 @@ func parseRpmManifest(_ context.Context, _ file.Resolver, _ *generic.Environment continue } - p := newDBPackage(reader.Location, *metadata, nil, nil) + // Create a new package representing the RPM manifest entry + // note: we don't know the quality of the manifest dependency information, so even though there are multiple + // packages, we can't discern the connectivity of completeness of the data. + p := newDBPackage(reader.Location, *metadata, nil, nil, pkg.UnknownDependencyCompleteness) if !pkg.IsValid(&p) { continue diff --git a/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go b/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go index 5a2cd2666f41..f50f0629c013 100644 --- a/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go +++ b/syft/pkg/cataloger/redhat/parse_rpm_manifest_test.go @@ -13,11 +13,12 @@ func TestParseRpmManifest(t *testing.T) { location := file.NewLocation(fixture) expected := []pkg.Package{ { - Name: "mariner-release", - Version: "2.0-12.cm2", - PURL: "pkg:rpm/mariner-release@2.0-12.cm2?arch=noarch&upstream=mariner-release-2.0-12.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "mariner-release", + Version: "2.0-12.cm2", + PURL: "pkg:rpm/mariner-release@2.0-12.cm2?arch=noarch&upstream=mariner-release-2.0-12.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RpmDBEntry{ Name: "mariner-release", Epoch: nil, @@ -30,11 +31,12 @@ func TestParseRpmManifest(t *testing.T) { }, }, { - Name: "filesystem", - Version: "1.1-9.cm2", - PURL: "pkg:rpm/filesystem@1.1-9.cm2?arch=x86_64&upstream=filesystem-1.1-9.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "filesystem", + Version: "1.1-9.cm2", + PURL: "pkg:rpm/filesystem@1.1-9.cm2?arch=x86_64&upstream=filesystem-1.1-9.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RpmDBEntry{ Name: "filesystem", Epoch: nil, @@ -47,11 +49,12 @@ func TestParseRpmManifest(t *testing.T) { }, }, { - Name: "glibc", - Version: "2.35-2.cm2", - PURL: "pkg:rpm/glibc@2.35-2.cm2?arch=x86_64&upstream=glibc-2.35-2.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "glibc", + Version: "2.35-2.cm2", + PURL: "pkg:rpm/glibc@2.35-2.cm2?arch=x86_64&upstream=glibc-2.35-2.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RpmDBEntry{ Name: "glibc", Epoch: nil, @@ -64,11 +67,12 @@ func TestParseRpmManifest(t *testing.T) { }, }, { - Name: "openssl-libs", - Version: "1.1.1k-15.cm2", - PURL: "pkg:rpm/openssl-libs@1.1.1k-15.cm2?arch=x86_64&upstream=openssl-1.1.1k-15.cm2.src.rpm", - Locations: file.NewLocationSet(location), - Type: pkg.RpmPkg, + Name: "openssl-libs", + Version: "1.1.1k-15.cm2", + PURL: "pkg:rpm/openssl-libs@1.1.1k-15.cm2?arch=x86_64&upstream=openssl-1.1.1k-15.cm2.src.rpm", + Locations: file.NewLocationSet(location), + Type: pkg.RpmPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RpmDBEntry{ Name: "openssl-libs", Epoch: nil, diff --git a/syft/pkg/cataloger/ruby/package.go b/syft/pkg/cataloger/ruby/package.go index 349fd59491c0..9b87af972bf2 100644 --- a/syft/pkg/cataloger/ruby/package.go +++ b/syft/pkg/cataloger/ruby/package.go @@ -14,6 +14,8 @@ func newGemfileLockPackage(name, version string, locations ...file.Location) pkg Locations: file.NewLocationSet(locations...), Language: pkg.Ruby, Type: pkg.GemPkg, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, } p.SetID() @@ -30,7 +32,9 @@ func newGemspecPackage(m gemData, gemSpecLocation file.Location) pkg.Package { PURL: packageURL(m.Name, m.Version), Language: pkg.Ruby, Type: pkg.GemPkg, - Metadata: m.RubyGemspec, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: m.RubyGemspec, } p.SetID() diff --git a/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go b/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go index ad94283aae37..4cd48e3ed61a 100644 --- a/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go +++ b/syft/pkg/cataloger/ruby/parse_gemfile_lock_test.go @@ -12,58 +12,58 @@ func TestParseGemfileLockEntries(t *testing.T) { fixture := "test-fixtures/Gemfile.lock" locations := file.NewLocationSet(file.NewLocation(fixture)) var expectedPkgs = []pkg.Package{ - {Name: "actionmailer", Version: "4.1.1", PURL: "pkg:gem/actionmailer@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "actionpack", Version: "4.1.1", PURL: "pkg:gem/actionpack@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "actionview", Version: "4.1.1", PURL: "pkg:gem/actionview@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "activemodel", Version: "4.1.1", PURL: "pkg:gem/activemodel@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "activerecord", Version: "4.1.1", PURL: "pkg:gem/activerecord@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "activesupport", Version: "4.1.1", PURL: "pkg:gem/activesupport@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "arel", Version: "5.0.1.20140414130214", PURL: "pkg:gem/arel@5.0.1.20140414130214", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "bootstrap-sass", Version: "3.1.1.1", PURL: "pkg:gem/bootstrap-sass@3.1.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "builder", Version: "3.2.2", PURL: "pkg:gem/builder@3.2.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "coffee-rails", Version: "4.0.1", PURL: "pkg:gem/coffee-rails@4.0.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "coffee-script", Version: "2.2.0", PURL: "pkg:gem/coffee-script@2.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "coffee-script-source", Version: "1.7.0", PURL: "pkg:gem/coffee-script-source@1.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "erubis", Version: "2.7.0", PURL: "pkg:gem/erubis@2.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "execjs", Version: "2.0.2", PURL: "pkg:gem/execjs@2.0.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "google-cloud-errors", Version: "1.3.0", PURL: "pkg:gem/google-cloud-errors@1.3.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "hike", Version: "1.2.3", PURL: "pkg:gem/hike@1.2.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "i18n", Version: "0.6.9", PURL: "pkg:gem/i18n@0.6.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "jbuilder", Version: "2.0.7", PURL: "pkg:gem/jbuilder@2.0.7", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "jquery-rails", Version: "3.1.0", PURL: "pkg:gem/jquery-rails@3.1.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "json", Version: "1.8.1", PURL: "pkg:gem/json@1.8.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "kgio", Version: "2.9.2", PURL: "pkg:gem/kgio@2.9.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "libv8", Version: "3.16.14.3", PURL: "pkg:gem/libv8@3.16.14.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "mail", Version: "2.5.4", PURL: "pkg:gem/mail@2.5.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "mime-types", Version: "1.25.1", PURL: "pkg:gem/mime-types@1.25.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "minitest", Version: "5.3.4", PURL: "pkg:gem/minitest@5.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "multi_json", Version: "1.10.1", PURL: "pkg:gem/multi_json@1.10.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "mysql2", Version: "0.3.16", PURL: "pkg:gem/mysql2@0.3.16", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "polyglot", Version: "0.3.4", PURL: "pkg:gem/polyglot@0.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rack", Version: "1.5.2", PURL: "pkg:gem/rack@1.5.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rack-test", Version: "0.6.2", PURL: "pkg:gem/rack-test@0.6.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rails", Version: "4.1.1", PURL: "pkg:gem/rails@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "railties", Version: "4.1.1", PURL: "pkg:gem/railties@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "raindrops", Version: "0.13.0", PURL: "pkg:gem/raindrops@0.13.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rake", Version: "10.3.2", PURL: "pkg:gem/rake@10.3.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "rdoc", Version: "4.1.1", PURL: "pkg:gem/rdoc@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "ref", Version: "1.0.5", PURL: "pkg:gem/ref@1.0.5", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sass", Version: "3.2.19", PURL: "pkg:gem/sass@3.2.19", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sass-rails", Version: "4.0.3", PURL: "pkg:gem/sass-rails@4.0.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sdoc", Version: "0.4.0", PURL: "pkg:gem/sdoc@0.4.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "spring", Version: "1.1.3", PURL: "pkg:gem/spring@1.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sprockets", Version: "2.11.0", PURL: "pkg:gem/sprockets@2.11.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sprockets-rails", Version: "2.1.3", PURL: "pkg:gem/sprockets-rails@2.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "sqlite3", Version: "1.3.9", PURL: "pkg:gem/sqlite3@1.3.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "therubyracer", Version: "0.12.1", PURL: "pkg:gem/therubyracer@0.12.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "thor", Version: "0.19.1", PURL: "pkg:gem/thor@0.19.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "thread_safe", Version: "0.3.3", PURL: "pkg:gem/thread_safe@0.3.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "tilt", Version: "1.4.1", PURL: "pkg:gem/tilt@1.4.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "treetop", Version: "1.4.15", PURL: "pkg:gem/treetop@1.4.15", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "turbolinks", Version: "3.0.0", PURL: "pkg:gem/turbolinks@3.0.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "tzinfo", Version: "1.2.0", PURL: "pkg:gem/tzinfo@1.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "uglifier", Version: "2.5.0", PURL: "pkg:gem/uglifier@2.5.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, - {Name: "unicorn", Version: "4.8.3", PURL: "pkg:gem/unicorn@4.8.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg}, + {Name: "actionmailer", Version: "4.1.1", PURL: "pkg:gem/actionmailer@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "actionpack", Version: "4.1.1", PURL: "pkg:gem/actionpack@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "actionview", Version: "4.1.1", PURL: "pkg:gem/actionview@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "activemodel", Version: "4.1.1", PURL: "pkg:gem/activemodel@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "activerecord", Version: "4.1.1", PURL: "pkg:gem/activerecord@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "activesupport", Version: "4.1.1", PURL: "pkg:gem/activesupport@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "arel", Version: "5.0.1.20140414130214", PURL: "pkg:gem/arel@5.0.1.20140414130214", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "bootstrap-sass", Version: "3.1.1.1", PURL: "pkg:gem/bootstrap-sass@3.1.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "builder", Version: "3.2.2", PURL: "pkg:gem/builder@3.2.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "coffee-rails", Version: "4.0.1", PURL: "pkg:gem/coffee-rails@4.0.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "coffee-script", Version: "2.2.0", PURL: "pkg:gem/coffee-script@2.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "coffee-script-source", Version: "1.7.0", PURL: "pkg:gem/coffee-script-source@1.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "erubis", Version: "2.7.0", PURL: "pkg:gem/erubis@2.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "execjs", Version: "2.0.2", PURL: "pkg:gem/execjs@2.0.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "google-cloud-errors", Version: "1.3.0", PURL: "pkg:gem/google-cloud-errors@1.3.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "hike", Version: "1.2.3", PURL: "pkg:gem/hike@1.2.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "i18n", Version: "0.6.9", PURL: "pkg:gem/i18n@0.6.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "jbuilder", Version: "2.0.7", PURL: "pkg:gem/jbuilder@2.0.7", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "jquery-rails", Version: "3.1.0", PURL: "pkg:gem/jquery-rails@3.1.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "json", Version: "1.8.1", PURL: "pkg:gem/json@1.8.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "kgio", Version: "2.9.2", PURL: "pkg:gem/kgio@2.9.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "libv8", Version: "3.16.14.3", PURL: "pkg:gem/libv8@3.16.14.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "mail", Version: "2.5.4", PURL: "pkg:gem/mail@2.5.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "mime-types", Version: "1.25.1", PURL: "pkg:gem/mime-types@1.25.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "minitest", Version: "5.3.4", PURL: "pkg:gem/minitest@5.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "multi_json", Version: "1.10.1", PURL: "pkg:gem/multi_json@1.10.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "mysql2", Version: "0.3.16", PURL: "pkg:gem/mysql2@0.3.16", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "polyglot", Version: "0.3.4", PURL: "pkg:gem/polyglot@0.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "rack", Version: "1.5.2", PURL: "pkg:gem/rack@1.5.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "rack-test", Version: "0.6.2", PURL: "pkg:gem/rack-test@0.6.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "rails", Version: "4.1.1", PURL: "pkg:gem/rails@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "railties", Version: "4.1.1", PURL: "pkg:gem/railties@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "raindrops", Version: "0.13.0", PURL: "pkg:gem/raindrops@0.13.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "rake", Version: "10.3.2", PURL: "pkg:gem/rake@10.3.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "rdoc", Version: "4.1.1", PURL: "pkg:gem/rdoc@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "ref", Version: "1.0.5", PURL: "pkg:gem/ref@1.0.5", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "sass", Version: "3.2.19", PURL: "pkg:gem/sass@3.2.19", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "sass-rails", Version: "4.0.3", PURL: "pkg:gem/sass-rails@4.0.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "sdoc", Version: "0.4.0", PURL: "pkg:gem/sdoc@0.4.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "spring", Version: "1.1.3", PURL: "pkg:gem/spring@1.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "sprockets", Version: "2.11.0", PURL: "pkg:gem/sprockets@2.11.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "sprockets-rails", Version: "2.1.3", PURL: "pkg:gem/sprockets-rails@2.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "sqlite3", Version: "1.3.9", PURL: "pkg:gem/sqlite3@1.3.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "therubyracer", Version: "0.12.1", PURL: "pkg:gem/therubyracer@0.12.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "thor", Version: "0.19.1", PURL: "pkg:gem/thor@0.19.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "thread_safe", Version: "0.3.3", PURL: "pkg:gem/thread_safe@0.3.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "tilt", Version: "1.4.1", PURL: "pkg:gem/tilt@1.4.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "treetop", Version: "1.4.15", PURL: "pkg:gem/treetop@1.4.15", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "turbolinks", Version: "3.0.0", PURL: "pkg:gem/turbolinks@3.0.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "tzinfo", Version: "1.2.0", PURL: "pkg:gem/tzinfo@1.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "uglifier", Version: "2.5.0", PURL: "pkg:gem/uglifier@2.5.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, + {Name: "unicorn", Version: "4.8.3", PURL: "pkg:gem/unicorn@4.8.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg, Dependencies: pkg.UnknownDependencyCompleteness}, } pkgtest.TestFileParser(t, fixture, parseGemFileLockEntries, expectedPkgs, nil) diff --git a/syft/pkg/cataloger/ruby/parse_gemspec_test.go b/syft/pkg/cataloger/ruby/parse_gemspec_test.go index f5ca64e9551a..1c74e39ad2ee 100644 --- a/syft/pkg/cataloger/ruby/parse_gemspec_test.go +++ b/syft/pkg/cataloger/ruby/parse_gemspec_test.go @@ -22,7 +22,8 @@ func TestParseGemspec(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("MIT", file.NewLocation(fixture)), ), - Language: pkg.Ruby, + Language: pkg.Ruby, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RubyGemspec{ Name: "bundler", Version: "2.1.4", diff --git a/syft/pkg/cataloger/rust/cataloger_test.go b/syft/pkg/cataloger/rust/cataloger_test.go index 3a7a356db215..8cded3b9faec 100644 --- a/syft/pkg/cataloger/rust/cataloger_test.go +++ b/syft/pkg/cataloger/rust/cataloger_test.go @@ -12,13 +12,14 @@ func TestNewAuditBinaryCataloger(t *testing.T) { expectedPkgs := []pkg.Package{ { - Name: "auditable", - Version: "0.1.0", - PURL: "pkg:cargo/auditable@0.1.0", - FoundBy: "cargo-auditable-binary-cataloger", - Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), - Language: pkg.Rust, - Type: pkg.RustPkg, + Name: "auditable", + Version: "0.1.0", + PURL: "pkg:cargo/auditable@0.1.0", + FoundBy: "cargo-auditable-binary-cataloger", + Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), + Language: pkg.Rust, + Type: pkg.RustPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RustBinaryAuditEntry{ Name: "auditable", Version: "0.1.0", @@ -26,13 +27,14 @@ func TestNewAuditBinaryCataloger(t *testing.T) { }, }, { - Name: "hello-auditable", - Version: "0.1.0", - PURL: "pkg:cargo/hello-auditable@0.1.0", - FoundBy: "cargo-auditable-binary-cataloger", - Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), - Language: pkg.Rust, - Type: pkg.RustPkg, + Name: "hello-auditable", + Version: "0.1.0", + PURL: "pkg:cargo/hello-auditable@0.1.0", + FoundBy: "cargo-auditable-binary-cataloger", + Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")), + Language: pkg.Rust, + Type: pkg.RustPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RustBinaryAuditEntry{ Name: "hello-auditable", Version: "0.1.0", diff --git a/syft/pkg/cataloger/rust/package.go b/syft/pkg/cataloger/rust/package.go index be67d96a9367..de65dd7443e0 100644 --- a/syft/pkg/cataloger/rust/package.go +++ b/syft/pkg/cataloger/rust/package.go @@ -11,13 +11,14 @@ import ( // Pkg returns the standard `pkg.Package` representation of the package referenced within the Cargo.lock metadata. func newPackageFromCargoMetadata(m pkg.RustCargoLockEntry, locations ...file.Location) pkg.Package { p := pkg.Package{ - Name: m.Name, - Version: m.Version, - Locations: file.NewLocationSet(locations...), - PURL: packageURL(m.Name, m.Version), - Language: pkg.Rust, - Type: pkg.RustPkg, - Metadata: m, + Name: m.Name, + Version: m.Version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(m.Name, m.Version), + Language: pkg.Rust, + Type: pkg.RustPkg, + Dependencies: pkg.CompleteDependencies, + Metadata: m, } p.SetID() @@ -46,6 +47,8 @@ func newPackageFromAudit(dep *rustaudit.Package, locations ...file.Location) pkg Language: pkg.Rust, Type: pkg.RustPkg, Locations: file.NewLocationSet(locations...), + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.RustBinaryAuditEntry{ Name: dep.Name, Version: dep.Version, diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go index 2d7d2b4b639f..8c65e09d096f 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock_test.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock_test.go @@ -13,13 +13,14 @@ func TestParseCargoLock(t *testing.T) { fixture := "test-fixtures/Cargo.lock" locations := file.NewLocationSet(file.NewLocation(fixture)) ansiTerm := pkg.Package{ - Name: "ansi_term", - Version: "0.12.1", - PURL: "pkg:cargo/ansi_term@0.12.1", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "ansi_term", + Version: "0.12.1", + PURL: "pkg:cargo/ansi_term@0.12.1", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "ansi_term", Version: "0.12.1", @@ -31,13 +32,14 @@ func TestParseCargoLock(t *testing.T) { }, } errno := pkg.Package{ - Name: "errno", - Version: "0.3.9", - PURL: "pkg:cargo/errno@0.3.9", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "errno", + Version: "0.3.9", + PURL: "pkg:cargo/errno@0.3.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "errno", Version: "0.3.9", @@ -49,13 +51,14 @@ func TestParseCargoLock(t *testing.T) { }, } matches := pkg.Package{ - Name: "matches", - Version: "0.1.8", - PURL: "pkg:cargo/matches@0.1.8", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "matches", + Version: "0.1.8", + PURL: "pkg:cargo/matches@0.1.8", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "matches", Version: "0.1.8", @@ -65,13 +68,14 @@ func TestParseCargoLock(t *testing.T) { }, } memchr := pkg.Package{ - Name: "memchr", - Version: "2.3.3", - PURL: "pkg:cargo/memchr@2.3.3", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "memchr", + Version: "2.3.3", + PURL: "pkg:cargo/memchr@2.3.3", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "memchr", Version: "2.3.3", @@ -82,13 +86,14 @@ func TestParseCargoLock(t *testing.T) { } natord := pkg.Package{ - Name: "natord", - Version: "1.0.9", - PURL: "pkg:cargo/natord@1.0.9", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "natord", + Version: "1.0.9", + PURL: "pkg:cargo/natord@1.0.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "natord", Version: "1.0.9", @@ -99,13 +104,14 @@ func TestParseCargoLock(t *testing.T) { } nom := pkg.Package{ - Name: "nom", - Version: "4.2.3", - PURL: "pkg:cargo/nom@4.2.3", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "nom", + Version: "4.2.3", + PURL: "pkg:cargo/nom@4.2.3", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "nom", Version: "4.2.3", @@ -118,13 +124,14 @@ func TestParseCargoLock(t *testing.T) { }, } schannel := pkg.Package{ - Name: "schannel", - Version: "0.1.26", - PURL: "pkg:cargo/schannel@0.1.26", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "schannel", + Version: "0.1.26", + PURL: "pkg:cargo/schannel@0.1.26", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "schannel", Version: "0.1.26", @@ -137,13 +144,14 @@ func TestParseCargoLock(t *testing.T) { } unicodeBidi := pkg.Package{ - Name: "unicode-bidi", - Version: "0.3.4", - PURL: "pkg:cargo/unicode-bidi@0.3.4", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "unicode-bidi", + Version: "0.3.4", + PURL: "pkg:cargo/unicode-bidi@0.3.4", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "unicode-bidi", Version: "0.3.4", @@ -157,13 +165,14 @@ func TestParseCargoLock(t *testing.T) { } versionCheck := pkg.Package{ - Name: "version_check", - Version: "0.1.5", - PURL: "pkg:cargo/version_check@0.1.5", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "version_check", + Version: "0.1.5", + PURL: "pkg:cargo/version_check@0.1.5", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "version_check", Version: "0.1.5", @@ -174,13 +183,14 @@ func TestParseCargoLock(t *testing.T) { } winapi := pkg.Package{ - Name: "winapi", - Version: "0.3.9", - PURL: "pkg:cargo/winapi@0.3.9", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "winapi", + Version: "0.3.9", + PURL: "pkg:cargo/winapi@0.3.9", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "winapi", Version: "0.3.9", @@ -194,13 +204,14 @@ func TestParseCargoLock(t *testing.T) { } winAPIi686PCWindowsGNU := pkg.Package{ - Name: "winapi-i686-pc-windows-gnu", - Version: "0.4.0", - PURL: "pkg:cargo/winapi-i686-pc-windows-gnu@0.4.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "winapi-i686-pc-windows-gnu", + Version: "0.4.0", + PURL: "pkg:cargo/winapi-i686-pc-windows-gnu@0.4.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "winapi-i686-pc-windows-gnu", Version: "0.4.0", @@ -211,13 +222,14 @@ func TestParseCargoLock(t *testing.T) { } winAPIx8664PCWindowsGNU := pkg.Package{ - Name: "winapi-x86_64-pc-windows-gnu", - Version: "0.4.0", - PURL: "pkg:cargo/winapi-x86_64-pc-windows-gnu@0.4.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "winapi-x86_64-pc-windows-gnu", + Version: "0.4.0", + PURL: "pkg:cargo/winapi-x86_64-pc-windows-gnu@0.4.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "winapi-x86_64-pc-windows-gnu", Version: "0.4.0", @@ -228,13 +240,14 @@ func TestParseCargoLock(t *testing.T) { } windowsSys52 := pkg.Package{ - Name: "windows-sys", - Version: "0.52.0", - PURL: "pkg:cargo/windows-sys@0.52.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "windows-sys", + Version: "0.52.0", + PURL: "pkg:cargo/windows-sys@0.52.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "windows-sys", Version: "0.52.0", @@ -245,13 +258,14 @@ func TestParseCargoLock(t *testing.T) { } windowsSys59 := pkg.Package{ - Name: "windows-sys", - Version: "0.59.0", - PURL: "pkg:cargo/windows-sys@0.59.0", - Locations: locations, - Language: pkg.Rust, - Type: pkg.RustPkg, - Licenses: pkg.NewLicenseSet(), + Name: "windows-sys", + Version: "0.59.0", + PURL: "pkg:cargo/windows-sys@0.59.0", + Locations: locations, + Language: pkg.Rust, + Type: pkg.RustPkg, + Licenses: pkg.NewLicenseSet(), + Dependencies: pkg.CompleteDependencies, Metadata: pkg.RustCargoLockEntry{ Name: "windows-sys", Version: "0.59.0", diff --git a/syft/pkg/cataloger/sbom/cataloger.go b/syft/pkg/cataloger/sbom/cataloger.go index 9779a8166e5a..e1483d459acc 100644 --- a/syft/pkg/cataloger/sbom/cataloger.go +++ b/syft/pkg/cataloger/sbom/cataloger.go @@ -54,15 +54,21 @@ func parseSBOM(_ context.Context, _ file.Resolver, _ *generic.Environment, reade var pkgs []pkg.Package relationships := s.Relationships + + for i := range relationships { + if p, ok := relationships[i].To.(pkg.Package); ok { + finalizePkg(&p, reader.Location) + relationships[i].To = p + } + + if p, ok := relationships[i].From.(pkg.Package); ok { + finalizePkg(&p, reader.Location) + relationships[i].From = p + } + } + for _, p := range s.Artifacts.Packages.Sorted() { - // replace all locations on the package with the location of the SBOM file. - // Why not keep the original list of locations? Since the "locations" field is meant to capture - // where there is evidence of this file, and the catalogers have not run against any file other than, - // the SBOM, this is the only location that is relevant for this cataloger. - p.Locations = file.NewLocationSet( - reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), - ) - p.FoundBy = catalogerName + finalizePkg(&p, reader.Location) pkgs = append(pkgs, p) relationships = append(relationships, artifact.Relationship{ @@ -75,6 +81,22 @@ func parseSBOM(_ context.Context, _ file.Resolver, _ *generic.Environment, reade return pkgs, relationships, nil } +func finalizePkg(p *pkg.Package, loc file.Location) { + // replace all locations on the package with the location of the SBOM file. + // Why not keep the original list of locations? Since the "locations" field is meant to capture + // where there is evidence of this file, and the catalogers have not run against any file other than, + // the SBOM, this is the only location that is relevant for this cataloger. + p.Locations = file.NewLocationSet( + loc.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) + p.FoundBy = catalogerName + + // we are entirely unaware of the quality of the SBOM being read from, the ecosystem really in use, the context + // where it was found, and thus are not able to reason about the dependency resolution mechanisms that + // are in play. + p.Dependencies = pkg.UnknownDependencyCompleteness +} + func adaptToReadSeeker(reader io.Reader) (io.ReadSeeker, error) { // with the stereoscope API and default file.Resolver implementation here in syft, odds are very high that // the underlying reader is already a ReadSeeker, so we can just return it as-is. We still want to diff --git a/syft/pkg/cataloger/sbom/cataloger_test.go b/syft/pkg/cataloger/sbom/cataloger_test.go index e53b14ae780e..a833d93573a9 100644 --- a/syft/pkg/cataloger/sbom/cataloger_test.go +++ b/syft/pkg/cataloger/sbom/cataloger_test.go @@ -20,15 +20,18 @@ func mustCPEs(s ...string) (c []cpe.CPE) { } func Test_parseSBOM(t *testing.T) { + sbomLocations := file.NewLocationSet(file.NewLocation("sbom.syft.json")) + expectedPkgs := []pkg.Package{ { - Name: "alpine-baselayout", - Version: "3.2.0-r23", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Name: "alpine-baselayout", + Version: "3.2.0-r23", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*", @@ -39,13 +42,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "alpine-baselayout-data", - Version: "3.2.0-r23", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/alpine-baselayout-data@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Name: "alpine-baselayout-data", + Version: "3.2.0-r23", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-baselayout-data@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-baselayout-data:alpine-baselayout-data:3.2.0-r23:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-baselayout-data:alpine_baselayout_data:3.2.0-r23:*:*:*:*:*:*:*", @@ -60,13 +64,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "alpine-keys", - Version: "2.4-r1", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/alpine-keys@2.4-r1?arch=x86_64&upstream=alpine-keys&distro=alpine-3.16.3", + Name: "alpine-keys", + Version: "2.4-r1", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-keys@2.4-r1?arch=x86_64&upstream=alpine-keys&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-keys:alpine-keys:2.4-r1:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-keys:alpine_keys:2.4-r1:*:*:*:*:*:*:*", @@ -77,13 +82,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "apk-tools", - Version: "2.12.9-r3", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/apk-tools@2.12.9-r3?arch=x86_64&upstream=apk-tools&distro=alpine-3.16.3", + Name: "apk-tools", + Version: "2.12.9-r3", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/apk-tools@2.12.9-r3?arch=x86_64&upstream=apk-tools&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:apk-tools:apk-tools:2.12.9-r3:*:*:*:*:*:*:*", "cpe:2.3:a:apk-tools:apk_tools:2.12.9-r3:*:*:*:*:*:*:*", @@ -94,13 +100,14 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "busybox", - Version: "1.35.0-r17", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Name: "busybox", + Version: "1.35.0-r17", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:busybox:busybox:1.35.0-r17:*:*:*:*:*:*:*", ), @@ -109,13 +116,14 @@ func Test_parseSBOM(t *testing.T) { Name: "ca-certificates-bundle", Version: "20220614-r0", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("MPL-2.0"), pkg.NewLicense("MIT"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/ca-certificates-bundle@20220614-r0?arch=x86_64&upstream=ca-certificates&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/ca-certificates-bundle@20220614-r0?arch=x86_64&upstream=ca-certificates&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:ca-certificates-bundle:ca-certificates-bundle:20220614-r0:*:*:*:*:*:*:*", "cpe:2.3:a:ca-certificates-bundle:ca_certificates_bundle:20220614-r0:*:*:*:*:*:*:*", @@ -133,13 +141,14 @@ func Test_parseSBOM(t *testing.T) { Name: "libc-utils", Version: "0.7.2-r3", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("BSD-2-Clause"), pkg.NewLicense("BSD-3-Clause"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/libc-utils@0.7.2-r3?arch=x86_64&upstream=libc-dev&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libc-utils@0.7.2-r3?arch=x86_64&upstream=libc-dev&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libc-utils:libc-utils:0.7.2-r3:*:*:*:*:*:*:*", "cpe:2.3:a:libc-utils:libc_utils:0.7.2-r3:*:*:*:*:*:*:*", @@ -150,37 +159,40 @@ func Test_parseSBOM(t *testing.T) { ), }, { - Name: "libcrypto1.1", - Version: "1.1.1s-r0", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/libcrypto1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Name: "libcrypto1.1", + Version: "1.1.1s-r0", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libcrypto1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libcrypto1.1:libcrypto1.1:1.1.1s-r0:*:*:*:*:*:*:*", ), }, { - Name: "libssl1.1", - Version: "1.1.1s-r0", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Name: "libssl1.1", + Version: "1.1.1s-r0", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), // SPDX expression is not set + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libssl1.1:libssl1.1:1.1.1s-r0:*:*:*:*:*:*:*", ), }, { - Name: "musl", - Version: "1.2.3-r1", - Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), // SPDX expression is not set - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Name: "musl", + Version: "1.2.3-r1", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), // SPDX expression is not set + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:musl:musl:1.2.3-r1:*:*:*:*:*:*:*", ), @@ -189,14 +201,15 @@ func Test_parseSBOM(t *testing.T) { Name: "musl-utils", Version: "1.2.3-r1", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("MIT"), pkg.NewLicense("BSD"), pkg.NewLicense("GPL2+"), // SPDX expression is not set ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/musl-utils@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/musl-utils@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:musl-utils:musl-utils:1.2.3-r1:*:*:*:*:*:*:*", "cpe:2.3:a:musl-utils:musl_utils:1.2.3-r1:*:*:*:*:*:*:*", @@ -210,12 +223,13 @@ func Test_parseSBOM(t *testing.T) { Name: "scanelf", Version: "1.3.4-r0", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/scanelf@1.3.4-r0?arch=x86_64&upstream=pax-utils&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/scanelf@1.3.4-r0?arch=x86_64&upstream=pax-utils&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:scanelf:scanelf:1.3.4-r0:*:*:*:*:*:*:*", ), @@ -224,12 +238,13 @@ func Test_parseSBOM(t *testing.T) { Name: "ssl_client", Version: "1.35.0-r17", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("GPL-2.0-only"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:ssl-client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*", "cpe:2.3:a:ssl-client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*", @@ -243,48 +258,42 @@ func Test_parseSBOM(t *testing.T) { Name: "zlib", Version: "1.2.12-r3", Type: "apk", - Locations: file.NewLocationSet(file.NewLocation("sbom.syft.json")), + Locations: sbomLocations, Licenses: pkg.NewLicenseSet( pkg.NewLicense("Zlib"), ), - FoundBy: "sbom-cataloger", - PURL: "pkg:apk/alpine/zlib@1.2.12-r3?arch=x86_64&upstream=zlib&distro=alpine-3.16.3", + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/zlib@1.2.12-r3?arch=x86_64&upstream=zlib&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:zlib:zlib:1.2.12-r3:*:*:*:*:*:*:*", ), }, } - apkgdbLocation := file.NewLocationSet(file.Location{ - LocationData: file.LocationData{ - Coordinates: file.Coordinates{ - RealPath: "/lib/apk/db/installed", - FileSystemID: "sha256:e5e13b0c77cbb769548077189c3da2f0a764ceca06af49d8d558e759f5c232bd", - }, - }, - }) - libSSL := pkg.Package{ - Name: "libssl1.1", - Version: "1.1.1s-r0", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Name: "libssl1.1", + Version: "1.1.1s-r0", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("OpenSSL")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/libssl1.1@1.1.1s-r0?arch=x86_64&upstream=openssl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:libssl1.1:libssl1.1:1.1.1s-r0:*:*:*:*:*:*:*", ), } sslClient := pkg.Package{ - Name: "ssl_client", - Version: "1.35.0-r17", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Name: "ssl_client", + Version: "1.35.0-r17", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/ssl_client@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:ssl-client:ssl-client:1.35.0-r17:*:*:*:*:*:*:*", "cpe:2.3:a:ssl-client:ssl_client:1.35.0-r17:*:*:*:*:*:*:*", @@ -296,13 +305,14 @@ func Test_parseSBOM(t *testing.T) { } baseLayout := pkg.Package{ - Name: "alpine-baselayout", - Version: "3.2.0-r23", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Name: "alpine-baselayout", + Version: "3.2.0-r23", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/alpine-baselayout@3.2.0-r23?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r23:*:*:*:*:*:*:*", "cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r23:*:*:*:*:*:*:*", @@ -314,26 +324,28 @@ func Test_parseSBOM(t *testing.T) { } busybox := pkg.Package{ - Name: "busybox", - Version: "1.35.0-r17", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Name: "busybox", + Version: "1.35.0-r17", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("GPL-2.0-only")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/busybox@1.35.0-r17?arch=x86_64&upstream=busybox&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:busybox:busybox:1.35.0-r17:*:*:*:*:*:*:*", ), } musl := pkg.Package{ - Name: "musl", - Version: "1.2.3-r1", - Type: "apk", - Locations: apkgdbLocation, - Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), - FoundBy: "apkdb-cataloger", - PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Name: "musl", + Version: "1.2.3-r1", + Type: "apk", + Locations: sbomLocations, + Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")), + FoundBy: "sbom-cataloger", + PURL: "pkg:apk/alpine/musl@1.2.3-r1?arch=x86_64&upstream=musl&distro=alpine-3.16.3", + Dependencies: pkg.UnknownDependencyCompleteness, CPEs: mustCPEs( "cpe:2.3:a:musl:musl:1.2.3-r1:*:*:*:*:*:*:*", ), diff --git a/syft/pkg/cataloger/swift/package.go b/syft/pkg/cataloger/swift/package.go index c4370f5dc533..587958d5cf36 100644 --- a/syft/pkg/cataloger/swift/package.go +++ b/syft/pkg/cataloger/swift/package.go @@ -16,6 +16,8 @@ func newSwiftPackageManagerPackage(name, version, sourceURL, revision string, lo Locations: file.NewLocationSet(locations...), Type: pkg.SwiftPkg, Language: pkg.Swift, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: revision, }, @@ -34,6 +36,8 @@ func newCocoaPodsPackage(name, version, hash string, locations ...file.Location) Locations: file.NewLocationSet(locations...), Type: pkg.CocoapodsPkg, Language: pkg.Swift, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: hash, }, diff --git a/syft/pkg/cataloger/swift/parse_package_resolved_test.go b/syft/pkg/cataloger/swift/parse_package_resolved_test.go index bf16d7542e14..f6badb3d3c2c 100644 --- a/syft/pkg/cataloger/swift/parse_package_resolved_test.go +++ b/syft/pkg/cataloger/swift/parse_package_resolved_test.go @@ -13,61 +13,68 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) +//Coffee1194 + func TestParsePackageResolved(t *testing.T) { fixture := "test-fixtures/Package.resolved" locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "swift-algorithms", - Version: "1.0.0", - PURL: "pkg:swift/github.com/apple/swift-algorithms.git/swift-algorithms@1.0.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-algorithms", + Version: "1.0.0", + PURL: "pkg:swift/github.com/apple/swift-algorithms.git/swift-algorithms@1.0.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "b14b7f4c528c942f121c8b860b9410b2bf57825e", }, }, { - Name: "swift-async-algorithms", - Version: "0.1.0", - PURL: "pkg:swift/github.com/apple/swift-async-algorithms.git/swift-async-algorithms@0.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-async-algorithms", + Version: "0.1.0", + PURL: "pkg:swift/github.com/apple/swift-async-algorithms.git/swift-async-algorithms@0.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "9cfed92b026c524674ed869a4ff2dcfdeedf8a2a", }, }, { - Name: "swift-atomics", - Version: "1.1.0", - PURL: "pkg:swift/github.com/apple/swift-atomics.git/swift-atomics@1.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-atomics", + Version: "1.1.0", + PURL: "pkg:swift/github.com/apple/swift-atomics.git/swift-atomics@1.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "6c89474e62719ddcc1e9614989fff2f68208fe10", }, }, { - Name: "swift-collections", - Version: "1.0.4", - PURL: "pkg:swift/github.com/apple/swift-collections.git/swift-collections@1.0.4", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-collections", + Version: "1.0.4", + PURL: "pkg:swift/github.com/apple/swift-collections.git/swift-collections@1.0.4", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "937e904258d22af6e447a0b72c0bc67583ef64a2", }, }, { - Name: "swift-numerics", - Version: "1.0.2", - PURL: "pkg:swift/github.com/apple/swift-numerics/swift-numerics@1.0.2", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-numerics", + Version: "1.0.2", + PURL: "pkg:swift/github.com/apple/swift-numerics/swift-numerics@1.0.2", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "0a5bc04095a675662cf24757cc0640aa2204253b", }, @@ -85,23 +92,25 @@ func TestParsePackageResolvedV3(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "swift-mmio", - Version: "", - PURL: "pkg:swift/github.com/apple/swift-mmio/swift-mmio", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-mmio", + Version: "", + PURL: "pkg:swift/github.com/apple/swift-mmio/swift-mmio", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "80c109b87511041338a4d8d88064088c8dfc079b", }, }, { - Name: "swift-syntax", - Version: "509.1.1", - PURL: "pkg:swift/github.com/apple/swift-syntax.git/swift-syntax@509.1.1", - Locations: locations, - Language: pkg.Swift, - Type: pkg.SwiftPkg, + Name: "swift-syntax", + Version: "509.1.1", + PURL: "pkg:swift/github.com/apple/swift-syntax.git/swift-syntax@509.1.1", + Locations: locations, + Language: pkg.Swift, + Type: pkg.SwiftPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiftPackageManagerResolvedEntry{ Revision: "64889f0c732f210a935a0ad7cda38f77f876262d", }, diff --git a/syft/pkg/cataloger/swift/parse_podfile_lock_test.go b/syft/pkg/cataloger/swift/parse_podfile_lock_test.go index 0abdd0d7cecd..9beb9ad52051 100644 --- a/syft/pkg/cataloger/swift/parse_podfile_lock_test.go +++ b/syft/pkg/cataloger/swift/parse_podfile_lock_test.go @@ -14,254 +14,277 @@ func TestParsePodfileLock(t *testing.T) { locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "GlossButtonNode", - Version: "3.1.2", - PURL: "pkg:cocoapods/GlossButtonNode@3.1.2", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "GlossButtonNode", + Version: "3.1.2", + PURL: "pkg:cocoapods/GlossButtonNode@3.1.2", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "4ea1197a744f2fb5fb875fe31caf17ded4762e8f", }, }, { - Name: "PINCache", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINCache@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINCache", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINCache@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7a8fc1a691173d21dbddbf86cd515de6efa55086", }, }, { - Name: "PINCache/Arc-exception-safe", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINCache/Arc-exception-safe@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINCache/Arc-exception-safe", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINCache/Arc-exception-safe@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7a8fc1a691173d21dbddbf86cd515de6efa55086", }, }, { - Name: "PINCache/Core", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINCache/Core@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINCache/Core", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINCache/Core@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7a8fc1a691173d21dbddbf86cd515de6efa55086", }, }, { - Name: "PINOperation", - Version: "1.2.1", - PURL: "pkg:cocoapods/PINOperation@1.2.1", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINOperation", + Version: "1.2.1", + PURL: "pkg:cocoapods/PINOperation@1.2.1", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "00c935935f1e8cf0d1e2d6b542e75b88fc3e5e20", }, }, { - Name: "PINRemoteImage/Core", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINRemoteImage/Core@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINRemoteImage/Core", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINRemoteImage/Core@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "f1295b29f8c5e640e25335a1b2bd9d805171bd01", }, }, { - Name: "PINRemoteImage/iOS", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINRemoteImage/iOS@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINRemoteImage/iOS", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINRemoteImage/iOS@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "f1295b29f8c5e640e25335a1b2bd9d805171bd01", }, }, { - Name: "PINRemoteImage/PINCache", - Version: "3.0.3", - PURL: "pkg:cocoapods/PINRemoteImage/PINCache@3.0.3", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "PINRemoteImage/PINCache", + Version: "3.0.3", + PURL: "pkg:cocoapods/PINRemoteImage/PINCache@3.0.3", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "f1295b29f8c5e640e25335a1b2bd9d805171bd01", }, }, { - Name: "Reveal-SDK", - Version: "33", - PURL: "pkg:cocoapods/Reveal-SDK@33", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Reveal-SDK", + Version: "33", + PURL: "pkg:cocoapods/Reveal-SDK@33", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "effba1c940b8337195563c425a6b5862ec875caa", }, }, { - Name: "SwiftGen", - Version: "6.5.1", - PURL: "pkg:cocoapods/SwiftGen@6.5.1", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "SwiftGen", + Version: "6.5.1", + PURL: "pkg:cocoapods/SwiftGen@6.5.1", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "a6d22010845f08fe18fbdf3a07a8e380fd22e0ea", }, }, { - Name: "Texture", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/AssetsLibrary", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/AssetsLibrary@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/AssetsLibrary", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/AssetsLibrary@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/Core", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/Core@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/Core", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/Core@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/MapKit", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/MapKit@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/MapKit", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/MapKit@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/Photos", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/Photos@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/Photos", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/Photos@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/PINRemoteImage", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/PINRemoteImage@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/PINRemoteImage", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/PINRemoteImage@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "Texture/Video", - Version: "3.1.0", - PURL: "pkg:cocoapods/Texture/Video@3.1.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "Texture/Video", + Version: "3.1.0", + PURL: "pkg:cocoapods/Texture/Video@3.1.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "2e8ab2519452515f7f5a520f5a8f7e0a413abfa3", }, }, { - Name: "TextureSwiftSupport", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/Components", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/Components@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/Components", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/Components@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/Experiments", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/Experiments@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/Experiments", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/Experiments@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/Extensions", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/Extensions@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/Extensions", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/Extensions@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TextureSwiftSupport/LayoutSpecBuilders", - Version: "3.13.0", - PURL: "pkg:cocoapods/TextureSwiftSupport/LayoutSpecBuilders@3.13.0", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TextureSwiftSupport/LayoutSpecBuilders", + Version: "3.13.0", + PURL: "pkg:cocoapods/TextureSwiftSupport/LayoutSpecBuilders@3.13.0", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "c515c7927fab92d0d9485f49b885b8c5de34fbfb", }, }, { - Name: "TinyConstraints", - Version: "4.0.2", - PURL: "pkg:cocoapods/TinyConstraints@4.0.2", - Locations: locations, - Language: pkg.Swift, - Type: pkg.CocoapodsPkg, + Name: "TinyConstraints", + Version: "4.0.2", + PURL: "pkg:cocoapods/TinyConstraints@4.0.2", + Locations: locations, + Language: pkg.Swift, + Type: pkg.CocoapodsPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.CocoaPodfileLockEntry{ Checksum: "7b7ccc0c485bb3bb47082138ff28bc33cd49897f", }, diff --git a/syft/pkg/cataloger/swipl/package.go b/syft/pkg/cataloger/swipl/package.go index 6421ede70b62..770bb171970f 100644 --- a/syft/pkg/cataloger/swipl/package.go +++ b/syft/pkg/cataloger/swipl/package.go @@ -14,7 +14,9 @@ func newSwiplPackPackage(m pkg.SwiplPackEntry, locations ...file.Location) pkg.P Locations: file.NewLocationSet(locations...), Type: pkg.SwiplPackPkg, Language: pkg.Swipl, - Metadata: m, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: m, } p.SetID() diff --git a/syft/pkg/cataloger/swipl/parse_pack_test.go b/syft/pkg/cataloger/swipl/parse_pack_test.go index 28feb7690441..02b4fdc7f2cb 100644 --- a/syft/pkg/cataloger/swipl/parse_pack_test.go +++ b/syft/pkg/cataloger/swipl/parse_pack_test.go @@ -9,17 +9,18 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) -func TestParsePackPackage(t *testing.T) { +func xTestParsePackPackage(t *testing.T) { fixture := "test-fixtures/pack.pl" locations := file.NewLocationSet(file.NewLocation(fixture)) expectedPkgs := []pkg.Package{ { - Name: "hdt", - Version: "0.5.2", - PURL: "pkg:swiplpack/hdt@0.5.2", - Locations: locations, - Language: pkg.Swipl, - Type: pkg.SwiplPackPkg, + Name: "hdt", + Version: "0.5.2", + PURL: "pkg:swiplpack/hdt@0.5.2", + Locations: locations, + Language: pkg.Swipl, + Type: pkg.SwiplPackPkg, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.SwiplPackEntry{ Name: "hdt", Version: "0.5.2", diff --git a/syft/pkg/cataloger/wordpress/package.go b/syft/pkg/cataloger/wordpress/package.go index 596ccfb5a13c..6df1c0ada236 100644 --- a/syft/pkg/cataloger/wordpress/package.go +++ b/syft/pkg/cataloger/wordpress/package.go @@ -18,7 +18,9 @@ func newWordpressPluginPackage(name, version string, m pluginData, location file Locations: file.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), Language: pkg.PHP, Type: pkg.WordpressPluginPkg, - Metadata: meta, + // no attempt is made by the parser function to resolve dependencies + Dependencies: pkg.UnknownDependencyCompleteness, + Metadata: meta, } if len(m.Licenses) > 0 { diff --git a/syft/pkg/cataloger/wordpress/parse_plugin_test.go b/syft/pkg/cataloger/wordpress/parse_plugin_test.go index a9e10f289d21..904685398cb2 100644 --- a/syft/pkg/cataloger/wordpress/parse_plugin_test.go +++ b/syft/pkg/cataloger/wordpress/parse_plugin_test.go @@ -22,7 +22,8 @@ func TestParseWordpressPluginFiles(t *testing.T) { Licenses: pkg.NewLicenseSet( pkg.NewLicenseFromLocations("GPLv2"), ), - Language: pkg.PHP, + Language: pkg.PHP, + Dependencies: pkg.UnknownDependencyCompleteness, Metadata: pkg.WordpressPluginEntry{ PluginInstallDirectory: "akismet", Author: "Automattic - Anti-spam Team", diff --git a/syft/pkg/dependencies.go b/syft/pkg/dependencies.go new file mode 100644 index 000000000000..66b598e5b3c4 --- /dev/null +++ b/syft/pkg/dependencies.go @@ -0,0 +1,49 @@ +package pkg + +import "strings" + +// DependencyCompleteness describes the quality of the current package and if the SBOM contains relationships to +// a complete set of dependencies. We are only concerned with describing the completeness of the dependencies +// relative to the direct dependencies of the package, not the completeness of the entire graph beyond direct +// dependencies. Completeness should apply to packages required by the current package that are non-test and +// non-development dependencies in nature. There is no distinction about build-time vs runtime dependencies. +// Overall completeness is a function of node connectivity within the SBOM graph, it is not sufficient that all +// dependencies exist in the graph to be considered complete, they must have explicit relationships that denote +// each dependency. +type DependencyCompleteness string + +const ( + // UnknownDependencyCompleteness indicates that the completeness of the dependencies cannot be considered + // positively complete or incomplete. This should be used when the dependency resolution mechanism is not + // well understood, the set of dependencies is unknowable, or no attempt has been made to resolve + // dependencies (no assertion). + UnknownDependencyCompleteness DependencyCompleteness = "unknown" + + // CompleteDependencies indicates that the package has all of its direct dependencies resolved and related to + // this package. Note that any indirect (transitive) dependencies must not be directly linked to this package. + CompleteDependencies DependencyCompleteness = "complete" + + // CompleteWithIndirectDependencies is a superset of complete. It indicates that the package has all of its direct dependencies + // resolved as well as some or all of indirect dependencies. What is notable about this is that direct and + // indirect dependencies are linked directly to this package and are not separable (you cannot distinguish between + // a direct and indirect dependency from the perspective of this package). + CompleteWithIndirectDependencies DependencyCompleteness = "complete-with-indirect" + + // IncompleteDependencies indicates that the package is known to not have all of its direct dependencies listed. + // This is reserved for cases where we know there are a non-zero number of dependencies for a package, but we + // are not listing them intentionally or because we are unable to resolve them. + IncompleteDependencies DependencyCompleteness = "incomplete" +) + +func ParseDependencyCompleteness(value string) DependencyCompleteness { + switch strings.ToLower(strings.TrimSpace(value)) { + case string(CompleteDependencies): + return CompleteDependencies + case string(CompleteWithIndirectDependencies): + return CompleteWithIndirectDependencies + case string(IncompleteDependencies): + return IncompleteDependencies + default: + return UnknownDependencyCompleteness + } +} diff --git a/syft/pkg/package.go b/syft/pkg/package.go index 8ee8d969fae7..c162950286b1 100644 --- a/syft/pkg/package.go +++ b/syft/pkg/package.go @@ -17,17 +17,18 @@ import ( // Package represents an application or library that has been bundled into a distributable format. // TODO: if we ignore FoundBy for ID generation should we merge the field to show it was found in two places? type Package struct { - id artifact.ID `hash:"ignore"` - Name string // the package name - Version string // the version of the package - FoundBy string `hash:"ignore" cyclonedx:"foundBy"` // the specific cataloger that discovered this package - Locations file.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package) - Licenses LicenseSet // licenses discovered with the package metadata - Language Language `hash:"ignore" cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc) - Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc) - CPEs []cpe.CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields) - PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec) - Metadata interface{} // additional data found while parsing the package source + id artifact.ID `hash:"ignore"` + Name string // the package name + Version string // the version of the package + FoundBy string `hash:"ignore" cyclonedx:"foundBy"` // the specific cataloger that discovered this package + Locations file.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package) + Licenses LicenseSet // licenses discovered with the package metadata + Language Language `hash:"ignore" cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc) + Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc) + CPEs []cpe.CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields) + PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec) + Dependencies DependencyCompleteness `hash:"ignore"` // the completeness of the dependency information for this package + Metadata interface{} // additional data found while parsing the package source } func (p *Package) OverrideID(id artifact.ID) {