Files
aquasecurity-trivy/pkg/fanal/analyzer/language/nodejs/npm/npm.go

161 lines
4.6 KiB
Go
Raw Normal View History

2019-05-01 15:24:08 +09:00
package npm
import (
"context"
"errors"
"io"
"io/fs"
feat: support local filesystem and remote git repository (fanal#107) * test(integration): move to the test directory * chore: update fixtures path * test: put common test images under the test directory * chore(Makefile): rename * feat: support local filesystem and remote git repository [PART 1] (fanal#109) * feat(walker): add tar/fs walker * fs_test: Add test names Signed-off-by: Simarpreet Singh <simar@linux.com> * walk_test: Add Test_isIgnored Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 2] (fanal#110) * refactor(analyzer): merge OSAnalyzer, PkgAnalyze, LibAnalyzer into Analyzer * test: comment out temporarily * fix(amazon): check the length * fix(analyzer): make AnalysisResult a reference * library/analyzer: Refactor library analyzer code. Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 3] (fanal#111) * refactor(image): move directory * feat(applier): add applier * fix(apk): replace extractor with applier * test: comment out temporarily * feat: support local filesystem and remote git repository [PART 4] (fanal#112) * feat(artifact): add image, local and remote artifact * image_test: Rename test field to use new convention Signed-off-by: Simarpreet Singh <simar@linux.com> * image_test: Add a test for put artifact failure Signed-off-by: Simarpreet Singh <simar@linux.com> * refactor(remote): remove unnecessary files for unit test * feat: support local filesystem and remote git repository [PART 5] (fanal#113) * test(integration): fix tests * feat: support local filesystem and remote git repository [PART 6] (fanal#114) * feat(main): add sub commands * refactor(types): remove unused type * chore(mod): update * test(artifact): add mock * fix(analyzer): redhat must be replaced with oracle * fix(analyzer): debian must be replaced with ubuntu * fix(fs): display dir when hostname is empty Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> * fix: make AnalysisResult a reference Co-authored-by: Simarpreet Singh <simar@linux.com> * refactor(walker): fix comment Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-05-28 23:29:07 +03:00
"os"
"path"
2019-05-01 15:24:08 +09:00
"path/filepath"
"golang.org/x/xerrors"
feat(cache): based on JSON (fanal#84) * temp * update * fix integration test * update * update * test(docker): add a test for ExtractLayerFiles * docker_test: Add opq and wh file paths. Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add sad path for GetLayer Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add invalid file for extractFiles Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: remove old crufty tests Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add tests for ApplyLayers Signed-off-by: Simarpreet Singh <simar@linux.com> * test(docker): add tests for status.d * test(docker): no mock * temp * analyze_test: Add tests for Analzye() happy path Signed-off-by: Simarpreet Singh <simar@linux.com> * cache: remove mock_cache.go Signed-off-by: Simarpreet Singh <simar@linux.com> * analyzer_test: Prefer real extractor over mock Signed-off-by: Simarpreet Singh <simar@linux.com> * analyzer_test: Add sad paths for Analyze Signed-off-by: Simarpreet Singh <simar@linux.com> * tests: Fix invocation call sites for new JSON cache Signed-off-by: Simarpreet Singh <simar@linux.com> * test(image): add httptest server * utils_test: Add build tags Signed-off-by: Simarpreet Singh <simar@linux.com> * test(analyzer): add sad path * test(image): remove unused tests * test(integration): fix interface * test(analyzer): add an image including lock files * refactor(analyzer): remove the unused function * test(analyzer): add tests for Applier * test(cache): add cache tests * feat(cache): support schema version * refactor(mock): remove unnecessary mocks * refactor: clean up debug code * test(analyzer): add a test image * test(bench): fix cache * cache_test: Add a layer with SchemaVersion of 2 Signed-off-by: Simarpreet Singh <simar@linux.com> * library_test: remove cruft Signed-off-by: Simarpreet Singh <simar@linux.com> * feat(image): support docker host and cert path * refactor(image): add omitempty * feat(image): add new struct to have image information in cache * feat(cache): add image bucket * refactor(cache): commonize getting layer * test(mock): generate new mocks * feat(analyzer): analyze image config and store it in cache * refactor(analyzer): make errors lowercase * test(cache): update tests * test(analyzer): fix tests * fix(cmd): pass image ID * fix(analyzer): add HistoryPackages to store package from history * fix(cache): return an error in GetLayer * refactor(cache): rename ImageConfig to ImageInfo * refactor(err): wrap errors Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-02-27 21:09:05 +02:00
chore(deps): merge go-dep-parser into Trivy (#6094) Signed-off-by: Arunprasad Rajkumar <arajkuma@redhat.com> Signed-off-by: guoguangwu <guoguangwu@magic-shield.com> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: knqyf263 <knqyf263@gmail.com> Co-authored-by: Masahiro <mur4m4s4.331@gmail.com> Co-authored-by: Tomoya Amachi <tomoya.amachi@gmail.com> Co-authored-by: Masahiro <lomycisw@gmail.com> Co-authored-by: Liz Rice <liz@lizrice.com> Co-authored-by: Johannes <johannes@jitesoft.com> Co-authored-by: aprp <doelaudi@gmail.com> Co-authored-by: rahul2393 <rahulyadavsep92@gmail.com> Co-authored-by: Arunprasad Rajkumar <ar.arunprasad@gmail.com> Co-authored-by: Emrecan BATI <emrecanbati@gmail.com> Co-authored-by: sherif84 <12298259+sherif84@users.noreply.github.com> Co-authored-by: Sherif Fathalla <sfathall@akamai.com> Co-authored-by: sherif <sherif.mailbox@gmail.com> Co-authored-by: Sam Lane <samuel.lane@hotmail.com> Co-authored-by: Ankush K <akhobragade@gmail.com> Co-authored-by: Ankush K <akhobragade42@gmail.com> Co-authored-by: Tauseef <tauseefmlk@gmail.com> Co-authored-by: Daniel <danfaizer@gmail.com> Co-authored-by: Matthieu MOREL <mmorel-35@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: afdesk <work@afdesk.com> Co-authored-by: AndreyLevchenko <levchenko.andrey@gmail.com> Co-authored-by: Kobus van Schoor <10784365+kobus-v-schoor@users.noreply.github.com> Co-authored-by: Jan-Otto Kröpke <github@jkroepke.de> Co-authored-by: jerbob92 <jerbob92@users.noreply.github.com> Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Co-authored-by: Shira Cohen <97398476+ShiraCohen33@users.noreply.github.com> Co-authored-by: astevenson-microsoft <78623826+astevenson-microsoft@users.noreply.github.com> Co-authored-by: Kyriakos Georgiou <kgeorgiou@users.noreply.github.com> Co-authored-by: mycodeself <mycodeself@users.noreply.github.com> Co-authored-by: DavidSalame <75929252+davidsalame1@users.noreply.github.com> Co-authored-by: Tom Fay <tom@teamfay.co.uk> Co-authored-by: Tom Fay <tomfay@microsoft.com> Co-authored-by: François Poirotte <fpoirotte@users.noreply.github.com> Co-authored-by: Guy Ben-Aharon <baguy3@gmail.com> Co-authored-by: Catminusminus <37803616+Catminusminus@users.noreply.github.com> Co-authored-by: Lior Vaisman Argon <97836016+VaismanLior@users.noreply.github.com> Co-authored-by: Matthieu Maitre <mmaitre@microsoft.com> Co-authored-by: Andrea Scarpino <andrea@scarpino.dev> Co-authored-by: MorAlon1 <101275199+MorAlon1@users.noreply.github.com> Co-authored-by: liorj-orca <96177663+liorj-orca@users.noreply.github.com> Co-authored-by: Nikita Pivkin <100182843+nikpivkin@users.noreply.github.com> Co-authored-by: guangwu <guoguangwu@magic-shield.com> Co-authored-by: Nikita Pivkin <nikita.pivkin@smartforce.io> Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io> Co-authored-by: yuriShafet <5830215+yuriShafet@users.noreply.github.com> Co-authored-by: Octogonapus <firey45@gmail.com>
2024-02-19 15:16:35 +04:00
"github.com/aquasecurity/trivy/pkg/dependency/parser/nodejs/npm"
"github.com/aquasecurity/trivy/pkg/dependency/parser/nodejs/packagejson"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/language"
"github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
xio "github.com/aquasecurity/trivy/pkg/x/io"
xpath "github.com/aquasecurity/trivy/pkg/x/path"
2019-05-01 15:24:08 +09:00
)
func init() {
analyzer.RegisterPostAnalyzer(analyzer.TypeNpmPkgLock, newNpmLibraryAnalyzer)
2019-05-01 15:24:08 +09:00
}
const (
version = 1
)
type npmLibraryAnalyzer struct {
logger *log.Logger
lockParser language.Parser
packageParser *packagejson.Parser
}
func newNpmLibraryAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) {
return &npmLibraryAnalyzer{
logger: log.WithPrefix("npm"),
lockParser: npm.NewParser(),
packageParser: packagejson.NewParser(),
}, nil
}
2025-10-14 11:13:48 +06:00
func (a npmLibraryAnalyzer) PostAnalyze(ctx context.Context, input analyzer.PostAnalysisInput) (*analyzer.AnalysisResult, error) {
// Parse package-lock.json
required := func(path string, _ fs.DirEntry) bool {
return filepath.Base(path) == types.NpmPkgLock || input.FilePatterns.Match(path)
}
var apps []types.Application
err := fsutils.WalkDir(input.FS, ".", required, func(filePath string, _ fs.DirEntry, _ io.Reader) error {
// Find all licenses from package.json files under node_modules dirs
licenses, err := a.findLicenses(input.FS, filePath)
if err != nil {
a.logger.Error("Unable to collect licenses", log.Err(err))
licenses = make(map[string][]string)
}
2025-10-14 11:13:48 +06:00
app, err := a.parseNpmPkgLock(ctx, input.FS, filePath)
if err != nil {
return xerrors.Errorf("parse error: %w", err)
} else if app == nil {
return nil
}
feat: support local filesystem and remote git repository (fanal#107) * test(integration): move to the test directory * chore: update fixtures path * test: put common test images under the test directory * chore(Makefile): rename * feat: support local filesystem and remote git repository [PART 1] (fanal#109) * feat(walker): add tar/fs walker * fs_test: Add test names Signed-off-by: Simarpreet Singh <simar@linux.com> * walk_test: Add Test_isIgnored Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 2] (fanal#110) * refactor(analyzer): merge OSAnalyzer, PkgAnalyze, LibAnalyzer into Analyzer * test: comment out temporarily * fix(amazon): check the length * fix(analyzer): make AnalysisResult a reference * library/analyzer: Refactor library analyzer code. Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 3] (fanal#111) * refactor(image): move directory * feat(applier): add applier * fix(apk): replace extractor with applier * test: comment out temporarily * feat: support local filesystem and remote git repository [PART 4] (fanal#112) * feat(artifact): add image, local and remote artifact * image_test: Rename test field to use new convention Signed-off-by: Simarpreet Singh <simar@linux.com> * image_test: Add a test for put artifact failure Signed-off-by: Simarpreet Singh <simar@linux.com> * refactor(remote): remove unnecessary files for unit test * feat: support local filesystem and remote git repository [PART 5] (fanal#113) * test(integration): fix tests * feat: support local filesystem and remote git repository [PART 6] (fanal#114) * feat(main): add sub commands * refactor(types): remove unused type * chore(mod): update * test(artifact): add mock * fix(analyzer): redhat must be replaced with oracle * fix(analyzer): debian must be replaced with ubuntu * fix(fs): display dir when hostname is empty Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> * fix: make AnalysisResult a reference Co-authored-by: Simarpreet Singh <simar@linux.com> * refactor(walker): fix comment Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-05-28 23:29:07 +03:00
// Fill licenses from package.json only if not present in lock file
for i, pkg := range app.Packages {
if len(pkg.Licenses) == 0 {
if ll, ok := licenses[pkg.ID]; ok {
app.Packages[i].Licenses = ll
}
}
}
2019-05-01 15:24:08 +09:00
apps = append(apps, *app)
return nil
})
feat: support local filesystem and remote git repository (fanal#107) * test(integration): move to the test directory * chore: update fixtures path * test: put common test images under the test directory * chore(Makefile): rename * feat: support local filesystem and remote git repository [PART 1] (fanal#109) * feat(walker): add tar/fs walker * fs_test: Add test names Signed-off-by: Simarpreet Singh <simar@linux.com> * walk_test: Add Test_isIgnored Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 2] (fanal#110) * refactor(analyzer): merge OSAnalyzer, PkgAnalyze, LibAnalyzer into Analyzer * test: comment out temporarily * fix(amazon): check the length * fix(analyzer): make AnalysisResult a reference * library/analyzer: Refactor library analyzer code. Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 3] (fanal#111) * refactor(image): move directory * feat(applier): add applier * fix(apk): replace extractor with applier * test: comment out temporarily * feat: support local filesystem and remote git repository [PART 4] (fanal#112) * feat(artifact): add image, local and remote artifact * image_test: Rename test field to use new convention Signed-off-by: Simarpreet Singh <simar@linux.com> * image_test: Add a test for put artifact failure Signed-off-by: Simarpreet Singh <simar@linux.com> * refactor(remote): remove unnecessary files for unit test * feat: support local filesystem and remote git repository [PART 5] (fanal#113) * test(integration): fix tests * feat: support local filesystem and remote git repository [PART 6] (fanal#114) * feat(main): add sub commands * refactor(types): remove unused type * chore(mod): update * test(artifact): add mock * fix(analyzer): redhat must be replaced with oracle * fix(analyzer): debian must be replaced with ubuntu * fix(fs): display dir when hostname is empty Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> * fix: make AnalysisResult a reference Co-authored-by: Simarpreet Singh <simar@linux.com> * refactor(walker): fix comment Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-05-28 23:29:07 +03:00
if err != nil {
return nil, xerrors.Errorf("package-lock.json/package.json walk error: %w", err)
2019-05-01 15:24:08 +09:00
}
return &analyzer.AnalysisResult{
Applications: apps,
}, nil
2019-05-01 15:24:08 +09:00
}
feat: support local filesystem and remote git repository (fanal#107) * test(integration): move to the test directory * chore: update fixtures path * test: put common test images under the test directory * chore(Makefile): rename * feat: support local filesystem and remote git repository [PART 1] (fanal#109) * feat(walker): add tar/fs walker * fs_test: Add test names Signed-off-by: Simarpreet Singh <simar@linux.com> * walk_test: Add Test_isIgnored Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 2] (fanal#110) * refactor(analyzer): merge OSAnalyzer, PkgAnalyze, LibAnalyzer into Analyzer * test: comment out temporarily * fix(amazon): check the length * fix(analyzer): make AnalysisResult a reference * library/analyzer: Refactor library analyzer code. Signed-off-by: Simarpreet Singh <simar@linux.com> * feat: support local filesystem and remote git repository [PART 3] (fanal#111) * refactor(image): move directory * feat(applier): add applier * fix(apk): replace extractor with applier * test: comment out temporarily * feat: support local filesystem and remote git repository [PART 4] (fanal#112) * feat(artifact): add image, local and remote artifact * image_test: Rename test field to use new convention Signed-off-by: Simarpreet Singh <simar@linux.com> * image_test: Add a test for put artifact failure Signed-off-by: Simarpreet Singh <simar@linux.com> * refactor(remote): remove unnecessary files for unit test * feat: support local filesystem and remote git repository [PART 5] (fanal#113) * test(integration): fix tests * feat: support local filesystem and remote git repository [PART 6] (fanal#114) * feat(main): add sub commands * refactor(types): remove unused type * chore(mod): update * test(artifact): add mock * fix(analyzer): redhat must be replaced with oracle * fix(analyzer): debian must be replaced with ubuntu * fix(fs): display dir when hostname is empty Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> * fix: make AnalysisResult a reference Co-authored-by: Simarpreet Singh <simar@linux.com> * refactor(walker): fix comment Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com> Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-05-28 23:29:07 +03:00
func (a npmLibraryAnalyzer) Required(filePath string, _ os.FileInfo) bool {
fileName := filepath.Base(filePath)
// Don't save package-lock.json from the `node_modules` directory to avoid duplication and mistakes.
if fileName == types.NpmPkgLock && !xpath.Contains(filePath, "node_modules") {
return true
}
// Save package.json files only from the `node_modules` directory.
// Required to search for licenses.
if fileName == types.NpmPkg && xpath.Contains(filePath, "node_modules") {
return true
}
return false
2019-05-01 15:24:08 +09:00
}
feat(cache): based on JSON (fanal#84) * temp * update * fix integration test * update * update * test(docker): add a test for ExtractLayerFiles * docker_test: Add opq and wh file paths. Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add sad path for GetLayer Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add invalid file for extractFiles Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: remove old crufty tests Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add tests for ApplyLayers Signed-off-by: Simarpreet Singh <simar@linux.com> * test(docker): add tests for status.d * test(docker): no mock * temp * analyze_test: Add tests for Analzye() happy path Signed-off-by: Simarpreet Singh <simar@linux.com> * cache: remove mock_cache.go Signed-off-by: Simarpreet Singh <simar@linux.com> * analyzer_test: Prefer real extractor over mock Signed-off-by: Simarpreet Singh <simar@linux.com> * analyzer_test: Add sad paths for Analyze Signed-off-by: Simarpreet Singh <simar@linux.com> * tests: Fix invocation call sites for new JSON cache Signed-off-by: Simarpreet Singh <simar@linux.com> * test(image): add httptest server * utils_test: Add build tags Signed-off-by: Simarpreet Singh <simar@linux.com> * test(analyzer): add sad path * test(image): remove unused tests * test(integration): fix interface * test(analyzer): add an image including lock files * refactor(analyzer): remove the unused function * test(analyzer): add tests for Applier * test(cache): add cache tests * feat(cache): support schema version * refactor(mock): remove unnecessary mocks * refactor: clean up debug code * test(analyzer): add a test image * test(bench): fix cache * cache_test: Add a layer with SchemaVersion of 2 Signed-off-by: Simarpreet Singh <simar@linux.com> * library_test: remove cruft Signed-off-by: Simarpreet Singh <simar@linux.com> * feat(image): support docker host and cert path * refactor(image): add omitempty * feat(image): add new struct to have image information in cache * feat(cache): add image bucket * refactor(cache): commonize getting layer * test(mock): generate new mocks * feat(analyzer): analyze image config and store it in cache * refactor(analyzer): make errors lowercase * test(cache): update tests * test(analyzer): fix tests * fix(cmd): pass image ID * fix(analyzer): add HistoryPackages to store package from history * fix(cache): return an error in GetLayer * refactor(cache): rename ImageConfig to ImageInfo * refactor(err): wrap errors Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-02-27 21:09:05 +02:00
func (a npmLibraryAnalyzer) Type() analyzer.Type {
return analyzer.TypeNpmPkgLock
feat(cache): based on JSON (fanal#84) * temp * update * fix integration test * update * update * test(docker): add a test for ExtractLayerFiles * docker_test: Add opq and wh file paths. Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add sad path for GetLayer Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add invalid file for extractFiles Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: remove old crufty tests Signed-off-by: Simarpreet Singh <simar@linux.com> * docker_test: Add tests for ApplyLayers Signed-off-by: Simarpreet Singh <simar@linux.com> * test(docker): add tests for status.d * test(docker): no mock * temp * analyze_test: Add tests for Analzye() happy path Signed-off-by: Simarpreet Singh <simar@linux.com> * cache: remove mock_cache.go Signed-off-by: Simarpreet Singh <simar@linux.com> * analyzer_test: Prefer real extractor over mock Signed-off-by: Simarpreet Singh <simar@linux.com> * analyzer_test: Add sad paths for Analyze Signed-off-by: Simarpreet Singh <simar@linux.com> * tests: Fix invocation call sites for new JSON cache Signed-off-by: Simarpreet Singh <simar@linux.com> * test(image): add httptest server * utils_test: Add build tags Signed-off-by: Simarpreet Singh <simar@linux.com> * test(analyzer): add sad path * test(image): remove unused tests * test(integration): fix interface * test(analyzer): add an image including lock files * refactor(analyzer): remove the unused function * test(analyzer): add tests for Applier * test(cache): add cache tests * feat(cache): support schema version * refactor(mock): remove unnecessary mocks * refactor: clean up debug code * test(analyzer): add a test image * test(bench): fix cache * cache_test: Add a layer with SchemaVersion of 2 Signed-off-by: Simarpreet Singh <simar@linux.com> * library_test: remove cruft Signed-off-by: Simarpreet Singh <simar@linux.com> * feat(image): support docker host and cert path * refactor(image): add omitempty * feat(image): add new struct to have image information in cache * feat(cache): add image bucket * refactor(cache): commonize getting layer * test(mock): generate new mocks * feat(analyzer): analyze image config and store it in cache * refactor(analyzer): make errors lowercase * test(cache): update tests * test(analyzer): fix tests * fix(cmd): pass image ID * fix(analyzer): add HistoryPackages to store package from history * fix(cache): return an error in GetLayer * refactor(cache): rename ImageConfig to ImageInfo * refactor(err): wrap errors Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-02-27 21:09:05 +02:00
}
func (a npmLibraryAnalyzer) Version() int {
return version
}
2025-10-14 11:13:48 +06:00
func (a npmLibraryAnalyzer) parseNpmPkgLock(ctx context.Context, fsys fs.FS, filePath string) (*types.Application, error) {
f, err := fsys.Open(filePath)
if err != nil {
return nil, xerrors.Errorf("file open error: %w", err)
}
defer func() { _ = f.Close() }()
file, ok := f.(xio.ReadSeekCloserAt)
if !ok {
return nil, xerrors.Errorf("type assertion error: %w", err)
}
// parse package-lock.json file
2025-10-14 11:13:48 +06:00
return language.Parse(ctx, types.Npm, filePath, file, a.lockParser)
}
func (a npmLibraryAnalyzer) findLicenses(fsys fs.FS, lockPath string) (map[string][]string, error) {
dir := path.Dir(lockPath)
root := path.Join(dir, "node_modules")
if _, err := fs.Stat(fsys, root); errors.Is(err, fs.ErrNotExist) {
a.logger.Info(`To collect the license information of packages, "npm install" needs to be performed beforehand`,
log.String("dir", root))
return nil, nil
}
// Parse package.json
required := func(path string, _ fs.DirEntry) bool {
return filepath.Base(path) == types.NpmPkg
}
// Traverse node_modules dir and find licenses
// Note that fs.FS is always slashed regardless of the platform,
// and path.Join should be used rather than filepath.Join.
licenses := make(map[string][]string)
err := fsutils.WalkDir(fsys, root, required, func(filePath string, _ fs.DirEntry, r io.Reader) error {
pkg, err := a.packageParser.Parse(r)
if err != nil {
return xerrors.Errorf("unable to parse %q: %w", filePath, err)
}
licenses[pkg.ID] = pkg.Licenses
return nil
})
if err != nil {
return nil, xerrors.Errorf("walk error: %w", err)
}
return licenses, nil
}