Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions crates/cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,15 @@ pub struct Cli {
pub checkpoint: Option<String>,
#[arg(long, global = true, help = "Resume a previous scan by UUID")]
pub resume: Option<String>,

#[cfg(feature = "portscan")]
#[arg(
long,
global = true,
env = "NVD_DB_PATH",
help = "Path to NVD CVE database (default: ~/.cache/nvd/nvd.sqlite3)"
)]
pub nvd_db: Option<String>,
}
/// Available gossan subcommands.

Expand Down
10 changes: 10 additions & 0 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ async fn main() -> anyhow::Result<()> {

let mut config = cli.build_config();

#[cfg(feature = "portscan")]
{
let nvd_path = cli
.nvd_db
.clone()
.or_else(|| std::env::var("NVD_DB_PATH").ok())
.map(std::path::PathBuf::from);
gossan_portscan::cve::nvd::init(nvd_path);
}

match cli.command {
Command::Scan {
target,
Expand Down
1 change: 1 addition & 0 deletions crates/portscan/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ rand = "0.8"
md5 = "0.7"
hex = { workspace = true }
hickory-resolver = { workspace = true }
rusqlite = { workspace = true }

[dev-dependencies]
proptest = "1.0"
Expand Down
4 changes: 4 additions & 0 deletions crates/portscan/src/cve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
//! description = "OpenSSH 9.5 — example vulnerability."
//! exploit = "ssh -o ... TARGET"
//! ```
pub mod nvd;

use gossan_core::{ServiceTarget, Target};
use secfinding::{Evidence, Finding, Severity};
use serde::Deserialize;
Expand Down Expand Up @@ -344,6 +346,8 @@ pub fn correlate_with_rules(banner: &str, svc: &ServiceTarget, rules: &[CveRule]
),
&rule.description,
)
.cve(&rule.cve)
.confidence((rule.cvss / 10.0) as f64)
Comment on lines +349 to +350

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clamp confidence to [0.0, 1.0] before writing it.

Line 350 assumes CVSS is always bounded. Since community rules are user-provided, out-of-range CVSS can produce invalid confidence values.

Suggested fix
-            .confidence((rule.cvss / 10.0) as f64)
+            .confidence(((rule.cvss / 10.0) as f64).clamp(0.0, 1.0))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.cve(&rule.cve)
.confidence((rule.cvss / 10.0) as f64)
.cve(&rule.cve)
.confidence(((rule.cvss / 10.0) as f64).clamp(0.0, 1.0))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/portscan/src/cve.rs` around lines 349 - 350, Clamp the computed
confidence to the [0.0, 1.0] range before passing it to .confidence: compute a
bounded value from rule.cvss (e.g. let confidence = (rule.cvss /
10.0).clamp(0.0, 1.0) and then call .confidence(confidence as f64)) so
out-of-range CVSS in user rules cannot produce invalid confidence values; update
the code around .cve(&rule.cve) and .confidence((rule.cvss / 10.0) as f64) to
use this clamped value.

.evidence(Evidence::Banner {
raw: banner.chars().take(120).collect::<String>().into(),
})
Expand Down
Loading
Loading