Skip to content

Commit bb70473

Browse files
committed
style: cargo fmt
none
1 parent b3ef87b commit bb70473

8 files changed

Lines changed: 117 additions & 112 deletions

File tree

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use clap::Parser;
22
use foxguard::cli::{Cli, OutputFormat};
33
use foxguard::engine::scan_directory;
4-
use foxguard::rules::RuleRegistry;
54
use foxguard::rules::semgrep_compat::load_semgrep_rules;
5+
use foxguard::rules::RuleRegistry;
66
use std::path::Path;
77

88
fn main() {

src/report/sarif.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ pub fn print_sarif(findings: &[Finding]) {
77
.map(|f| {
88
let mut props = serde_json::Map::new();
99
if let Some(cwe) = &f.cwe {
10-
props.insert(
11-
"tags".to_string(),
12-
json!([cwe]),
13-
);
10+
props.insert("tags".to_string(), json!([cwe]));
1411
}
1512

1613
json!({

src/rules/go.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,8 @@ impl Rule for NoSqlInjection {
7171

7272
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
7373
let mut findings = Vec::new();
74-
let sql_pattern = Regex::new(
75-
r"(?i)(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC)\s"
76-
)
77-
.unwrap();
74+
let sql_pattern =
75+
Regex::new(r"(?i)(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC)\s").unwrap();
7876

7977
walk_tree(tree.root_node(), source, &mut |node, src| {
8078
// Detect: "SELECT ... WHERE id = " + userId (binary_expression with +)
@@ -211,10 +209,9 @@ impl Rule for NoHardcodedSecret {
211209

212210
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
213211
let mut findings = Vec::new();
214-
let secret_pattern = Regex::new(
215-
r"(?i)(password|secret|api_?key|token|auth|credential|private_?key)"
216-
)
217-
.unwrap();
212+
let secret_pattern =
213+
Regex::new(r"(?i)(password|secret|api_?key|token|auth|credential|private_?key)")
214+
.unwrap();
218215

219216
walk_tree(tree.root_node(), source, &mut |node, src| {
220217
// Short variable declaration: password := "hardcoded"

src/rules/javascript.rs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,9 @@ impl Rule for NoHardcodedSecret {
117117

118118
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
119119
let mut findings = Vec::new();
120-
let secret_pattern = Regex::new(
121-
r"(?i)(password|secret|api_?key|token|auth|credential|private_?key)"
122-
)
123-
.unwrap();
120+
let secret_pattern =
121+
Regex::new(r"(?i)(password|secret|api_?key|token|auth|credential|private_?key)")
122+
.unwrap();
124123

125124
walk_tree(tree.root_node(), source, &mut |node, src| {
126125
// variable_declarator: const password = "hardcoded"
@@ -211,10 +210,8 @@ impl Rule for NoSqlInjection {
211210

212211
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
213212
let mut findings = Vec::new();
214-
let sql_pattern = Regex::new(
215-
r"(?i)(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC)\s"
216-
)
217-
.unwrap();
213+
let sql_pattern =
214+
Regex::new(r"(?i)(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC)\s").unwrap();
218215

219216
walk_tree(tree.root_node(), source, &mut |node, src| {
220217
// Detect: query("SELECT * FROM users WHERE id = " + userId)
@@ -346,7 +343,14 @@ impl Rule for NoCommandInjection {
346343

347344
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
348345
let mut findings = Vec::new();
349-
let dangerous_fns = ["exec", "execSync", "spawn", "spawnSync", "execFile", "execFileSync"];
346+
let dangerous_fns = [
347+
"exec",
348+
"execSync",
349+
"spawn",
350+
"spawnSync",
351+
"execFile",
352+
"execFileSync",
353+
];
350354

351355
walk_tree(tree.root_node(), source, &mut |node, src| {
352356
if node.kind() == "call_expression" {
@@ -578,9 +582,18 @@ impl Rule for NoPathTraversal {
578582
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
579583
let mut findings = Vec::new();
580584
let fs_fns = [
581-
"readFile", "readFileSync", "writeFile", "writeFileSync",
582-
"readdir", "readdirSync", "unlink", "unlinkSync",
583-
"stat", "statSync", "access", "accessSync",
585+
"readFile",
586+
"readFileSync",
587+
"writeFile",
588+
"writeFileSync",
589+
"readdir",
590+
"readdirSync",
591+
"unlink",
592+
"unlinkSync",
593+
"stat",
594+
"statSync",
595+
"access",
596+
"accessSync",
584597
];
585598

586599
walk_tree(tree.root_node(), source, &mut |node, src| {
@@ -694,9 +707,8 @@ impl Rule for NoUnsafeRegex {
694707
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
695708
let mut findings = Vec::new();
696709
// Patterns known to cause catastrophic backtracking: nested quantifiers
697-
let dangerous_pattern = Regex::new(
698-
r"(\([^)]*[+*][^)]*\)[+*]|\([^)]*\|[^)]*\)[+*])"
699-
).unwrap();
710+
let dangerous_pattern =
711+
Regex::new(r"(\([^)]*[+*][^)]*\)[+*]|\([^)]*\|[^)]*\)[+*])").unwrap();
700712

701713
walk_tree(tree.root_node(), source, &mut |node, src| {
702714
// Detect regex literals: /pattern/
@@ -835,7 +847,10 @@ impl Rule for ExpressCookieNoSecure {
835847
let key_inner = key_text.trim_matches(|c| c == '"' || c == '\'');
836848
if key_inner == "cookie" && value.kind() == "object" {
837849
let obj_text = &src[value.byte_range()];
838-
if !obj_text.contains("secure") || obj_text.contains("secure: false") || obj_text.contains("secure:false") {
850+
if !obj_text.contains("secure")
851+
|| obj_text.contains("secure: false")
852+
|| obj_text.contains("secure:false")
853+
{
839854
findings.push(make_finding(
840855
self.id(),
841856
self.severity(),
@@ -886,7 +901,10 @@ impl Rule for ExpressCookieNoHttpOnly {
886901
let key_inner = key_text.trim_matches(|c| c == '"' || c == '\'');
887902
if key_inner == "cookie" && value.kind() == "object" {
888903
let obj_text = &src[value.byte_range()];
889-
if !obj_text.contains("httpOnly") || obj_text.contains("httpOnly: false") || obj_text.contains("httpOnly:false") {
904+
if !obj_text.contains("httpOnly")
905+
|| obj_text.contains("httpOnly: false")
906+
|| obj_text.contains("httpOnly:false")
907+
{
890908
findings.push(make_finding(
891909
self.id(),
892910
self.severity(),
@@ -927,9 +945,7 @@ impl Rule for ExpressDirectResponseWrite {
927945

928946
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
929947
let mut findings = Vec::new();
930-
let user_input_pattern = Regex::new(
931-
r"req\.(params|query|body|headers)"
932-
).unwrap();
948+
let user_input_pattern = Regex::new(r"req\.(params|query|body|headers)").unwrap();
933949

934950
walk_tree(tree.root_node(), source, &mut |node, src| {
935951
// Detect: res.send(req.query.foo), res.write(req.body.bar)
@@ -1008,9 +1024,9 @@ impl Rule for NoCorsStar {
10081024
header_name.trim_matches(|c| c == '"' || c == '\'');
10091025
let val_inner =
10101026
header_val.trim_matches(|c| c == '"' || c == '\'');
1011-
if name_inner.eq_ignore_ascii_case(
1012-
"Access-Control-Allow-Origin",
1013-
) && val_inner == "*"
1027+
if name_inner
1028+
.eq_ignore_ascii_case("Access-Control-Allow-Origin")
1029+
&& val_inner == "*"
10141030
{
10151031
findings.push(make_finding(
10161032
self.id(),

src/rules/python.rs

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,9 @@ impl Rule for NoHardcodedSecret {
119119

120120
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
121121
let mut findings = Vec::new();
122-
let secret_pattern = Regex::new(
123-
r"(?i)(password|secret|api_?key|token|auth|credential|private_?key)"
124-
)
125-
.unwrap();
122+
let secret_pattern =
123+
Regex::new(r"(?i)(password|secret|api_?key|token|auth|credential|private_?key)")
124+
.unwrap();
126125

127126
walk_tree(tree.root_node(), source, &mut |node, src| {
128127
// assignment: password = "hardcoded"
@@ -183,16 +182,18 @@ impl Rule for NoSqlInjection {
183182

184183
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
185184
let mut findings = Vec::new();
186-
let sql_pattern = Regex::new(
187-
r"(?i)(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC)\s"
188-
)
189-
.unwrap();
185+
let sql_pattern =
186+
Regex::new(r"(?i)(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC)\s").unwrap();
190187

191188
walk_tree(tree.root_node(), source, &mut |node, src| {
192189
// Detect f-strings with SQL: f"SELECT * FROM users WHERE id = {user_id}"
193190
if node.kind() == "string" {
194191
let text = &src[node.byte_range()];
195-
if (text.starts_with("f\"") || text.starts_with("f'") || text.starts_with("f\"\"\"")) && sql_pattern.is_match(text) {
192+
if (text.starts_with("f\"")
193+
|| text.starts_with("f'")
194+
|| text.starts_with("f\"\"\""))
195+
&& sql_pattern.is_match(text)
196+
{
196197
findings.push(make_finding(
197198
self.id(),
198199
self.severity(),
@@ -305,8 +306,13 @@ impl Rule for NoCommandInjection {
305306
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
306307
let mut findings = Vec::new();
307308
let dangerous_fns = [
308-
"os.system", "os.popen", "subprocess.call", "subprocess.run",
309-
"subprocess.Popen", "subprocess.check_output", "subprocess.check_call",
309+
"os.system",
310+
"os.popen",
311+
"subprocess.call",
312+
"subprocess.run",
313+
"subprocess.Popen",
314+
"subprocess.check_output",
315+
"subprocess.check_call",
310316
];
311317

312318
walk_tree(tree.root_node(), source, &mut |node, src| {
@@ -322,7 +328,9 @@ impl Rule for NoCommandInjection {
322328
let text = &src[first_arg.byte_range()];
323329
text.starts_with("f\"") || text.starts_with("f'")
324330
}
325-
"concatenated_string" | "binary_operator" | "identifier"
331+
"concatenated_string"
332+
| "binary_operator"
333+
| "identifier"
326334
| "call" => true,
327335
_ => false,
328336
};
@@ -382,7 +390,9 @@ impl Rule for NoPathTraversal {
382390
if let Some(first_arg) = args.named_child(0) {
383391
// Flag if path uses concatenation or f-string
384392
let is_dynamic = match first_arg.kind() {
385-
"binary_operator" | "concatenated_string" | "identifier" => true,
393+
"binary_operator" | "concatenated_string" | "identifier" => {
394+
true
395+
}
386396
"string" => {
387397
let text = &src[first_arg.byte_range()];
388398
text.starts_with("f\"") || text.starts_with("f'")
@@ -438,7 +448,11 @@ impl Rule for NoWeakCrypto {
438448
if let Some(func) = node.child_by_field_name("function") {
439449
let func_text = &src[func.byte_range()];
440450
if func_text == "hashlib.md5" || func_text == "hashlib.sha1" {
441-
let algo = if func_text.contains("md5") { "MD5" } else { "SHA1" };
451+
let algo = if func_text.contains("md5") {
452+
"MD5"
453+
} else {
454+
"SHA1"
455+
};
442456
findings.push(make_finding(
443457
self.id(),
444458
self.severity(),
@@ -506,7 +520,12 @@ impl Rule for NoPickle {
506520

507521
fn check(&self, source: &str, tree: &tree_sitter::Tree) -> Vec<Finding> {
508522
let mut findings = Vec::new();
509-
let dangerous_fns = ["pickle.loads", "pickle.load", "cPickle.loads", "cPickle.load"];
523+
let dangerous_fns = [
524+
"pickle.loads",
525+
"pickle.load",
526+
"cPickle.loads",
527+
"cPickle.load",
528+
];
510529

511530
walk_tree(tree.root_node(), source, &mut |node, src| {
512531
if node.kind() == "call" {
@@ -690,7 +709,9 @@ impl Rule for FlaskDebugMode {
690709
if &src[attr.byte_range()] == "run" {
691710
if let Some(args) = node.child_by_field_name("arguments") {
692711
let args_text = &src[args.byte_range()];
693-
if args_text.contains("debug=True") || args_text.contains("debug = True") {
712+
if args_text.contains("debug=True")
713+
|| args_text.contains("debug = True")
714+
{
694715
findings.push(make_finding(
695716
self.id(),
696717
self.severity(),
@@ -892,10 +913,7 @@ impl Rule for NoCorsStar {
892913
self.id(),
893914
self.severity(),
894915
self.cwe(),
895-
&format!(
896-
"{} = True — restrict CORS to specific origins",
897-
left_text
898-
),
916+
&format!("{} = True — restrict CORS to specific origins", left_text),
899917
node,
900918
src,
901919
));

0 commit comments

Comments
 (0)