mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
feat: add manifest-based package installation detection
This commit is contained in:
@@ -73,6 +73,12 @@ func (g *packageManagerGuard) Run(ctx context.Context, args []string, parsedComm
|
||||
log.Debugf("Running package manager guard with args: %v", args)
|
||||
|
||||
if !parsedCommand.HasInstallTarget() {
|
||||
// Check if this is a manifest-based installation
|
||||
if parsedCommand.ShouldExtractFromManifest() {
|
||||
log.Debugf("Detected manifest-based installation, extracting packages from manifest files")
|
||||
return g.handleManifestInstallation(ctx, parsedCommand)
|
||||
}
|
||||
|
||||
log.Debugf("No install target found, continuing execution")
|
||||
return g.continueExecution(ctx, parsedCommand)
|
||||
}
|
||||
@@ -268,3 +274,77 @@ func (g *packageManagerGuard) clearStatus() {
|
||||
|
||||
g.interaction.ClearStatus()
|
||||
}
|
||||
|
||||
func (g *packageManagerGuard) handleManifestInstallation(ctx context.Context, parsedCommand *packagemanager.ParsedCommand) error {
|
||||
g.setStatus("Extracting packages from manifest files")
|
||||
|
||||
// Create extractor with appropriate ecosystem
|
||||
var ecosystem packagev1.Ecosystem
|
||||
switch g.packageManager.Name() {
|
||||
case "pip":
|
||||
ecosystem = packagev1.Ecosystem_ECOSYSTEM_PYPI
|
||||
case "npm", "pnpm":
|
||||
ecosystem = packagev1.Ecosystem_ECOSYSTEM_NPM
|
||||
default:
|
||||
return fmt.Errorf("unsupported package manager for manifest extraction: %s", g.packageManager.Name())
|
||||
}
|
||||
|
||||
extractorConfig := packagemanager.NewDefaultExtractorConfig()
|
||||
extractorConfig.ExtractorEcosystem = ecosystem
|
||||
|
||||
switch ecosystem {
|
||||
case packagev1.Ecosystem_ECOSYSTEM_PYPI:
|
||||
extractorConfig.ExtractorsName = packagemanager.PyPiExtractors
|
||||
case packagev1.Ecosystem_ECOSYSTEM_NPM:
|
||||
extractorConfig.ExtractorsName = packagemanager.NpmExtractors
|
||||
}
|
||||
|
||||
extractor := packagemanager.NewExtractor(*extractorConfig)
|
||||
|
||||
packages, err := extractor.ExtractManifestFiles()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to extract packages from manifest files: %w", err)
|
||||
}
|
||||
|
||||
if len(packages) == 0 {
|
||||
log.Debugf("No packages found in manifest files, continuing execution")
|
||||
return g.continueExecution(ctx, parsedCommand)
|
||||
}
|
||||
|
||||
log.Debugf("Extracted %d packages from manifest files", len(packages))
|
||||
|
||||
// Analyze the extracted packages
|
||||
g.setStatus(fmt.Sprintf("Analyzing %d packages from manifest files", len(packages)))
|
||||
|
||||
analysisResults, err := g.concurrentAnalyzePackages(ctx, packages)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to analyze packages: %w", err)
|
||||
}
|
||||
|
||||
confirmableMalwarePackages := []*analyzer.PackageVersionAnalysisResult{}
|
||||
for _, result := range analysisResults {
|
||||
if result.Action == analyzer.ActionBlock {
|
||||
return g.blockInstallation(result)
|
||||
}
|
||||
|
||||
if result.Action == analyzer.ActionConfirm {
|
||||
confirmableMalwarePackages = append(confirmableMalwarePackages, result)
|
||||
}
|
||||
}
|
||||
|
||||
if len(confirmableMalwarePackages) > 0 {
|
||||
confirmed, err := g.getConfirmationOnMalware(ctx, confirmableMalwarePackages)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get confirmation on malware: %w", err)
|
||||
}
|
||||
|
||||
if !confirmed {
|
||||
return g.blockInstallation(confirmableMalwarePackages...)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("No malicious packages found in manifest files, continuing execution")
|
||||
|
||||
g.clearStatus()
|
||||
return g.continueExecution(ctx, parsedCommand)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user