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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ members = [
"crates/scanr-sca",
"crates/scanr-cli",
"crates/scanr-engine",
"crates/scanr-container",
]
resolver = "2"
1 change: 1 addition & 0 deletions crates/scanr-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ categories = ["command-line-utilities", "development-tools"]
clap = { version = "4.5", features = ["derive"] }
crossterm = "0.28"
ratatui = "0.28"
scanr-container = { version = "0.1.1", path = "../scanr-container" }
scanr-engine = { version = "0.1.1", path = "../scanr-engine" }
scanr-sca = { version = "0.1.1", path = "../scanr-sca" }
serde = { version = "1.0", features = ["derive"] }
Expand Down
22 changes: 22 additions & 0 deletions crates/scanr-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::path::PathBuf;
use std::process;

use clap::{Parser, Subcommand};
use scanr_engine::ScanEngine;
use serde::Serialize;

mod tui;
Expand Down Expand Up @@ -53,6 +54,11 @@ enum Commands {
#[arg(short, long)]
recursive: bool,
},
/// Scan a container image target (engine skeleton).
Image {
/// Image target (for example: ghcr.io/org/app:latest).
target: String,
},
/// Software bill of materials operations.
Sbom {
#[command(subcommand)]
Expand Down Expand Up @@ -558,6 +564,22 @@ async fn main() {
process::exit(final_ci_exit_code);
}
}
Some(Commands::Image { target }) => {
let container_engine = scanr_container::ContainerEngine::new();
let result = match container_engine.scan(scanr_engine::ScanInput::Image(target)) {
Ok(result) => result,
Err(error) => {
eprintln!("Image scan failed: {error}");
process::exit(1);
}
};

println!("Scanr Container Scan");
println!("Engine: {}", result.metadata.engine_name);
println!("Target: {}", result.metadata.target);
println!("Status: placeholder implementation (C1 skeleton)");
println!("Findings: {}", result.findings.len());
}
Some(Commands::Sbom { command }) => match command {
SbomCommands::Generate { path, output } => {
match scanr_sca::generate_cyclonedx_sbom(&path) {
Expand Down
15 changes: 15 additions & 0 deletions crates/scanr-container/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "scanr-container"
version = "0.1.1"
edition = "2024"
description = "Container security engine for Scanr"
license = "Apache-2.0"
repository = "https://github.com/Open-Lab-s/Scanr"
homepage = "https://scanr.dev"
readme = "../../README.md"
keywords = ["security", "devsecops", "container", "vulnerability", "scanr"]
categories = ["development-tools"]

[dependencies]
scanr-engine = { version = "0.1.1", path = "../scanr-engine" }
scanr-sca = { version = "0.1.1", path = "../scanr-sca" }
41 changes: 41 additions & 0 deletions crates/scanr-container/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use scanr_engine::{EngineType, ScanEngine, ScanInput, ScanMetadata, ScanResult};
use scanr_sca::ScaEngine;

#[derive(Debug, Default, Clone)]
pub struct ContainerEngine {
pub sca_engine: ScaEngine,
}

impl ContainerEngine {
pub fn new() -> Self {
Self {
sca_engine: ScaEngine::new(),
}
}
}

impl ScanEngine for ContainerEngine {
fn name(&self) -> &'static str {
"container"
}

fn scan(&self, input: ScanInput) -> scanr_engine::EngineResult<ScanResult> {
let target = match input {
ScanInput::Image(image) => image,
ScanInput::Tar(path) | ScanInput::Path(path) => path.display().to_string(),
};

let _ = &self.sca_engine;

Ok(ScanResult {
findings: Vec::new(),
metadata: ScanMetadata {
engine: EngineType::Container,
engine_name: self.name().to_string(),
target,
total_dependencies: 0,
total_vulnerabilities: 0,
},
})
}
}
Loading