mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
refactor: introduce PackageAnalyser struct and remove unused arborist files
This commit is contained in:
@@ -86,14 +86,13 @@ func wrapNpm() error {
|
||||
return err
|
||||
}
|
||||
|
||||
maliciousPkgs := make(map[string]string)
|
||||
|
||||
client, err := analyser.GetMalwareAnalysisClient()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while creating a malware analysis client: %w", err)
|
||||
}
|
||||
pkgAnalyser := analyser.New(client, ctx)
|
||||
|
||||
handler := analyser.AnalysePackage(maliciousPkgs, client, ctx)
|
||||
handler := pkgAnalyser.Handler()
|
||||
|
||||
// Create work queue with appropriate buffer size and concurrency
|
||||
queue := vetUtils.NewWorkQueue[models.Package](100, 10, handler)
|
||||
@@ -122,8 +121,8 @@ func wrapNpm() error {
|
||||
return fmt.Errorf("npm not found: %w", err)
|
||||
}
|
||||
|
||||
if len(maliciousPkgs) > 0 {
|
||||
if !utils.ConfirmInstallation(maliciousPkgs) {
|
||||
if len(pkgAnalyser.MaliciousPkgs) > 0 {
|
||||
if !utils.ConfirmInstallation(pkgAnalyser.MaliciousPkgs) {
|
||||
log.Infof("Installation canceled due to security concerns")
|
||||
return nil
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,67 +0,0 @@
|
||||
const Arborist = require("@npmcli/arborist");
|
||||
const fs = require("fs");
|
||||
|
||||
async function getDependencyTree(packageName, authToken) {
|
||||
const arb = new Arborist({
|
||||
registry: "https://registry.npmjs.org",
|
||||
token: authToken,
|
||||
authToken: authToken,
|
||||
});
|
||||
try {
|
||||
const idealTree = await arb.buildIdealTree({
|
||||
add: [packageName],
|
||||
});
|
||||
const packageNames = [];
|
||||
idealTree.children.forEach((node) => {
|
||||
packageNames.push(`${node.name}@${node.version}`);
|
||||
});
|
||||
return packageNames;
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch dependency tree for ${packageName}:`, error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write dependency list to a file
|
||||
* @param {string[]} packages - List of package dependencies
|
||||
* @param {string} filename - Output filename
|
||||
*/
|
||||
function writeToFile(packages, filename) {
|
||||
try {
|
||||
fs.writeFileSync(filename, packages.join("\n"), "utf8");
|
||||
console.log(`Dependencies written to ${filename}`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to write to file ${filename}:`, error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const packageArg = process.argv[2];
|
||||
const outputFile = process.argv[3];
|
||||
const authToken = process.env.NPM_AUTH_TOKEN;
|
||||
|
||||
if (!packageArg) {
|
||||
console.error("Please provide a package name as an argument");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!outputFile) {
|
||||
console.error("Please provide an output filename as the second argument");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!authToken) {
|
||||
console.warn(
|
||||
"NPM token not found. Some private or scoped dependencies may not be included in the scan.",
|
||||
);
|
||||
}
|
||||
|
||||
getDependencyTree(packageArg, authToken)
|
||||
.then((packages) => {
|
||||
writeToFile(packages, outputFile);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -14,17 +14,32 @@ import (
|
||||
vetUtils "github.com/safedep/vet/pkg/common/utils"
|
||||
)
|
||||
|
||||
func AnalysePackage(maliciousPkgs map[string]string, client malysisv1grpc.MalwareAnalysisServiceClient, ctx context.Context) vetUtils.WorkQueueFn[models.Package] {
|
||||
type PackageAnalyser struct {
|
||||
MaliciousPkgs map[string]string
|
||||
Client malysisv1grpc.MalwareAnalysisServiceClient
|
||||
Ctx context.Context
|
||||
MaliciousPkgsMutex sync.Mutex
|
||||
}
|
||||
|
||||
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 {
|
||||
var maliciousPkgsMutex sync.Mutex
|
||||
resp, err := SubmitPackageForAnalysis(ctx, client,
|
||||
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(ctx, client, resp.GetAnalysisId())
|
||||
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)
|
||||
@@ -46,9 +61,9 @@ func AnalysePackage(maliciousPkgs map[string]string, client malysisv1grpc.Malwar
|
||||
log.Infof("Inference for %s: isMalware=%v", item.Name, inference.GetIsMalware())
|
||||
|
||||
if inference.GetIsMalware() {
|
||||
maliciousPkgsMutex.Lock()
|
||||
maliciousPkgs[fmt.Sprintf("%s@%s", item.Name, item.Version)] = inference.GetSummary()
|
||||
maliciousPkgsMutex.Unlock()
|
||||
ap.MaliciousPkgsMutex.Lock()
|
||||
ap.MaliciousPkgs[fmt.Sprintf("%s@%s", item.Name, item.Version)] = inference.GetSummary()
|
||||
ap.MaliciousPkgsMutex.Unlock()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user