diff --git a/docs/docs/coverage/language/index.md b/docs/docs/coverage/language/index.md index b9461b4e013b..df8203f93691 100644 --- a/docs/docs/coverage/language/index.md +++ b/docs/docs/coverage/language/index.md @@ -26,7 +26,8 @@ On the other hand, when the target is a post-build artifact, like a container im | | egg package[^1] | ✅ | ✅ | - | - | | | wheel package[^2] | ✅ | ✅ | - | - | | | conda package[^3] | ✅ | ✅ | - | - | -| [PHP](php.md) | composer.lock | ✅ | ✅ | ✅ | ✅ | +| [PHP](php.md) | composer.lock | - | - | ✅ | ✅ | +| | installed.json | ✅ | ✅ | - | - | | [Node.js](nodejs.md) | package-lock.json | - | - | ✅ | ✅ | | | yarn.lock | - | - | ✅ | ✅ | | | pnpm-lock.yaml | - | - | ✅ | ✅ | diff --git a/docs/docs/coverage/language/php.md b/docs/docs/coverage/language/php.md index 6fa138c35290..9fe38bf4990d 100644 --- a/docs/docs/coverage/language/php.md +++ b/docs/docs/coverage/language/php.md @@ -4,23 +4,27 @@ Trivy supports [Composer][composer], which is a tool for dependency management i The following scanners are supported. -| Package manager | SBOM | Vulnerability | License | -| --------------- | :---: | :-----------: | :-----: | -| Composer | ✓ | ✓ | ✓ | +| Package manager | SBOM | Vulnerability | License | +|-----------------|:----:|:-------------:|:-------:| +| Composer | ✓ | ✓ | ✓ | The following table provides an outline of the features Trivy offers. -| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position | -|-----------------|---------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:| -| Composer | composer.lock | ✓ | Excluded | ✓ | ✓ | +| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position | +|-----------------|----------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:| +| Composer | composer.lock | ✓ | Excluded | ✓ | ✓ | +| Composer | installed.json | ✓ | Excluded | - | ✓ | -## Composer +## composer.lock In order to detect dependencies, Trivy searches for `composer.lock`. Trivy also supports dependency trees; however, to display an accurate tree, it needs to know whether each package is a direct dependency of the project. Since this information is not included in `composer.lock`, Trivy parses `composer.json`, which should be located next to `composer.lock`. If you want to see the dependency tree, please ensure that `composer.json` is present. +## installed.json +Trivy also supports dependency detection for `installed.json` files. By default, you can find this file at `path_to_app/vendor/composer/installed.json`. + [composer]: https://getcomposer.org/ [dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies \ No newline at end of file diff --git a/integration/repo_test.go b/integration/repo_test.go index 49e342d1a91a..e07b48b950b7 100644 --- a/integration/repo_test.go +++ b/integration/repo_test.go @@ -250,6 +250,16 @@ func TestRepository(t *testing.T) { }, golden: "testdata/test-repo.json.golden", }, + { + name: "installed.json", + args: args{ + command: "rootfs", + scanner: types.VulnerabilityScanner, + listAllPkgs: true, + input: "testdata/fixtures/repo/composer-vendor", + }, + golden: "testdata/composer.vendor.json.golden", + }, { name: "dockerfile", args: args{ diff --git a/integration/testdata/composer.vendor.json.golden b/integration/testdata/composer.vendor.json.golden new file mode 100644 index 000000000000..ebb1f65a0824 --- /dev/null +++ b/integration/testdata/composer.vendor.json.golden @@ -0,0 +1,131 @@ +{ + "SchemaVersion": 2, + "CreatedAt": "2021-08-25T12:20:30.000000005Z", + "ArtifactName": "testdata/fixtures/repo/composer-vendor", + "ArtifactType": "filesystem", + "Metadata": { + "ImageConfig": { + "architecture": "", + "created": "0001-01-01T00:00:00Z", + "os": "", + "rootfs": { + "type": "", + "diff_ids": null + }, + "config": {} + } + }, + "Results": [ + { + "Target": "installed.json", + "Class": "lang-pkgs", + "Type": "composer-vendor", + "Packages": [ + { + "ID": "guzzlehttp/psr7@1.8.3", + "Name": "guzzlehttp/psr7", + "Identifier": { + "PURL": "pkg:composer/guzzlehttp/psr7@1.8.3", + "UID": "25fca97fe23aa7b1" + }, + "Version": "1.8.3", + "Licenses": [ + "MIT" + ], + "DependsOn": [ + "psr/http-message@1.1", + "ralouphie/getallheaders@3.0.3" + ], + "Layer": {}, + "Locations": [ + { + "StartLine": 3, + "EndLine": 115 + } + ] + }, + { + "ID": "psr/http-message@1.1", + "Name": "psr/http-message", + "Identifier": { + "PURL": "pkg:composer/psr/http-message@1.1", + "UID": "299d8ff4461e894" + }, + "Version": "1.1", + "Licenses": [ + "MIT" + ], + "Layer": {}, + "Locations": [ + { + "StartLine": 116, + "EndLine": 171 + } + ] + }, + { + "ID": "ralouphie/getallheaders@3.0.3", + "Name": "ralouphie/getallheaders", + "Identifier": { + "PURL": "pkg:composer/ralouphie/getallheaders@3.0.3", + "UID": "c383e94d979a209c" + }, + "Version": "3.0.3", + "Licenses": [ + "MIT" + ], + "Layer": {}, + "Locations": [ + { + "StartLine": 172, + "EndLine": 218 + } + ] + } + ], + "Vulnerabilities": [ + { + "VulnerabilityID": "CVE-2022-24775", + "PkgID": "guzzlehttp/psr7@1.8.3", + "PkgName": "guzzlehttp/psr7", + "PkgIdentifier": { + "PURL": "pkg:composer/guzzlehttp/psr7@1.8.3", + "UID": "25fca97fe23aa7b1" + }, + "InstalledVersion": "1.8.3", + "FixedVersion": "1.8.4", + "Status": "fixed", + "Layer": {}, + "SeveritySource": "ghsa", + "PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-24775", + "DataSource": { + "ID": "ghsa", + "Name": "GitHub Security Advisory Composer", + "URL": "https://github.com/advisories?query=type%%3Areviewed+ecosystem%%3Acomposer" + }, + "Title": "Improper Input Validation in guzzlehttp/psr7", + "Description": "### Impact\nIn proper header parsing. An attacker could sneak in a new line character and pass untrusted values. \n\n### Patches\nThe issue is patched in 1.8.4 and 2.1.1.\n\n### Workarounds\nThere are no known workarounds.\n", + "Severity": "HIGH", + "CweIDs": [ + "CWE-20" + ], + "VendorSeverity": { + "ghsa": 3 + }, + "CVSS": { + "ghsa": { + "V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N", + "V3Score": 7.5 + } + }, + "References": [ + "https://github.com/guzzle/psr7/security/advisories/GHSA-q7rv-6hp3-vh96", + "https://nvd.nist.gov/vuln/detail/CVE-2022-24775" + ], + "PublishedDate": "2022-03-25T19:26:33Z", + "LastModifiedDate": "2022-06-14T20:02:29Z" + } + ] + } + ] +} diff --git a/integration/testdata/fixtures/repo/composer-vendor/installed.json b/integration/testdata/fixtures/repo/composer-vendor/installed.json new file mode 100644 index 000000000000..532876cd7ff5 --- /dev/null +++ b/integration/testdata/fixtures/repo/composer-vendor/installed.json @@ -0,0 +1,222 @@ +{ + "packages": [ + { + "name": "guzzlehttp/psr7", + "version": "1.8.3", + "version_normalized": "1.8.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85", + "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "time": "2021-10-05T13:56:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.8.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "install-path": "../guzzlehttp/psr7" + }, + { + "name": "psr/http-message", + "version": "1.1", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "time": "2023-04-04T09:50:52+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/1.1" + }, + "install-path": "../psr/http-message" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "version_normalized": "3.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "time": "2019-03-08T08:55:37+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "install-path": "../ralouphie/getallheaders" + } + ], + "dev": true, + "dev-package-names": [] +} diff --git a/pkg/detector/library/driver.go b/pkg/detector/library/driver.go index af91c30c786f..6990d3c7e84d 100644 --- a/pkg/detector/library/driver.go +++ b/pkg/detector/library/driver.go @@ -33,7 +33,7 @@ func NewDriver(libType ftypes.LangType) (Driver, bool) { case ftypes.RustBinary, ftypes.Cargo: ecosystem = vulnerability.Cargo comparer = compare.GenericComparer{} - case ftypes.Composer: + case ftypes.Composer, ftypes.ComposerVendor: ecosystem = vulnerability.Composer comparer = compare.GenericComparer{} case ftypes.GoBinary, ftypes.GoModule: diff --git a/pkg/fanal/analyzer/const.go b/pkg/fanal/analyzer/const.go index 82bf3bb12296..6e9d0332eb61 100644 --- a/pkg/fanal/analyzer/const.go +++ b/pkg/fanal/analyzer/const.go @@ -49,7 +49,8 @@ const ( TypeCargo Type = "cargo" // PHP - TypeComposer Type = "composer" + TypeComposer Type = "composer" + TypeComposerVendor Type = "composer-vendor" // Java TypeJar Type = "jar" @@ -218,6 +219,7 @@ var ( TypePubSpecLock, TypeMixLock, TypeCondaEnv, + TypeComposer, } // TypeIndividualPkgs has all analyzers for individual packages @@ -229,6 +231,7 @@ var ( TypeGoBinary, TypeJar, TypeRustBinary, + TypeComposerVendor, } // TypeConfigFiles has all config file analyzers diff --git a/pkg/fanal/analyzer/language/php/composer/composer.go b/pkg/fanal/analyzer/language/php/composer/composer.go index 1c0e14a1881a..15d2a2e8ec27 100644 --- a/pkg/fanal/analyzer/language/php/composer/composer.go +++ b/pkg/fanal/analyzer/language/php/composer/composer.go @@ -26,7 +26,7 @@ func init() { analyzer.RegisterPostAnalyzer(analyzer.TypeComposer, newComposerAnalyzer) } -const version = 1 +const composerAnalyzerVersion = 1 var requiredFiles = []string{ types.ComposerLock, @@ -96,7 +96,7 @@ func (a composerAnalyzer) Type() analyzer.Type { } func (a composerAnalyzer) Version() int { - return version + return composerAnalyzerVersion } func (a composerAnalyzer) parseComposerLock(path string, r io.Reader) (*types.Application, error) { diff --git a/pkg/fanal/analyzer/language/php/composer/composer_test.go b/pkg/fanal/analyzer/language/php/composer/composer_test.go index ea963d94dcf2..67ed0a0daa6e 100644 --- a/pkg/fanal/analyzer/language/php/composer/composer_test.go +++ b/pkg/fanal/analyzer/language/php/composer/composer_test.go @@ -20,7 +20,7 @@ func Test_composerAnalyzer_PostAnalyze(t *testing.T) { }{ { name: "happy path", - dir: "testdata/happy", + dir: "testdata/composer/happy", want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -63,7 +63,7 @@ func Test_composerAnalyzer_PostAnalyze(t *testing.T) { }, { name: "no composer.json", - dir: "testdata/no-composer-json", + dir: "testdata/composer/no-composer-json", want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -106,7 +106,7 @@ func Test_composerAnalyzer_PostAnalyze(t *testing.T) { }, { name: "wrong composer.json", - dir: "testdata/wrong-composer-json", + dir: "testdata/composer/wrong-composer-json", want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -149,7 +149,7 @@ func Test_composerAnalyzer_PostAnalyze(t *testing.T) { }, { name: "broken composer.lock", - dir: "testdata/sad", + dir: "testdata/composer/sad", want: &analyzer.AnalysisResult{}, }, } diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/composer-vendor/happy/installed.json b/pkg/fanal/analyzer/language/php/composer/testdata/composer-vendor/happy/installed.json new file mode 100644 index 000000000000..e44e60d9050a --- /dev/null +++ b/pkg/fanal/analyzer/language/php/composer/testdata/composer-vendor/happy/installed.json @@ -0,0 +1,131 @@ +{ + "packages": [ + { + "name": "pear/log", + "version": "1.13.3", + "version_normalized": "1.13.3.0", + "source": { + "type": "git", + "url": "https://github.com/pear/Log.git", + "reference": "21af0be11669194d72d88b5ee9d5f176dc75d9a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/Log/zipball/21af0be11669194d72d88b5ee9d5f176dc75d9a3", + "reference": "21af0be11669194d72d88b5ee9d5f176dc75d9a3", + "shasum": "" + }, + "require": { + "pear/pear_exception": "1.0.1 || 1.0.2", + "php": ">5.2" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "pear/db": "Install optionally via your project's composer.json" + }, + "time": "2021-05-04T23:51:30+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Log": "./" + }, + "exclude-from-classmap": [ + "/examples/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jon Parise", + "email": "jon@php.net", + "homepage": "http://www.indelible.org", + "role": "Developer" + } + ], + "description": "PEAR Logging Framework", + "homepage": "http://pear.github.io/Log/", + "keywords": [ + "log", + "logging" + ], + "support": { + "issues": "https://github.com/pear/Log/issues", + "source": "https://github.com/pear/Log" + }, + "install-path": "../pear/log" + }, + { + "name": "pear/pear_exception", + "version": "v1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/pear/PEAR_Exception.git", + "reference": "b14fbe2ddb0b9f94f5b24cf08783d599f776fff0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/b14fbe2ddb0b9f94f5b24cf08783d599f776fff0", + "reference": "b14fbe2ddb0b9f94f5b24cf08783d599f776fff0", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "<9" + }, + "time": "2021-03-21T15:43:46+00:00", + "type": "class", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "PEAR/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "." + ], + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Helgi Thormar", + "email": "dufuz@php.net" + }, + { + "name": "Greg Beaver", + "email": "cellog@php.net" + } + ], + "description": "The PEAR Exception base class.", + "homepage": "https://github.com/pear/PEAR_Exception", + "keywords": [ + "exception" + ], + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR_Exception", + "source": "https://github.com/pear/PEAR_Exception" + }, + "install-path": "../pear/pear_exception" + } + ], + "dev": true, + "dev-package-names": [] +} diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/sad/composer.lock b/pkg/fanal/analyzer/language/php/composer/testdata/composer-vendor/sad/installed.json similarity index 100% rename from pkg/fanal/analyzer/language/php/composer/testdata/sad/composer.lock rename to pkg/fanal/analyzer/language/php/composer/testdata/composer-vendor/sad/installed.json diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/happy/composer.json b/pkg/fanal/analyzer/language/php/composer/testdata/composer/happy/composer.json similarity index 100% rename from pkg/fanal/analyzer/language/php/composer/testdata/happy/composer.json rename to pkg/fanal/analyzer/language/php/composer/testdata/composer/happy/composer.json diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/happy/composer.lock b/pkg/fanal/analyzer/language/php/composer/testdata/composer/happy/composer.lock similarity index 100% rename from pkg/fanal/analyzer/language/php/composer/testdata/happy/composer.lock rename to pkg/fanal/analyzer/language/php/composer/testdata/composer/happy/composer.lock diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/no-composer-json/composer.lock b/pkg/fanal/analyzer/language/php/composer/testdata/composer/no-composer-json/composer.lock similarity index 100% rename from pkg/fanal/analyzer/language/php/composer/testdata/no-composer-json/composer.lock rename to pkg/fanal/analyzer/language/php/composer/testdata/composer/no-composer-json/composer.lock diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/wrong-composer-json/composer.json b/pkg/fanal/analyzer/language/php/composer/testdata/composer/sad/composer.lock similarity index 100% rename from pkg/fanal/analyzer/language/php/composer/testdata/wrong-composer-json/composer.json rename to pkg/fanal/analyzer/language/php/composer/testdata/composer/sad/composer.lock diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/composer/wrong-composer-json/composer.json b/pkg/fanal/analyzer/language/php/composer/testdata/composer/wrong-composer-json/composer.json new file mode 100644 index 000000000000..81750b96f9d8 --- /dev/null +++ b/pkg/fanal/analyzer/language/php/composer/testdata/composer/wrong-composer-json/composer.json @@ -0,0 +1 @@ +{ \ No newline at end of file diff --git a/pkg/fanal/analyzer/language/php/composer/testdata/wrong-composer-json/composer.lock b/pkg/fanal/analyzer/language/php/composer/testdata/composer/wrong-composer-json/composer.lock similarity index 100% rename from pkg/fanal/analyzer/language/php/composer/testdata/wrong-composer-json/composer.lock rename to pkg/fanal/analyzer/language/php/composer/testdata/composer/wrong-composer-json/composer.lock diff --git a/pkg/fanal/analyzer/language/php/composer/vendor.go b/pkg/fanal/analyzer/language/php/composer/vendor.go new file mode 100644 index 000000000000..423de2b7a352 --- /dev/null +++ b/pkg/fanal/analyzer/language/php/composer/vendor.go @@ -0,0 +1,39 @@ +package composer + +import ( + "context" + "os" + "path/filepath" + + "github.com/aquasecurity/trivy/pkg/dependency/parser/php/composer" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/analyzer/language" + "github.com/aquasecurity/trivy/pkg/fanal/types" +) + +func init() { + analyzer.RegisterAnalyzer(&composerVendorAnalyzer{}) +} + +const ( + composerInstalledAnalyzerVersion = 1 +) + +// composerVendorAnalyzer analyzes 'installed.json' +type composerVendorAnalyzer struct{} + +func (a composerVendorAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { + return language.Analyze(types.ComposerVendor, input.FilePath, input.Content, composer.NewParser()) +} + +func (a composerVendorAnalyzer) Required(filePath string, _ os.FileInfo) bool { + return filepath.Base(filePath) == types.ComposerInstalledJson +} + +func (a composerVendorAnalyzer) Type() analyzer.Type { + return analyzer.TypeComposerVendor +} + +func (a composerVendorAnalyzer) Version() int { + return composerInstalledAnalyzerVersion +} diff --git a/pkg/fanal/analyzer/language/php/composer/vendor_test.go b/pkg/fanal/analyzer/language/php/composer/vendor_test.go new file mode 100644 index 000000000000..887c5d404039 --- /dev/null +++ b/pkg/fanal/analyzer/language/php/composer/vendor_test.go @@ -0,0 +1,120 @@ +package composer + +import ( + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/aquasecurity/trivy/pkg/fanal/analyzer" + "github.com/aquasecurity/trivy/pkg/fanal/types" +) + +func Test_composerVendorAnalyzer_Analyze(t *testing.T) { + tests := []struct { + name string + inputFile string + want *analyzer.AnalysisResult + wantErr string + }{ + { + name: "happy path", + inputFile: "testdata/composer-vendor/happy/installed.json", + want: &analyzer.AnalysisResult{ + Applications: []types.Application{ + { + Type: types.ComposerVendor, + FilePath: "testdata/composer-vendor/happy/installed.json", + Packages: []types.Package{ + { + ID: "pear/log@1.13.3", + Name: "pear/log", + Version: "1.13.3", + Indirect: false, + Relationship: types.RelationshipUnknown, + Licenses: []string{"MIT"}, + Locations: []types.Location{ + { + StartLine: 3, + EndLine: 65, + }, + }, + DependsOn: []string{"pear/pear_exception@v1.0.2"}, + }, + { + ID: "pear/pear_exception@v1.0.2", + Name: "pear/pear_exception", + Version: "v1.0.2", + Indirect: false, + Relationship: types.RelationshipUnknown, + Licenses: []string{"BSD-2-Clause"}, + Locations: []types.Location{ + { + StartLine: 66, + EndLine: 127, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "sad path", + inputFile: "testdata/composer-vendor/sad/installed.json", + wantErr: "decode error", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, err := os.Open(tt.inputFile) + require.NoError(t, err) + defer func() { + err = f.Close() + require.NoError(t, err) + }() + + a := composerVendorAnalyzer{} + got, err := a.Analyze(nil, analyzer.AnalysisInput{ + FilePath: tt.inputFile, + Content: f, + }) + + if tt.wantErr != "" { + require.ErrorContains(t, err, tt.wantErr) + return + } + + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +} + +func Test_composerVendorAnalyzer_Required(t *testing.T) { + tests := []struct { + name string + filePath string + want bool + }{ + { + name: "happy path", + filePath: "app/vendor/composer/installed.json", + want: true, + }, + { + name: "sad path", + filePath: "composer.json", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := composerVendorAnalyzer{} + got := a.Required(tt.filePath, nil) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/fanal/artifact/image/image_test.go b/pkg/fanal/artifact/image/image_test.go index 6ce36846868a..cd7fea2df1e2 100644 --- a/pkg/fanal/artifact/image/image_test.go +++ b/pkg/fanal/artifact/image/image_test.go @@ -352,17 +352,17 @@ func TestArtifact_Inspect(t *testing.T) { missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{ Args: cache.ArtifactCacheMissingBlobsArgs{ ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313", - BlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + BlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, }, Returns: cache.ArtifactCacheMissingBlobsReturns{ MissingArtifact: true, - MissingBlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + MissingBlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, }, }, putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{ { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0", + BlobID: "sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -429,7 +429,7 @@ func TestArtifact_Inspect(t *testing.T) { Name: "../../test/testdata/alpine-311.tar.gz", Type: artifact.TypeContainerImage, ID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313", - BlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + BlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, ImageMetadata: artifact.ImageMetadata{ ID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72", DiffIDs: []string{ @@ -488,25 +488,25 @@ func TestArtifact_Inspect(t *testing.T) { Args: cache.ArtifactCacheMissingBlobsArgs{ ArtifactID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650", BlobIDs: []string{ - "sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000", - "sha256:f9e6a3065bb47f810916e90249076950a4b70785a27d3bcb90406d0ab342fa67", - "sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001", - "sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440", + "sha256:a3eb0f92862bc742ea1e7ee875dd5623568ee17213ae7d29f05960eb1135fa6d", + "sha256:05b96a707dab6e1fcd9543f0df6a0e4cdf5c7e26272d7f6bc7ed2e1cf23afa9f", + "sha256:677cd3a664e4923227de2c2571c40b9956d99e4775b2e11ce8aa207842123119", + "sha256:e870ba0421bc71c046819f809c8369e98f59a2cde34961fdd429a2102da33c0c", }, }, Returns: cache.ArtifactCacheMissingBlobsReturns{ MissingBlobIDs: []string{ - "sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000", - "sha256:f9e6a3065bb47f810916e90249076950a4b70785a27d3bcb90406d0ab342fa67", - "sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001", - "sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440", + "sha256:a3eb0f92862bc742ea1e7ee875dd5623568ee17213ae7d29f05960eb1135fa6d", + "sha256:05b96a707dab6e1fcd9543f0df6a0e4cdf5c7e26272d7f6bc7ed2e1cf23afa9f", + "sha256:677cd3a664e4923227de2c2571c40b9956d99e4775b2e11ce8aa207842123119", + "sha256:e870ba0421bc71c046819f809c8369e98f59a2cde34961fdd429a2102da33c0c", }, }, }, putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{ { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000", + BlobID: "sha256:a3eb0f92862bc742ea1e7ee875dd5623568ee17213ae7d29f05960eb1135fa6d", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -594,7 +594,7 @@ func TestArtifact_Inspect(t *testing.T) { }, { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:f9e6a3065bb47f810916e90249076950a4b70785a27d3bcb90406d0ab342fa67", + BlobID: "sha256:05b96a707dab6e1fcd9543f0df6a0e4cdf5c7e26272d7f6bc7ed2e1cf23afa9f", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -690,7 +690,7 @@ func TestArtifact_Inspect(t *testing.T) { }, { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001", + BlobID: "sha256:677cd3a664e4923227de2c2571c40b9956d99e4775b2e11ce8aa207842123119", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -898,7 +898,7 @@ func TestArtifact_Inspect(t *testing.T) { }, { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440", + BlobID: "sha256:e870ba0421bc71c046819f809c8369e98f59a2cde34961fdd429a2102da33c0c", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -1761,10 +1761,10 @@ func TestArtifact_Inspect(t *testing.T) { Type: artifact.TypeContainerImage, ID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650", BlobIDs: []string{ - "sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000", - "sha256:f9e6a3065bb47f810916e90249076950a4b70785a27d3bcb90406d0ab342fa67", - "sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001", - "sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440", + "sha256:a3eb0f92862bc742ea1e7ee875dd5623568ee17213ae7d29f05960eb1135fa6d", + "sha256:05b96a707dab6e1fcd9543f0df6a0e4cdf5c7e26272d7f6bc7ed2e1cf23afa9f", + "sha256:677cd3a664e4923227de2c2571c40b9956d99e4775b2e11ce8aa207842123119", + "sha256:e870ba0421bc71c046819f809c8369e98f59a2cde34961fdd429a2102da33c0c", }, ImageMetadata: artifact.ImageMetadata{ ID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4", @@ -1858,25 +1858,25 @@ func TestArtifact_Inspect(t *testing.T) { Args: cache.ArtifactCacheMissingBlobsArgs{ ArtifactID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650", BlobIDs: []string{ - "sha256:e1187118cdbe8893fc2fd4b345f813d195ee6aaeb4820d4576694199f8c10350", - "sha256:12c266a627dc4014c3ee96936058ba98209056f4ffe0081bb5fca7ff91592cdb", - "sha256:47adac0e28b12338e99dedbd7e8b0ef1f7aaa28e646f637ab2db8908b80704c8", - "sha256:dd1082b33b17401fdc31bcbf60eaaecb9ce29e23956c50db6f34b2cc6cfa13c8", + "sha256:f46989447d5a1357f6b2427b86ca2af827dd380dbd7fbf392d2abf9a5d457323", + "sha256:487a6fb0914825c8fb9f3a0662a608039bd5a8b6488d76b9de2eb1a684e908e1", + "sha256:a23b05a9c95939a0d30d6b4f6c25393473252bde47b2daa03258c27461367509", + "sha256:47226d3c41a3ffd99dacdbcd2b197a7394ee8948270710ee035181427f88dfab", }, }, Returns: cache.ArtifactCacheMissingBlobsReturns{ MissingBlobIDs: []string{ - "sha256:e1187118cdbe8893fc2fd4b345f813d195ee6aaeb4820d4576694199f8c10350", - "sha256:12c266a627dc4014c3ee96936058ba98209056f4ffe0081bb5fca7ff91592cdb", - "sha256:47adac0e28b12338e99dedbd7e8b0ef1f7aaa28e646f637ab2db8908b80704c8", - "sha256:dd1082b33b17401fdc31bcbf60eaaecb9ce29e23956c50db6f34b2cc6cfa13c8", + "sha256:f46989447d5a1357f6b2427b86ca2af827dd380dbd7fbf392d2abf9a5d457323", + "sha256:487a6fb0914825c8fb9f3a0662a608039bd5a8b6488d76b9de2eb1a684e908e1", + "sha256:a23b05a9c95939a0d30d6b4f6c25393473252bde47b2daa03258c27461367509", + "sha256:47226d3c41a3ffd99dacdbcd2b197a7394ee8948270710ee035181427f88dfab", }, }, }, putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{ { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:e1187118cdbe8893fc2fd4b345f813d195ee6aaeb4820d4576694199f8c10350", + BlobID: "sha256:f46989447d5a1357f6b2427b86ca2af827dd380dbd7fbf392d2abf9a5d457323", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -1887,7 +1887,7 @@ func TestArtifact_Inspect(t *testing.T) { }, { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:12c266a627dc4014c3ee96936058ba98209056f4ffe0081bb5fca7ff91592cdb", + BlobID: "sha256:487a6fb0914825c8fb9f3a0662a608039bd5a8b6488d76b9de2eb1a684e908e1", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -1898,7 +1898,7 @@ func TestArtifact_Inspect(t *testing.T) { }, { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:47adac0e28b12338e99dedbd7e8b0ef1f7aaa28e646f637ab2db8908b80704c8", + BlobID: "sha256:a23b05a9c95939a0d30d6b4f6c25393473252bde47b2daa03258c27461367509", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -1910,7 +1910,7 @@ func TestArtifact_Inspect(t *testing.T) { }, { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:dd1082b33b17401fdc31bcbf60eaaecb9ce29e23956c50db6f34b2cc6cfa13c8", + BlobID: "sha256:47226d3c41a3ffd99dacdbcd2b197a7394ee8948270710ee035181427f88dfab", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -1926,10 +1926,10 @@ func TestArtifact_Inspect(t *testing.T) { Type: artifact.TypeContainerImage, ID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650", BlobIDs: []string{ - "sha256:e1187118cdbe8893fc2fd4b345f813d195ee6aaeb4820d4576694199f8c10350", - "sha256:12c266a627dc4014c3ee96936058ba98209056f4ffe0081bb5fca7ff91592cdb", - "sha256:47adac0e28b12338e99dedbd7e8b0ef1f7aaa28e646f637ab2db8908b80704c8", - "sha256:dd1082b33b17401fdc31bcbf60eaaecb9ce29e23956c50db6f34b2cc6cfa13c8", + "sha256:f46989447d5a1357f6b2427b86ca2af827dd380dbd7fbf392d2abf9a5d457323", + "sha256:487a6fb0914825c8fb9f3a0662a608039bd5a8b6488d76b9de2eb1a684e908e1", + "sha256:a23b05a9c95939a0d30d6b4f6c25393473252bde47b2daa03258c27461367509", + "sha256:47226d3c41a3ffd99dacdbcd2b197a7394ee8948270710ee035181427f88dfab", }, ImageMetadata: artifact.ImageMetadata{ ID: "sha256:58701fd185bda36cab0557bb6438661831267aa4a9e0b54211c4d5317a48aff4", @@ -2012,7 +2012,7 @@ func TestArtifact_Inspect(t *testing.T) { missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{ Args: cache.ArtifactCacheMissingBlobsArgs{ ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313", - BlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + BlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, }, Returns: cache.ArtifactCacheMissingBlobsReturns{ Err: xerrors.New("MissingBlobs failed"), @@ -2026,16 +2026,16 @@ func TestArtifact_Inspect(t *testing.T) { missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{ Args: cache.ArtifactCacheMissingBlobsArgs{ ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313", - BlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + BlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, }, Returns: cache.ArtifactCacheMissingBlobsReturns{ - MissingBlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + MissingBlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, }, }, putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{ { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0", + BlobID: "sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", @@ -2095,18 +2095,18 @@ func TestArtifact_Inspect(t *testing.T) { Args: cache.ArtifactCacheMissingBlobsArgs{ ArtifactID: "sha256:33f9415ed2cd5a9cef5d5144333619745b9ec0f851f0684dd45fa79c6b26a650", BlobIDs: []string{ - "sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000", - "sha256:f9e6a3065bb47f810916e90249076950a4b70785a27d3bcb90406d0ab342fa67", - "sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001", - "sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440", + "sha256:a3eb0f92862bc742ea1e7ee875dd5623568ee17213ae7d29f05960eb1135fa6d", + "sha256:05b96a707dab6e1fcd9543f0df6a0e4cdf5c7e26272d7f6bc7ed2e1cf23afa9f", + "sha256:677cd3a664e4923227de2c2571c40b9956d99e4775b2e11ce8aa207842123119", + "sha256:e870ba0421bc71c046819f809c8369e98f59a2cde34961fdd429a2102da33c0c", }, }, Returns: cache.ArtifactCacheMissingBlobsReturns{ MissingBlobIDs: []string{ - "sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000", - "sha256:f9e6a3065bb47f810916e90249076950a4b70785a27d3bcb90406d0ab342fa67", - "sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001", - "sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440", + "sha256:a3eb0f92862bc742ea1e7ee875dd5623568ee17213ae7d29f05960eb1135fa6d", + "sha256:05b96a707dab6e1fcd9543f0df6a0e4cdf5c7e26272d7f6bc7ed2e1cf23afa9f", + "sha256:677cd3a664e4923227de2c2571c40b9956d99e4775b2e11ce8aa207842123119", + "sha256:e870ba0421bc71c046819f809c8369e98f59a2cde34961fdd429a2102da33c0c", }, }, }, @@ -2114,7 +2114,7 @@ func TestArtifact_Inspect(t *testing.T) { { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:dd0a4f4754bf4590327be34f4266f63c92184352afadb72e4c9b162f76224000", + BlobID: "sha256:a3eb0f92862bc742ea1e7ee875dd5623568ee17213ae7d29f05960eb1135fa6d", BlobInfoAnything: true, }, @@ -2125,7 +2125,7 @@ func TestArtifact_Inspect(t *testing.T) { { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:f9e6a3065bb47f810916e90249076950a4b70785a27d3bcb90406d0ab342fa67", + BlobID: "sha256:05b96a707dab6e1fcd9543f0df6a0e4cdf5c7e26272d7f6bc7ed2e1cf23afa9f", BlobInfoAnything: true, }, @@ -2136,7 +2136,7 @@ func TestArtifact_Inspect(t *testing.T) { { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:b6be0de11c6090f71dea119f43dd360335643420058e317baffb089f0dff4001", + BlobID: "sha256:677cd3a664e4923227de2c2571c40b9956d99e4775b2e11ce8aa207842123119", BlobInfoAnything: true, }, @@ -2147,7 +2147,7 @@ func TestArtifact_Inspect(t *testing.T) { { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:37c561c19b169f5f9832f4b0060bf74ebc8d1c9e01662ad4fa21c394da159440", + BlobID: "sha256:e870ba0421bc71c046819f809c8369e98f59a2cde34961fdd429a2102da33c0c", BlobInfoAnything: true, }, @@ -2164,17 +2164,17 @@ func TestArtifact_Inspect(t *testing.T) { missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{ Args: cache.ArtifactCacheMissingBlobsArgs{ ArtifactID: "sha256:c232b7d8ac8aa08aa767313d0b53084c4380d1c01a213a5971bdb039e6538313", - BlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + BlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, }, Returns: cache.ArtifactCacheMissingBlobsReturns{ MissingArtifact: true, - MissingBlobIDs: []string{"sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0"}, + MissingBlobIDs: []string{"sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638"}, }, }, putBlobExpectations: []cache.ArtifactCachePutBlobExpectation{ { Args: cache.ArtifactCachePutBlobArgs{ - BlobID: "sha256:1fd280c63e1416a2261e76454caa19a5b77c6bddedd48309c9687c4fe72b34c0", + BlobID: "sha256:d4e6142cda465c55c8adf5b6c3148f3417a2c5582a76f933836738206e01b638", BlobInfo: types.BlobInfo{ SchemaVersion: types.BlobJSONSchemaVersion, Digest: "", diff --git a/pkg/fanal/types/const.go b/pkg/fanal/types/const.go index 9ad8c1a2c57b..7253404c0be1 100644 --- a/pkg/fanal/types/const.go +++ b/pkg/fanal/types/const.go @@ -43,38 +43,39 @@ const ( // Programming language dependencies const ( - Bundler LangType = "bundler" - GemSpec LangType = "gemspec" - Cargo LangType = "cargo" - Composer LangType = "composer" - Npm LangType = "npm" - NuGet LangType = "nuget" - DotNetCore LangType = "dotnet-core" - PackagesProps LangType = "packages-props" - Pip LangType = "pip" - Pipenv LangType = "pipenv" - Poetry LangType = "poetry" - CondaPkg LangType = "conda-pkg" - CondaEnv LangType = "conda-environment" - PythonPkg LangType = "python-pkg" - NodePkg LangType = "node-pkg" - Yarn LangType = "yarn" - Pnpm LangType = "pnpm" - Jar LangType = "jar" - Pom LangType = "pom" - Gradle LangType = "gradle" - Sbt LangType = "sbt" - GoBinary LangType = "gobinary" - GoModule LangType = "gomod" - JavaScript LangType = "javascript" - RustBinary LangType = "rustbinary" - Conan LangType = "conan" - Cocoapods LangType = "cocoapods" - Swift LangType = "swift" - Pub LangType = "pub" - Hex LangType = "hex" - Bitnami LangType = "bitnami" - Julia LangType = "julia" + Bundler LangType = "bundler" + GemSpec LangType = "gemspec" + Cargo LangType = "cargo" + Composer LangType = "composer" + ComposerVendor LangType = "composer-vendor" + Npm LangType = "npm" + NuGet LangType = "nuget" + DotNetCore LangType = "dotnet-core" + PackagesProps LangType = "packages-props" + Pip LangType = "pip" + Pipenv LangType = "pipenv" + Poetry LangType = "poetry" + CondaPkg LangType = "conda-pkg" + CondaEnv LangType = "conda-environment" + PythonPkg LangType = "python-pkg" + NodePkg LangType = "node-pkg" + Yarn LangType = "yarn" + Pnpm LangType = "pnpm" + Jar LangType = "jar" + Pom LangType = "pom" + Gradle LangType = "gradle" + Sbt LangType = "sbt" + GoBinary LangType = "gobinary" + GoModule LangType = "gomod" + JavaScript LangType = "javascript" + RustBinary LangType = "rustbinary" + Conan LangType = "conan" + Cocoapods LangType = "cocoapods" + Swift LangType = "swift" + Pub LangType = "pub" + Hex LangType = "hex" + Bitnami LangType = "bitnami" + Julia LangType = "julia" K8sUpstream LangType = "kubernetes" EKS LangType = "eks" // Amazon Elastic Kubernetes Service @@ -122,8 +123,9 @@ const ( YarnLock = "yarn.lock" PnpmLock = "pnpm-lock.yaml" - ComposerLock = "composer.lock" - ComposerJson = "composer.json" + ComposerLock = "composer.lock" + ComposerJson = "composer.json" + ComposerInstalledJson = "installed.json" PyProject = "pyproject.toml" PipRequirements = "requirements.txt" diff --git a/pkg/purl/purl.go b/pkg/purl/purl.go index 1ccf39c8530a..12b27e6290e6 100644 --- a/pkg/purl/purl.go +++ b/pkg/purl/purl.go @@ -448,6 +448,8 @@ func purlType(t ftypes.TargetType) string { return packageurl.TypeGem case ftypes.NuGet, ftypes.DotNetCore, ftypes.PackagesProps: return packageurl.TypeNuget + case ftypes.Composer, ftypes.ComposerVendor: + return packageurl.TypeComposer case ftypes.CondaPkg, ftypes.CondaEnv: return packageurl.TypeConda case ftypes.PythonPkg, ftypes.Pip, ftypes.Pipenv, ftypes.Poetry: