Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
60 changes: 60 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ globset = "0.4"
tempfile = "3"
ratatui = "0.30"
crossterm = "0.28"
toml = "0.8"

[[bin]]
name = "foxguard-mcp"
Expand Down
20 changes: 17 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,9 +493,23 @@ fn validate_rules_path(rules: Option<&str>) -> Result<(), String> {

/// Returns `true` if the rule ID belongs to the PQ audit rule set.
fn is_pq_rule_id(id: &str) -> bool {
id.contains("pq-vulnerable")
|| id.contains("hardcoded-crypto-algorithm")
|| (id.starts_with("config/") && id.contains("tls"))
matches!(
id,
"py/pq-vulnerable-crypto"
| "js/pq-vulnerable-crypto"
| "go/pq-vulnerable-crypto"
| "java/pq-vulnerable-crypto"
| "rs/pq-vulnerable-crypto"
| "config/nginx-pq-vulnerable-tls"
| "config/apache-pq-vulnerable-tls"
| "config/haproxy-pq-vulnerable-tls"
| "config/dockerfile-insecure-tls-env"
| "manifest/cargo-pq-vulnerable-dep"
| "manifest/pip-pq-vulnerable-dep"
| "py/hardcoded-crypto-algorithm"
| "js/hardcoded-crypto-algorithm"
| "java/hardcoded-crypto-algorithm"
)
}

fn collect_changed_targets(path: &str, changed: bool) -> Result<Option<Vec<PathBuf>>, String> {
Expand Down
1 change: 1 addition & 0 deletions src/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ mod tests {
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/bin/gen_rules_ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const LANGUAGE_ORDER: &[Language] = &[
Language::ApacheConf,
Language::HAProxyConf,
Language::Dockerfile,
Language::Manifest,
];

fn language_slug(language: Language) -> &'static str {
Expand All @@ -47,6 +48,7 @@ fn language_slug(language: Language) -> &'static str {
Language::ApacheConf => "apacheconf",
Language::HAProxyConf => "haproxyconf",
Language::Dockerfile => "dockerfile",
Language::Manifest => "manifest",
}
}

Expand All @@ -66,6 +68,7 @@ fn language_display_name(language: Language) -> &'static str {
Language::ApacheConf => "Apache",
Language::HAProxyConf => "HAProxy",
Language::Dockerfile => "Dockerfile",
Language::Manifest => "Manifest",
}
}

Expand All @@ -85,6 +88,7 @@ fn language_array_name(language: Language) -> &'static str {
Language::ApacheConf => "apacheconfRules",
Language::HAProxyConf => "haproxyconfRules",
Language::Dockerfile => "dockerfileRules",
Language::Manifest => "manifestRules",
}
}

Expand Down
1 change: 1 addition & 0 deletions src/compliance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ mod tests {
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: deadline.map(String::from),
dep_name: None,
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,7 @@ mod tests {
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
};

let (config_path, added) =
Expand Down Expand Up @@ -1303,6 +1304,7 @@ mod tests {
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
}
}

Expand Down
1 change: 1 addition & 0 deletions src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ mod tests {
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/engine/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ pub fn parse_file(source: &str, language: Language) -> Option<tree_sitter::Tree>
Language::NginxConf
| Language::ApacheConf
| Language::HAProxyConf
| Language::Dockerfile => tree_sitter_bash::LANGUAGE.into(),
| Language::Dockerfile
| Language::Manifest => tree_sitter_bash::LANGUAGE.into(),
Comment on lines +21 to +22
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Language::Manifest routed to Bash tree-sitter grammar unnecessarily

Both CargoLockPqCrypto and RequirementsTxtPqCrypto accept _tree: &tree_sitter::Tree and never use it — they parse the source directly with the toml crate or by iterating over lines. Routing Language::Manifest through tree_sitter_bash::LANGUAGE therefore parses valid TOML (Cargo.lock) and pip syntax as Bash, producing a parse tree that is silently discarded. This wastes CPU time on every manifest scan and may emit confusing error-level log lines from tree-sitter if it encounters Cargo.lock syntax it can't parse as Bash.

Consider returning None early from parse_file for Language::Manifest, or making the tree-sitter step optional for languages that don't need it.

};

parser.set_language(&ts_language).ok()?;
Expand Down
4 changes: 3 additions & 1 deletion src/engine/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ fn detect_config_language(path: &Path) -> Option<Language> {
"nginx.conf" => return Some(Language::NginxConf),
"httpd.conf" | "apache2.conf" => return Some(Language::ApacheConf),
"haproxy.cfg" => return Some(Language::HAProxyConf),
"Cargo.lock" | "requirements.txt" => return Some(Language::Manifest),
_ => {}
}

Expand Down Expand Up @@ -492,7 +493,8 @@ fn comment_markers(language: Language) -> &'static [&'static str] {
Language::NginxConf
| Language::ApacheConf
| Language::HAProxyConf
| Language::Dockerfile => &["#"],
| Language::Dockerfile
| Language::Manifest => &["#"],
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub enum Language {
ApacheConf,
HAProxyConf,
Dockerfile,
Manifest,
}

impl std::fmt::Display for Language {
Expand All @@ -70,6 +71,7 @@ impl std::fmt::Display for Language {
Language::ApacheConf => write!(f, "apacheconf"),
Language::HAProxyConf => write!(f, "haproxyconf"),
Language::Dockerfile => write!(f, "dockerfile"),
Language::Manifest => write!(f, "manifest"),
}
}
}
Expand Down Expand Up @@ -129,4 +131,8 @@ pub struct Finding {
/// compliance module after scanning. `None` for non-crypto findings.
#[serde(skip_serializing_if = "Option::is_none")]
pub cnsa2_deadline: Option<String>,
/// Dependency name for manifest-level findings (e.g. "rustls", "paramiko").
/// `None` for source-level rules.
#[serde(skip_serializing_if = "Option::is_none")]
pub dep_name: Option<String>,
}
2 changes: 2 additions & 0 deletions src/report/cbom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ mod tests {
tags: vec!["PQ".to_string()],
crypto_algorithm: Some(algo.to_string()),
cnsa2_deadline: None,
dep_name: None,
}
}

Expand Down Expand Up @@ -382,6 +383,7 @@ mod tests {
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
}];

let groups: BTreeMap<String, Vec<&Finding>> = findings
Expand Down
1 change: 1 addition & 0 deletions src/report/github_pr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ mod tests {
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/rules/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ pub fn make_finding(
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
}
}

Expand Down Expand Up @@ -281,6 +282,7 @@ pub fn make_finding_from_offsets(
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/rules/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ fn map_go_taint_findings(
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
})
.collect()
}
Expand Down Expand Up @@ -1602,6 +1603,7 @@ pub fn run_go_taint_batched(
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
})
})
.collect()
Expand Down
2 changes: 2 additions & 0 deletions src/rules/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,7 @@ fn map_js_taint_findings(
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
})
.collect()
}
Expand Down Expand Up @@ -2931,6 +2932,7 @@ pub fn run_js_taint_batched(
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
})
})
.collect()
Expand Down
1 change: 1 addition & 0 deletions src/rules/kotlin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,7 @@ fn run_kt_taint(
tags: vec![],
crypto_algorithm: None,
cnsa2_deadline: None,
dep_name: None,
});
}
}
Expand Down
Loading
Loading