1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use std::path::PathBuf;
use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser, Debug)]
#[command(
name = "bitvex",
version,
about = "CRA compliance tool: generates OpenVEX reports from Yocto build artifacts"
)]
pub struct Args {
#[command(subcommand)]
pub command: Option<Command>,
/// Path to the SBOM in SPDX JSON format
#[arg(long, value_name = "PATH")]
pub sbom: Option<PathBuf>,
/// Path to the Linux kernel .config file
#[arg(long = "kernel-config", value_name = "PATH")]
pub kernel_config: Option<PathBuf>,
/// Path to the Device Tree source file (.dts)
#[arg(long = "device-tree", value_name = "PATH")]
pub device_tree: Option<PathBuf>,
/// Output path for the OpenVEX JSON report
#[arg(
long,
short,
value_name = "PATH",
default_value = "bitvex-report.vex.json"
)]
pub output: PathBuf,
/// Author identifier for the VEX document
#[arg(long, default_value = "BitVex <bitvex@automated>")]
pub author: String,
/// Path to bitvex.toml rules file
#[arg(long, value_name = "PATH")]
pub rules: Option<PathBuf>,
/// Use offline OSV database (no network required)
#[arg(long)]
pub offline: bool,
/// Download/update offline OSV database (can combine with --offline)
#[arg(long)]
pub download_db: bool,
/// Path to offline OSV database directory
#[arg(long = "db-path", value_name = "PATH")]
pub db_path: Option<PathBuf>,
/// Database download profile (small/medium/big/complete)
#[arg(long)]
pub profile: Option<DownloadProfile>,
/// Skip confirmation prompts (accept all)
#[arg(long, short)]
pub yes: bool,
/// Enable verbose logging
#[arg(long, short)]
pub verbose: bool,
}
#[derive(Subcommand, Debug)]
pub enum Command {
/// Compare two SBOMs and report differences
Diff {
/// Path to the old SBOM (SPDX JSON)
#[arg(long)]
old: PathBuf,
/// Path to the new SBOM (SPDX JSON)
#[arg(long)]
new: PathBuf,
/// Output path for the diff report (JSON)
#[arg(long, short)]
output: Option<PathBuf>,
},
/// Download/update the offline OSV vulnerability database
DownloadDb {
/// Path to store the database
#[arg(long = "db-path", value_name = "PATH")]
db_path: Option<PathBuf>,
/// Comma-separated list of ecosystems to download
#[arg(long, value_delimiter = ',')]
ecosystems: Option<Vec<String>>,
/// Download profile: small (29MB), medium (35MB), big (116MB), complete (822MB)
#[arg(long)]
profile: Option<DownloadProfile>,
/// Skip confirmation prompt
#[arg(long, short)]
yes: bool,
},
}
#[derive(Debug, Clone, ValueEnum)]
pub enum DownloadProfile {
/// Linux kernel only (~29 MB)
Small,
/// Linux + Alpine + crates.io (~35 MB) - Recommended
Medium,
/// Linux + Alpine + Debian + PyPI + crates.io (~116 MB)
Big,
/// All ecosystems (~822 MB)
Complete,
}
impl DownloadProfile {
pub fn ecosystems(&self) -> &[&str] {
match self {
DownloadProfile::Small => &["Linux"],
DownloadProfile::Medium => &["Linux", "Alpine", "crates.io"],
DownloadProfile::Big => &["Linux", "Alpine", "Debian", "PyPI", "crates.io"],
DownloadProfile::Complete => &[
"Alpine",
"Debian",
"Ubuntu",
"Linux",
"crates.io",
"Go",
"npm",
"PyPI",
"Maven",
"NuGet",
],
}
}
pub fn name(&self) -> &str {
match self {
DownloadProfile::Small => "small",
DownloadProfile::Medium => "medium",
DownloadProfile::Big => "big",
DownloadProfile::Complete => "complete",
}
}
}