From 0269a5bd7e13f051d16ba70ef4f716e0d28808fb Mon Sep 17 00:00:00 2001 From: Erik Varga Date: Fri, 20 Sep 2024 04:54:09 -0700 Subject: [PATCH] Add native support for php/composerlock extraction. PiperOrigin-RevId: 676800059 --- docs/supported_inventory_types.md | 2 +- .../language/php/composerlock/extractor.go | 134 +++++++++++ .../php/composerlock/extractor_test.go | 221 ++++++++++++++++++ .../php/composerlock/testdata/empty.json | 19 ++ .../php/composerlock/testdata/not-json.txt | 1 + .../testdata/one-package-dev.json | 51 ++++ .../composerlock/testdata/one-package.json | 51 ++++ .../testdata/two-packages-alt.json | 87 +++++++ .../composerlock/testdata/two-packages.json | 88 +++++++ extractor/filesystem/list/list.go | 6 +- 10 files changed, 658 insertions(+), 2 deletions(-) create mode 100644 extractor/filesystem/language/php/composerlock/extractor.go create mode 100644 extractor/filesystem/language/php/composerlock/extractor_test.go create mode 100644 extractor/filesystem/language/php/composerlock/testdata/empty.json create mode 100644 extractor/filesystem/language/php/composerlock/testdata/not-json.txt create mode 100644 extractor/filesystem/language/php/composerlock/testdata/one-package-dev.json create mode 100644 extractor/filesystem/language/php/composerlock/testdata/one-package.json create mode 100644 extractor/filesystem/language/php/composerlock/testdata/two-packages-alt.json create mode 100644 extractor/filesystem/language/php/composerlock/testdata/two-packages.json diff --git a/docs/supported_inventory_types.md b/docs/supported_inventory_types.md index 84819ee4..81d2e9a7 100644 --- a/docs/supported_inventory_types.md +++ b/docs/supported_inventory_types.md @@ -32,7 +32,7 @@ SCALIBR supports extracting software package information from a variety of OS an * Installed NPM packages (package.json) * Lockfiles: package-lock.json, yarn.lock (OSV), pnpm-lock.yaml * PHP: - * Composer (OSV) + * Composer * Python * Installed PyPI packages (global and venv) * Lockfiles: requirements.txt, poetry (OSV), Pipfile.lock (OSV) diff --git a/extractor/filesystem/language/php/composerlock/extractor.go b/extractor/filesystem/language/php/composerlock/extractor.go new file mode 100644 index 00000000..55a6e4ad --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/extractor.go @@ -0,0 +1,134 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package composerlock extracts composer.lock files. +package composerlock + +import ( + "context" + "encoding/json" + "fmt" + "io/fs" + "path/filepath" + + "github.com/google/osv-scalibr/extractor" + "github.com/google/osv-scalibr/extractor/filesystem" + "github.com/google/osv-scalibr/extractor/filesystem/osv" + "github.com/google/osv-scalibr/plugin" + "github.com/google/osv-scalibr/purl" +) + +type composerPackage struct { + Name string `json:"name"` + Version string `json:"version"` + Dist struct { + Reference string `json:"reference"` + } `json:"dist"` +} + +type composerLock struct { + Packages []composerPackage `json:"packages"` + PackagesDev []composerPackage `json:"packages-dev"` +} + +// ComposerEcosystem is the OSV ecosystem for packages described in composer.lock files. +const ComposerEcosystem string = "Packagist" + +// Extractor extracts composer.lock files. +type Extractor struct{} + +// Name of the extractor. +func (e Extractor) Name() string { return "php/composerlock" } + +// Version of the extractor. +func (e Extractor) Version() int { return 0 } + +// Requirements of the extractor. +func (e Extractor) Requirements() *plugin.Capabilities { + return &plugin.Capabilities{} +} + +// FileRequired returns true if the specified file matches composer.lock files. +func (e Extractor) FileRequired(path string, fileInfo fs.FileInfo) bool { + return filepath.Base(path) == "composer.lock" +} + +// Extract extracts packages from a composer.lock file passed through the scan input. +func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([]*extractor.Inventory, error) { + var parsedLockfile *composerLock + + err := json.NewDecoder(input.Reader).Decode(&parsedLockfile) + + if err != nil { + return []*extractor.Inventory{}, fmt.Errorf("could not extract from %s: %w", input.Path, err) + } + + packages := make( + []*extractor.Inventory, + 0, + // len cannot return negative numbers, but the types can't reflect that + uint64(len(parsedLockfile.Packages))+uint64(len(parsedLockfile.PackagesDev)), + ) + + for _, composerPackage := range parsedLockfile.Packages { + packages = append(packages, &extractor.Inventory{ + Name: composerPackage.Name, + Version: composerPackage.Version, + Locations: []string{input.Path}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: composerPackage.Dist.Reference, + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{}, + }, + }) + } + + for _, composerPackage := range parsedLockfile.PackagesDev { + packages = append(packages, &extractor.Inventory{ + Name: composerPackage.Name, + Version: composerPackage.Version, + Locations: []string{input.Path}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: composerPackage.Dist.Reference, + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{"dev"}, + }, + }) + } + + return packages, nil +} + +// ToPURL converts an inventory created by this extractor into a PURL. +func (e Extractor) ToPURL(i *extractor.Inventory) (*purl.PackageURL, error) { + return &purl.PackageURL{ + Type: purl.TypeComposer, + Name: i.Name, + Version: i.Version, + }, nil +} + +// ToCPEs is not applicable as this extractor does not infer CPEs from the Inventory. +func (e Extractor) ToCPEs(i *extractor.Inventory) ([]string, error) { + return []string{}, nil +} + +// Ecosystem returns the OSV Ecosystem of the software extracted by this extractor. +func (e Extractor) Ecosystem(i *extractor.Inventory) (string, error) { + return ComposerEcosystem, nil +} + +var _ filesystem.Extractor = Extractor{} diff --git a/extractor/filesystem/language/php/composerlock/extractor_test.go b/extractor/filesystem/language/php/composerlock/extractor_test.go new file mode 100644 index 00000000..5f7d7ede --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/extractor_test.go @@ -0,0 +1,221 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package composerlock_test + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/osv-scalibr/extractor" + "github.com/google/osv-scalibr/extractor/filesystem/language/php/composerlock" + "github.com/google/osv-scalibr/extractor/filesystem/osv" + "github.com/google/osv-scalibr/testing/extracttest" +) + +func TestExtractor_FileRequired(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + inputPath string + want bool + }{ + { + name: "empty name", + inputPath: "", + want: false, + }, + { + name: "composer.lock from root", + inputPath: "composer.lock", + want: true, + }, + { + name: "composer.lock from subpath", + inputPath: "path/to/my/composer.lock", + want: true, + }, + { + name: "composer.lock as a dir", + inputPath: "path/to/my/composer.lock/file", + want: false, + }, + { + name: "composer.lock with additional extension", + inputPath: "path/to/my/composer.lock.file", + want: false, + }, + { + name: "composer.lock as substring", + inputPath: "path.to.my.composer.lock", + want: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + e := composerlock.Extractor{} + got := e.FileRequired(tt.inputPath, nil) + if got != tt.want { + t.Errorf("FileRequired(%s, FileInfo) got = %v, want %v", tt.inputPath, got, tt.want) + } + }) + } +} + +func TestExtractor_Extract(t *testing.T) { + t.Parallel() + + tests := []extracttest.TestTableEntry{ + { + Name: "invalid json", + InputConfig: extracttest.ScanInputMockConfig{ + Path: "testdata/not-json.txt", + }, + WantInventory: []*extractor.Inventory{}, + WantErr: extracttest.ContainsErrStr{Str: "could not extract from"}, + }, + { + Name: "no packages", + InputConfig: extracttest.ScanInputMockConfig{ + Path: "testdata/empty.json", + }, + WantInventory: []*extractor.Inventory{}, + }, + { + Name: "one package", + InputConfig: extracttest.ScanInputMockConfig{ + Path: "testdata/one-package.json", + }, + WantInventory: []*extractor.Inventory{ + { + Name: "sentry/sdk", + Version: "2.0.4", + Locations: []string{"testdata/one-package.json"}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{}, + }, + }, + }, + }, + { + Name: "one package dev", + InputConfig: extracttest.ScanInputMockConfig{ + Path: "testdata/one-package-dev.json", + }, + WantInventory: []*extractor.Inventory{ + { + Name: "sentry/sdk", + Version: "2.0.4", + Locations: []string{"testdata/one-package-dev.json"}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{"dev"}, + }, + }, + }, + }, + { + Name: "two packages", + InputConfig: extracttest.ScanInputMockConfig{ + Path: "testdata/two-packages.json", + }, + WantInventory: []*extractor.Inventory{ + { + Name: "sentry/sdk", + Version: "2.0.4", + Locations: []string{"testdata/two-packages.json"}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{}, + }, + }, + { + Name: "theseer/tokenizer", + Version: "1.1.3", + Locations: []string{"testdata/two-packages.json"}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{"dev"}, + }, + }, + }, + }, + { + Name: "two packages alt", + InputConfig: extracttest.ScanInputMockConfig{ + Path: "testdata/two-packages-alt.json", + }, + WantInventory: []*extractor.Inventory{ + { + Name: "sentry/sdk", + Version: "2.0.4", + Locations: []string{"testdata/two-packages-alt.json"}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{}, + }, + }, + { + Name: "theseer/tokenizer", + Version: "1.1.3", + Locations: []string{"testdata/two-packages-alt.json"}, + SourceCode: &extractor.SourceCodeIdentifier{ + Commit: "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + }, + Metadata: osv.DepGroupMetadata{ + DepGroupVals: []string{}, + }, + }, + }, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.Name, func(t *testing.T) { + t.Parallel() + extr := composerlock.Extractor{} + + scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig) + defer extracttest.CloseTestScanInput(t, scanInput) + + got, err := extr.Extract(context.Background(), &scanInput) + + if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" { + t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) + return + } + + if diff := cmp.Diff(tt.WantInventory, got, cmpopts.SortSlices(extracttest.InventoryCmpLess)); diff != "" { + t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff) + } + }) + } +} diff --git a/extractor/filesystem/language/php/composerlock/testdata/empty.json b/extractor/filesystem/language/php/composerlock/testdata/empty.json new file mode 100644 index 00000000..ede983d2 --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/testdata/empty.json @@ -0,0 +1,19 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "439b16dd5df2e0730bd1cc4352654d09", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^7.1.3" + }, + "platform-dev": [] +} diff --git a/extractor/filesystem/language/php/composerlock/testdata/not-json.txt b/extractor/filesystem/language/php/composerlock/testdata/not-json.txt new file mode 100644 index 00000000..3ae3a213 --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/testdata/not-json.txt @@ -0,0 +1 @@ +this is not json! diff --git a/extractor/filesystem/language/php/composerlock/testdata/one-package-dev.json b/extractor/filesystem/language/php/composerlock/testdata/one-package-dev.json new file mode 100644 index 00000000..33d3c975 --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/testdata/one-package-dev.json @@ -0,0 +1,51 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "439b16dd5df2e0730bd1cc4352654d09", + "packages": [], + "packages-dev": [ + { + "name": "sentry/sdk", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/getsentry/sentry-php-sdk.git", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "shasum": "" + }, + "require": { + "http-interop/http-factory-guzzle": "^1.0", + "php-http/curl-client": "^1.0|^2.0", + "sentry/sentry": "^2.1.3" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Sentry", + "email": "accounts@sentry.io" + } + ], + "description": "This is a metapackage shipping sentry/sentry with a recommended http client.", + "time": "2019-09-09T19:54:44+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^7.1.3" + }, + "platform-dev": [] +} diff --git a/extractor/filesystem/language/php/composerlock/testdata/one-package.json b/extractor/filesystem/language/php/composerlock/testdata/one-package.json new file mode 100644 index 00000000..3cfadf73 --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/testdata/one-package.json @@ -0,0 +1,51 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "439b16dd5df2e0730bd1cc4352654d09", + "packages": [ + { + "name": "sentry/sdk", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/getsentry/sentry-php-sdk.git", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "shasum": "" + }, + "require": { + "http-interop/http-factory-guzzle": "^1.0", + "php-http/curl-client": "^1.0|^2.0", + "sentry/sentry": "^2.1.3" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Sentry", + "email": "accounts@sentry.io" + } + ], + "description": "This is a metapackage shipping sentry/sentry with a recommended http client.", + "time": "2019-09-09T19:54:44+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^7.1.3" + }, + "platform-dev": [] +} diff --git a/extractor/filesystem/language/php/composerlock/testdata/two-packages-alt.json b/extractor/filesystem/language/php/composerlock/testdata/two-packages-alt.json new file mode 100644 index 00000000..2a17e5e5 --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/testdata/two-packages-alt.json @@ -0,0 +1,87 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "439b16dd5df2e0730bd1cc4352654d09", + "packages": [ + { + "name": "sentry/sdk", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/getsentry/sentry-php-sdk.git", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "shasum": "" + }, + "require": { + "http-interop/http-factory-guzzle": "^1.0", + "php-http/curl-client": "^1.0|^2.0", + "sentry/sentry": "^2.1.3" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Sentry", + "email": "accounts@sentry.io" + } + ], + "description": "This is a metapackage shipping sentry/sentry with a recommended http client.", + "time": "2019-09-09T19:54:44+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-06-13T22:48:21+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^7.1.3" + }, + "platform-dev": [] +} diff --git a/extractor/filesystem/language/php/composerlock/testdata/two-packages.json b/extractor/filesystem/language/php/composerlock/testdata/two-packages.json new file mode 100644 index 00000000..de640fd4 --- /dev/null +++ b/extractor/filesystem/language/php/composerlock/testdata/two-packages.json @@ -0,0 +1,88 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "439b16dd5df2e0730bd1cc4352654d09", + "packages": [ + { + "name": "sentry/sdk", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/getsentry/sentry-php-sdk.git", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "reference": "4c115873c86ad5bd0ac6d962db70ca53bf8fb874", + "shasum": "" + }, + "require": { + "http-interop/http-factory-guzzle": "^1.0", + "php-http/curl-client": "^1.0|^2.0", + "sentry/sentry": "^2.1.3" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Sentry", + "email": "accounts@sentry.io" + } + ], + "description": "This is a metapackage shipping sentry/sentry with a recommended http client.", + "time": "2019-09-09T19:54:44+00:00" + } + ], + "packages-dev": [ + { + "name": "theseer/tokenizer", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-06-13T22:48:21+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^7.1.3" + }, + "platform-dev": [] +} diff --git a/extractor/filesystem/list/list.go b/extractor/filesystem/list/list.go index 4ff1c59a..60d4e6f1 100644 --- a/extractor/filesystem/list/list.go +++ b/extractor/filesystem/list/list.go @@ -34,6 +34,7 @@ import ( "github.com/google/osv-scalibr/extractor/filesystem/language/javascript/packagejson" "github.com/google/osv-scalibr/extractor/filesystem/language/javascript/packagelockjson" "github.com/google/osv-scalibr/extractor/filesystem/language/javascript/pnpmlock" + "github.com/google/osv-scalibr/extractor/filesystem/language/php/composerlock" "github.com/google/osv-scalibr/extractor/filesystem/language/python/requirements" "github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg" "github.com/google/osv-scalibr/extractor/filesystem/language/ruby/gemspec" @@ -71,6 +72,8 @@ var ( SBOM []filesystem.Extractor = []filesystem.Extractor{&cdx.Extractor{}, &spdx.Extractor{}} // Dotnet (.NET) extractors. Dotnet []filesystem.Extractor = []filesystem.Extractor{packageslockjson.New(packageslockjson.DefaultConfig())} + // PHP extractors. + PHP []filesystem.Extractor = []filesystem.Extractor{&composerlock.Extractor{}} // Containers extractors. Containers []filesystem.Extractor = []filesystem.Extractor{containerd.New(containerd.DefaultConfig())} @@ -100,6 +103,7 @@ var ( Javascript, Python, Go, + PHP, Ruby, Dotnet, SBOM, @@ -117,7 +121,6 @@ var ( osv.Wrapper{ExtractorName: "java/gradle", ExtractorVersion: 0, PURLType: purl.TypeMaven, Extractor: lockfile.GradleLockExtractor{}}, osv.Wrapper{ExtractorName: "java/pomxml", ExtractorVersion: 0, PURLType: purl.TypeMaven, Extractor: lockfile.MavenLockExtractor{}}, osv.Wrapper{ExtractorName: "javascript/yarn", ExtractorVersion: 0, PURLType: purl.TypeNPM, Extractor: lockfile.YarnLockExtractor{}}, - osv.Wrapper{ExtractorName: "php/composer", ExtractorVersion: 0, PURLType: purl.TypeComposer, Extractor: lockfile.ComposerLockExtractor{}}, osv.Wrapper{ExtractorName: "python/Pipfile", ExtractorVersion: 0, PURLType: purl.TypePyPi, Extractor: lockfile.PipenvLockExtractor{}}, osv.Wrapper{ExtractorName: "python/poetry", ExtractorVersion: 0, PURLType: purl.TypePyPi, Extractor: lockfile.PoetryLockExtractor{}}, osv.Wrapper{ExtractorName: "ruby/gemfile", ExtractorVersion: 0, PURLType: purl.TypeGem, Extractor: lockfile.GemfileLockExtractor{}}, @@ -132,6 +135,7 @@ var ( "go": Go, "ruby": Ruby, "dotnet": Dotnet, + "php": PHP, "sbom": SBOM, "os": OS,