@@ -361,7 +361,6 @@ func (l *base) detectPlatform() {
361
361
362
362
//TODO Azure, GCP...
363
363
l .setPlatform (models.Platform {Name : "other" })
364
- return
365
364
}
366
365
367
366
var dsFingerPrintPrefix = "AgentStatus.agentCertHash: "
@@ -582,12 +581,6 @@ func (l *base) parseSystemctlStatus(stdout string) string {
582
581
return ss [1 ]
583
582
}
584
583
585
- // LibFile : library file content
586
- type LibFile struct {
587
- Contents []byte
588
- Filemode os.FileMode
589
- }
590
-
591
584
func (l * base ) scanLibraries () (err error ) {
592
585
if len (l .LibraryScanners ) != 0 {
593
586
return nil
@@ -598,9 +591,9 @@ func (l *base) scanLibraries() (err error) {
598
591
return nil
599
592
}
600
593
601
- l .log .Info ("Scanning Lockfile ..." )
594
+ l .log .Info ("Scanning Language-specific Packages ..." )
602
595
603
- libFilemap := map [string ]LibFile {}
596
+ found := map [string ]bool {}
604
597
detectFiles := l .ServerInfo .Lockfiles
605
598
606
599
priv := noSudo
@@ -615,9 +608,17 @@ func (l *base) scanLibraries() (err error) {
615
608
findopt += fmt .Sprintf ("-name %q -o " , filename )
616
609
}
617
610
611
+ dir := "/"
612
+ if len (l .ServerInfo .FindLockDirs ) != 0 {
613
+ dir = strings .Join (l .ServerInfo .FindLockDirs , " " )
614
+ } else {
615
+ l .log .Infof ("It's recommended to specify FindLockDirs in config.toml. If FindLockDirs is not specified, all directories under / will be searched, which may increase CPU load" )
616
+ }
617
+ l .log .Infof ("Finding files under %s" , dir )
618
+
618
619
// delete last "-o "
619
620
// find / -type f -and \( -name "package-lock.json" -o -name "yarn.lock" ... \) 2>&1 | grep -v "find: "
620
- cmd := fmt .Sprintf (`find / -type f -and \( ` + findopt [:len (findopt )- 3 ] + ` \) 2>&1 | grep -v "find: "` )
621
+ cmd := fmt .Sprintf (`find %s -type f -and \( ` + findopt [:len (findopt )- 3 ]+ ` \) 2>&1 | grep -v "find: "` , dir )
621
622
r := exec (l .ServerInfo , cmd , priv )
622
623
if r .ExitStatus != 0 && r .ExitStatus != 1 {
623
624
return xerrors .Errorf ("Failed to find lock files" )
@@ -635,116 +636,62 @@ func (l *base) scanLibraries() (err error) {
635
636
}
636
637
637
638
// skip already exist
638
- if _ , ok := libFilemap [path ]; ok {
639
+ if _ , ok := found [path ]; ok {
639
640
continue
640
641
}
641
642
642
- var f LibFile
643
+ var contents []byte
644
+ var filemode os.FileMode
645
+
643
646
switch l .Distro .Family {
644
647
case constant .ServerTypePseudo :
645
648
fileinfo , err := os .Stat (path )
646
649
if err != nil {
647
- return xerrors .Errorf ("Failed to get target file info. err: %w, filepath: %s" , err , path )
650
+ l .log .Warnf ("Failed to get target file info. err: %s, filepath: %s" , err , path )
651
+ continue
648
652
}
649
- f . Filemode = fileinfo .Mode ().Perm ()
650
- f . Contents , err = os .ReadFile (path )
653
+ filemode = fileinfo .Mode ().Perm ()
654
+ contents , err = os .ReadFile (path )
651
655
if err != nil {
652
- return xerrors .Errorf ("Failed to read target file contents. err: %w, filepath: %s" , err , path )
656
+ l .log .Warnf ("Failed to read target file contents. err: %s, filepath: %s" , err , path )
657
+ continue
653
658
}
654
659
default :
660
+ l .log .Debugf ("Analyzing file: %s" , path )
655
661
cmd := fmt .Sprintf (`stat -c "%%a" %s` , path )
656
- r := exec (l .ServerInfo , cmd , priv )
662
+ r := exec (l .ServerInfo , cmd , priv , logging . NewIODiscardLogger () )
657
663
if ! r .isSuccess () {
658
- return xerrors .Errorf ("Failed to get target file permission: %s, filepath: %s" , r , path )
664
+ l .log .Warnf ("Failed to get target file permission: %s, filepath: %s" , r , path )
665
+ continue
659
666
}
660
667
permStr := fmt .Sprintf ("0%s" , strings .ReplaceAll (r .Stdout , "\n " , "" ))
661
668
perm , err := strconv .ParseUint (permStr , 8 , 32 )
662
669
if err != nil {
663
- return xerrors .Errorf ("Failed to parse permission string. err: %w, permission string: %s" , err , permStr )
670
+ l .log .Warnf ("Failed to parse permission string. err: %s, permission string: %s" , err , permStr )
671
+ continue
664
672
}
665
- f . Filemode = os .FileMode (perm )
673
+ filemode = os .FileMode (perm )
666
674
667
675
cmd = fmt .Sprintf ("cat %s" , path )
668
- r = exec (l .ServerInfo , cmd , priv )
676
+ r = exec (l .ServerInfo , cmd , priv , logging . NewIODiscardLogger () )
669
677
if ! r .isSuccess () {
670
- return xerrors .Errorf ("Failed to get target file contents: %s, filepath: %s" , r , path )
678
+ l .log .Warnf ("Failed to get target file contents: %s, filepath: %s" , r , path )
679
+ continue
671
680
}
672
- f . Contents = []byte (r .Stdout )
681
+ contents = []byte (r .Stdout )
673
682
}
674
- libFilemap [path ] = f
675
- }
676
-
677
- var libraryScanners []models. LibraryScanner
678
- if libraryScanners , err = AnalyzeLibraries ( context . Background (), libFilemap , l . ServerInfo . Mode . IsOffline ()); err != nil {
679
- return err
683
+ found [path ] = true
684
+ var libraryScanners []models. LibraryScanner
685
+ if libraryScanners , err = AnalyzeLibrary ( context . Background (), path , contents , filemode , l . ServerInfo . Mode . IsOffline ()); err != nil {
686
+ return err
687
+ }
688
+ l . LibraryScanners = append ( l . LibraryScanners , libraryScanners ... )
680
689
}
681
- l .LibraryScanners = append (l .LibraryScanners , libraryScanners ... )
682
690
return nil
683
691
}
684
692
685
- // AnalyzeLibraries : detects libs defined in lockfile
686
- func AnalyzeLibraries (ctx context.Context , libFilemap map [string ]LibFile , isOffline bool ) (libraryScanners []models.LibraryScanner , err error ) {
687
- // https://github.com/aquasecurity/trivy/blob/84677903a6fa1b707a32d0e8b2bffc23dde52afa/pkg/fanal/analyzer/const.go
688
- disabledAnalyzers := []analyzer.Type {
689
- // ======
690
- // OS
691
- // ======
692
- analyzer .TypeOSRelease ,
693
- analyzer .TypeAlpine ,
694
- analyzer .TypeAmazon ,
695
- analyzer .TypeCBLMariner ,
696
- analyzer .TypeDebian ,
697
- analyzer .TypePhoton ,
698
- analyzer .TypeCentOS ,
699
- analyzer .TypeRocky ,
700
- analyzer .TypeAlma ,
701
- analyzer .TypeFedora ,
702
- analyzer .TypeOracle ,
703
- analyzer .TypeRedHatBase ,
704
- analyzer .TypeSUSE ,
705
- analyzer .TypeUbuntu ,
706
-
707
- // OS Package
708
- analyzer .TypeApk ,
709
- analyzer .TypeDpkg ,
710
- analyzer .TypeDpkgLicense ,
711
- analyzer .TypeRpm ,
712
- analyzer .TypeRpmqa ,
713
-
714
- // OS Package Repository
715
- analyzer .TypeApkRepo ,
716
-
717
- // ============
718
- // Image Config
719
- // ============
720
- analyzer .TypeApkCommand ,
721
-
722
- // =================
723
- // Structured Config
724
- // =================
725
- analyzer .TypeYaml ,
726
- analyzer .TypeJSON ,
727
- analyzer .TypeDockerfile ,
728
- analyzer .TypeTerraform ,
729
- analyzer .TypeCloudFormation ,
730
- analyzer .TypeHelm ,
731
-
732
- // ========
733
- // License
734
- // ========
735
- analyzer .TypeLicenseFile ,
736
-
737
- // ========
738
- // Secrets
739
- // ========
740
- analyzer .TypeSecret ,
741
-
742
- // =======
743
- // Red Hat
744
- // =======
745
- analyzer .TypeRedHatContentManifestType ,
746
- analyzer .TypeRedHatDockerfileType ,
747
- }
693
+ // AnalyzeLibrary : detects library defined in artifact such as lockfile or jar
694
+ func AnalyzeLibrary (ctx context.Context , path string , contents []byte , filemode os.FileMode , isOffline bool ) (libraryScanners []models.LibraryScanner , err error ) {
748
695
anal , err := analyzer .NewAnalyzerGroup (analyzer.AnalyzerOptions {
749
696
Group : analyzer .GroupBuiltin ,
750
697
DisabledAnalyzers : disabledAnalyzers ,
@@ -753,34 +700,94 @@ func AnalyzeLibraries(ctx context.Context, libFilemap map[string]LibFile, isOffl
753
700
return nil , xerrors .Errorf ("Failed to new analyzer group. err: %w" , err )
754
701
}
755
702
756
- for path , f := range libFilemap {
757
- var wg sync.WaitGroup
758
- result := new (analyzer.AnalysisResult )
759
- if err := anal .AnalyzeFile (
760
- ctx ,
761
- & wg ,
762
- semaphore .NewWeighted (1 ),
763
- result ,
764
- "" ,
765
- path ,
766
- & DummyFileInfo {size : int64 (len (f .Contents )), filemode : f .Filemode },
767
- func () (dio.ReadSeekCloserAt , error ) { return dio .NopCloser (bytes .NewReader (f .Contents )), nil },
768
- nil ,
769
- analyzer.AnalysisOptions {Offline : isOffline },
770
- ); err != nil {
771
- return nil , xerrors .Errorf ("Failed to get libs. err: %w" , err )
772
- }
773
- wg .Wait ()
774
-
775
- libscan , err := convertLibWithScanner (result .Applications )
776
- if err != nil {
777
- return nil , xerrors .Errorf ("Failed to convert libs. err: %w" , err )
778
- }
779
- libraryScanners = append (libraryScanners , libscan ... )
703
+ var wg sync.WaitGroup
704
+ result := new (analyzer.AnalysisResult )
705
+ if err := anal .AnalyzeFile (
706
+ ctx ,
707
+ & wg ,
708
+ semaphore .NewWeighted (1 ),
709
+ result ,
710
+ "" ,
711
+ path ,
712
+ & DummyFileInfo {size : int64 (len (contents )), filemode : filemode },
713
+ func () (dio.ReadSeekCloserAt , error ) { return dio .NopCloser (bytes .NewReader (contents )), nil },
714
+ nil ,
715
+ analyzer.AnalysisOptions {Offline : isOffline },
716
+ ); err != nil {
717
+ return nil , xerrors .Errorf ("Failed to get libs. err: %w" , err )
718
+ }
719
+ wg .Wait ()
720
+
721
+ libscan , err := convertLibWithScanner (result .Applications )
722
+ if err != nil {
723
+ return nil , xerrors .Errorf ("Failed to convert libs. err: %w" , err )
780
724
}
725
+ libraryScanners = append (libraryScanners , libscan ... )
781
726
return libraryScanners , nil
782
727
}
783
728
729
+ // https://github.com/aquasecurity/trivy/blob/84677903a6fa1b707a32d0e8b2bffc23dde52afa/pkg/fanal/analyzer/const.go
730
+ var disabledAnalyzers = []analyzer.Type {
731
+ // ======
732
+ // OS
733
+ // ======
734
+ analyzer .TypeOSRelease ,
735
+ analyzer .TypeAlpine ,
736
+ analyzer .TypeAmazon ,
737
+ analyzer .TypeCBLMariner ,
738
+ analyzer .TypeDebian ,
739
+ analyzer .TypePhoton ,
740
+ analyzer .TypeCentOS ,
741
+ analyzer .TypeRocky ,
742
+ analyzer .TypeAlma ,
743
+ analyzer .TypeFedora ,
744
+ analyzer .TypeOracle ,
745
+ analyzer .TypeRedHatBase ,
746
+ analyzer .TypeSUSE ,
747
+ analyzer .TypeUbuntu ,
748
+
749
+ // OS Package
750
+ analyzer .TypeApk ,
751
+ analyzer .TypeDpkg ,
752
+ analyzer .TypeDpkgLicense ,
753
+ analyzer .TypeRpm ,
754
+ analyzer .TypeRpmqa ,
755
+
756
+ // OS Package Repository
757
+ analyzer .TypeApkRepo ,
758
+
759
+ // ============
760
+ // Image Config
761
+ // ============
762
+ analyzer .TypeApkCommand ,
763
+
764
+ // =================
765
+ // Structured Config
766
+ // =================
767
+ analyzer .TypeYaml ,
768
+ analyzer .TypeJSON ,
769
+ analyzer .TypeDockerfile ,
770
+ analyzer .TypeTerraform ,
771
+ analyzer .TypeCloudFormation ,
772
+ analyzer .TypeHelm ,
773
+
774
+ // ========
775
+ // License
776
+ // ========
777
+ analyzer .TypeLicenseFile ,
778
+
779
+ // ========
780
+ // Secrets
781
+ // ========
782
+ analyzer .TypeSecret ,
783
+
784
+ // =======
785
+ // Red Hat
786
+ // =======
787
+ analyzer .TypeRedHatContentManifestType ,
788
+ analyzer .TypeRedHatDockerfileType ,
789
+ }
790
+
784
791
// DummyFileInfo is a dummy struct for libscan
785
792
type DummyFileInfo struct {
786
793
size int64
0 commit comments