mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
108 lines
3.3 KiB
Go
108 lines
3.3 KiB
Go
package analyser
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"buf.build/gen/go/safedep/api/grpc/go/safedep/services/malysis/v1/malysisv1grpc"
|
|
malysisv1pb "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/malysis/v1"
|
|
packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1"
|
|
malysisv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/services/malysis/v1"
|
|
"github.com/safedep/dry/log"
|
|
"github.com/safedep/pmg/internal/ui"
|
|
"github.com/safedep/pmg/pkg/models"
|
|
vetUtils "github.com/safedep/vet/pkg/common/utils"
|
|
)
|
|
|
|
type PackageAnalyser struct {
|
|
MaliciousPkgs map[string]string
|
|
Client malysisv1grpc.MalwareAnalysisServiceClient
|
|
Ctx context.Context
|
|
MaliciousPkgsMutex sync.Mutex
|
|
ProgressTracker ui.ProgressTracker
|
|
}
|
|
|
|
func New(client malysisv1grpc.MalwareAnalysisServiceClient, ctx context.Context) *PackageAnalyser {
|
|
return &PackageAnalyser{
|
|
MaliciousPkgs: make(map[string]string),
|
|
Client: client,
|
|
Ctx: ctx,
|
|
MaliciousPkgsMutex: sync.Mutex{},
|
|
}
|
|
}
|
|
|
|
func (ap *PackageAnalyser) Handler() vetUtils.WorkQueueFn[models.Package] {
|
|
return func(q *vetUtils.WorkQueue[models.Package], item models.Package) error {
|
|
resp, err := SubmitPackageForAnalysis(ap.Ctx, ap.Client,
|
|
packagev1.Ecosystem_ECOSYSTEM_NPM, item.Name, item.Version)
|
|
if err != nil {
|
|
log.Debugf("Failed to analyze %s@%s: %v", item.Name, item.Version, err)
|
|
return err
|
|
}
|
|
|
|
reportResp, err := GetAnalysisReport(ap.Ctx, ap.Client, resp.GetAnalysisId())
|
|
if err != nil {
|
|
log.Debugf("Failed to get analysis report for %s:%s %v",
|
|
item.Name, resp.GetAnalysisId(), err)
|
|
return err
|
|
}
|
|
|
|
report := reportResp.GetReport()
|
|
if report == nil {
|
|
log.Debugf("Empty report received for %s", item.Name)
|
|
return nil
|
|
}
|
|
|
|
inference := report.GetInference()
|
|
if inference == nil {
|
|
log.Debugf("No inference data for %s", item.Name)
|
|
return nil
|
|
}
|
|
|
|
log.Infof("Inference for %s: isMalware=%v", item.Name, inference.GetIsMalware())
|
|
|
|
if inference.GetIsMalware() {
|
|
ap.MaliciousPkgsMutex.Lock()
|
|
ap.MaliciousPkgs[fmt.Sprintf("%s@%s", item.Name, item.Version)] = inference.GetSummary()
|
|
ap.MaliciousPkgsMutex.Unlock()
|
|
}
|
|
|
|
ui.IncrementProgress(ap.ProgressTracker, 1)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func SubmitPackageForAnalysis(ctx context.Context, client malysisv1grpc.MalwareAnalysisServiceClient,
|
|
ecosystem packagev1.Ecosystem, name string,
|
|
version string) (*malysisv1.AnalyzePackageResponse, error) {
|
|
req := &malysisv1.AnalyzePackageRequest{
|
|
Target: &malysisv1pb.PackageAnalysisTarget{
|
|
PackageVersion: &packagev1.PackageVersion{
|
|
Package: &packagev1.Package{
|
|
Ecosystem: ecosystem,
|
|
Name: name,
|
|
},
|
|
Version: version,
|
|
},
|
|
},
|
|
}
|
|
resp, err := client.AnalyzePackage(ctx, req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to analyze %s@%s: %w", name, version, err)
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func GetAnalysisReport(ctx context.Context, client malysisv1grpc.MalwareAnalysisServiceClient,
|
|
analysisId string) (*malysisv1.GetAnalysisReportResponse, error) {
|
|
analysisReportReq := &malysisv1.GetAnalysisReportRequest{
|
|
AnalysisId: analysisId,
|
|
}
|
|
reportResp, err := client.GetAnalysisReport(ctx, analysisReportReq)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get analysis report: %w", err)
|
|
}
|
|
return reportResp, nil
|
|
}
|