From 338cbf0555882d46d6385a514017d546c544f743 Mon Sep 17 00:00:00 2001 From: mrl5 <31549762+mrl5@users.noreply.github.com> Date: Sun, 6 Mar 2022 00:04:54 +0100 Subject: [PATCH] feat(scan): support scanning the portage tree/kits of ebuilds [#29] --- README.md | 1 + crates/cli/src/command/scan.rs | 4 ++ crates/cpe-tag/python/integrator.py | 1 + crates/os-adapter/src/adapter/portage.rs | 68 ++++++++++++++++-------- docs/COOKBOOK.md | 14 +++++ 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 03e9ef1..5620599 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Discover CVEs for software. - **Use case 1)** as a [Funtoo Linux] user I want to have awareness about CVEs on my system - **Use case 2)** as user I want to list CVEs for given package - **Use case 3)** as a [Gentoo Linux] user I want to have awareness about CVEs on my system +- **Use case 4)** as a [Funtoo Linux] maintainer I want to scan all packages in kit for CVEs ## DISCLAIMER diff --git a/crates/cli/src/command/scan.rs b/crates/cli/src/command/scan.rs index a54da23..aa8bef2 100644 --- a/crates/cli/src/command/scan.rs +++ b/crates/cli/src/command/scan.rs @@ -47,6 +47,10 @@ pub async fn execute( let known_exploited_cves = fetch_known_exploited_cves(&client).await?; for (ctg, pkgs) in catpkgs { + if pkgs.len() == 0 { + continue; + } + let cwd = out_dir.join(&ctg); log::debug!("processing {} ...", ctg); handle_pkgs(&client, &feed, &cwd, &ctg, &pkgs, &known_exploited_cves).await?; diff --git a/crates/cpe-tag/python/integrator.py b/crates/cpe-tag/python/integrator.py index 9ba9ef7..8efe591 100644 --- a/crates/cpe-tag/python/integrator.py +++ b/crates/cpe-tag/python/integrator.py @@ -12,6 +12,7 @@ def run(payload: list) -> str: def handle_list(packages: list) -> list: + assert len(packages) > 0, "expected non empty list" cpe_patterns = [] for package in packages: cpe_patterns = cpe_patterns + handle_dict(package) diff --git a/crates/os-adapter/src/adapter/portage.rs b/crates/os-adapter/src/adapter/portage.rs index ab6cb51..97f024f 100644 --- a/crates/os-adapter/src/adapter/portage.rs +++ b/crates/os-adapter/src/adapter/portage.rs @@ -8,7 +8,7 @@ use cpe_tag::package::{convert_to_pkg, Package}; use std::collections::HashMap; use std::error::Error; -use std::fs::read_dir; +use std::fs::{read_dir, DirEntry}; use std::path::{Path, PathBuf}; pub trait Portage { @@ -28,7 +28,7 @@ where fn get_all_catpkgs(&self) -> Result>, Box> { let pkg_prefix_adapter: HashMap<&str, String> = HashMap::from([("dev-libs", "lib".to_owned())]); - let skipped_dirs = vec!["virtual"]; + let skipped_dirs = vec!["eclass", "licenses", "metadata", "profiles", "virtual"]; let mut all_catpkgs = HashMap::new(); if !&self.get_pkg_dir().exists() { @@ -39,21 +39,21 @@ where for category in read_dir(&self.get_pkg_dir())? { let category = category?; - let path = &category.path(); + let cat_path = &category.path(); - if !path.is_dir() { + if !cat_path.is_dir() { continue; } match category.file_name().into_string() { Ok(ctgr) => { - if skipped_dirs.contains(&ctgr.as_str()) { + if skipped_dirs.contains(&ctgr.as_str()) || ctgr.starts_with('.') { log::debug!("SKIPPING packages in {} ...", ctgr); continue; } log::debug!("collecting packages in {} ...", ctgr); - let pkgs = list_pkgs(path, pkg_prefix_adapter.get(ctgr.as_str()))?; + let pkgs = list_pkgs(cat_path, pkg_prefix_adapter.get(ctgr.as_str()))?; all_catpkgs.insert(ctgr, pkgs); } Err(os_path) => { @@ -72,30 +72,54 @@ fn list_pkgs(path: &Path, prefix: Option<&String>) -> Result, Box, + pkgs: &mut Vec, +) -> Result<(), Box> { + for entry in read_dir(path)? { + let entry = entry?; + if !is_ebuild(&entry) { continue; } - match pkg.file_name().into_string() { - Ok(p) => { - if let Some(converted) = convert_to_pkg(&p) { - pkgs.push(converted); - } + if let Ok(ebuild) = entry.file_name().into_string() { + let pkg: Vec<&str> = ebuild.rsplit(".ebuild").collect(); + let pkg = pkg[1].to_owned(); + if let Some(converted) = convert_to_pkg(&pkg) { + pkgs.push(converted); + } - if let Some(prfx) = prefix { - if let Some(converted) = convert_to_pkg(&format!("{}{}", prfx, &p)) { - pkgs.push(converted); - } + if let Some(prfx) = prefix { + if let Some(converted) = convert_to_pkg(&format!("{}{}", prfx, &pkg)) { + pkgs.push(converted); } } - Err(os_string) => { - log::error!("skipping {:?}", os_string); - continue; - } } } - Ok(pkgs) + Ok(()) +} + +fn is_ebuild(entry: &DirEntry) -> bool { + if !entry.path().is_file() { + return false; + } + + if let Ok(file_name) = entry.file_name().into_string() { + return file_name.ends_with(".ebuild"); + } + + log::error!("malformed file name {:?}", entry.file_name()); + false } diff --git a/docs/COOKBOOK.md b/docs/COOKBOOK.md index d35927c..870f4eb 100644 --- a/docs/COOKBOOK.md +++ b/docs/COOKBOOK.md @@ -8,6 +8,7 @@ vulner --help - [Scanning Funtoo Linux system for CVEs](#scanning-funtoo-linux-system-for-cves) - [Listing CVEs for given packages](#listing-cves-for-given-packages) - [Printing known exploited vulnerabilities catalog](#printing-known-exploited-vulnerabilities-catalog) +- [Scanning packages in Funtoo Linux kit for CVEs](#scanning-packages-in-funtoo-linux-kit-for-cves) ## Scanning Funtoo Linux system for CVEs @@ -57,6 +58,19 @@ $ cat ~/vulner/scan-results/2022-01-30UTC/*/app-emulation/*containerd*.txt | jq ``` +## Scanning packages in Funtoo Linux kit for CVEs +```bash +kit="gnome-kit" + +export VULNER_FEED_DIR=$HOME/vulner/feeds/json +export VULNER_OUT_DIR=$HOME/vulner/${kit}-scan-results +export RUST_LOG=info + +vulner sync +vulner scan -p /var/git/meta-repo/kits/${kit}/ +``` + + ## Listing CVEs for given packages ### Example 1