From ad3a53ac17b413ef5f6e05fba0e369698138fe16 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 5 Dec 2024 17:21:05 +0530 Subject: [PATCH 1/5] secrets-reqwest-hardcoded-auth-rust --- .../secrets-reqwest-hardcoded-auth-rust.yml | 142 +++++++++++++++ ...s-reqwest-hardcoded-auth-rust-snapshot.yml | 164 ++++++++++++++++++ ...crets-reqwest-hardcoded-auth-rust-test.yml | 43 +++++ 3 files changed, 349 insertions(+) create mode 100644 rules/rust/security/secrets-reqwest-hardcoded-auth-rust.yml create mode 100644 tests/__snapshots__/secrets-reqwest-hardcoded-auth-rust-snapshot.yml create mode 100644 tests/rust/secrets-reqwest-hardcoded-auth-rust-test.yml diff --git a/rules/rust/security/secrets-reqwest-hardcoded-auth-rust.yml b/rules/rust/security/secrets-reqwest-hardcoded-auth-rust.yml new file mode 100644 index 00000000..0a084a8e --- /dev/null +++ b/rules/rust/security/secrets-reqwest-hardcoded-auth-rust.yml @@ -0,0 +1,142 @@ +id: secrets-reqwest-hardcoded-auth-rust +language: rust +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. It is + recommended to rotate the secret and retrieve them from a secure secret + vault or Hardware Security Module (HSM), alternatively environment + variables can be used if allowed by your company policy. +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://docs.rs/reqwest/latest/reqwest/ + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures +utils: + MATCH_PATTERN_ONE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: field_identifier + regex: '^basic_auth$' + - has: + stopBy: neighbor + kind: arguments + all: + - has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: '^Some$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + + + - inside: + stopBy: end + kind: let_declaration + follows: + stopBy: end + kind: let_declaration + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: call_expression + pattern: reqwest::Client::new($$$) + + MATCH_PATTERN_TWO: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: field_identifier + regex: '^bearer_auth|basic_auth$' + - inside: + stopBy: end + kind: let_declaration + follows: + stopBy: end + kind: let_declaration + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: call_expression + pattern: reqwest::Client::new($$$) + - has: + stopBy: neighbor + kind: arguments + all: + - has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + - not: + has: + kind: call_expression + + +rule: + kind: call_expression + any: + - matches: MATCH_PATTERN_ONE + - matches: MATCH_PATTERN_TWO + + diff --git a/tests/__snapshots__/secrets-reqwest-hardcoded-auth-rust-snapshot.yml b/tests/__snapshots__/secrets-reqwest-hardcoded-auth-rust-snapshot.yml new file mode 100644 index 00000000..3959a392 --- /dev/null +++ b/tests/__snapshots__/secrets-reqwest-hardcoded-auth-rust-snapshot.yml @@ -0,0 +1,164 @@ +id: secrets-reqwest-hardcoded-auth-rust +snapshots: + ? | + async fn test1() -> Result<(), reqwest::Error> { + let client = reqwest::Client::new(); + let resp = client.delete("http://httpbin.org/delete") + .basic_auth("admin", Some("hardcoded-password")) + .send() + .await?; + println!("body = {:?}", resp); + Ok(()) + } + : labels: + - source: |- + client.delete("http://httpbin.org/delete") + .basic_auth("admin", Some("hardcoded-password")) + style: primary + start: 97 + end: 188 + - source: client + style: secondary + start: 97 + end: 103 + - source: client.delete + style: secondary + start: 97 + end: 110 + - source: client.delete("http://httpbin.org/delete") + style: secondary + start: 97 + end: 139 + - source: basic_auth + style: secondary + start: 141 + end: 151 + - source: |- + client.delete("http://httpbin.org/delete") + .basic_auth + style: secondary + start: 97 + end: 151 + - source: admin + style: secondary + start: 153 + end: 158 + - source: '"admin"' + style: secondary + start: 152 + end: 159 + - source: Some + style: secondary + start: 161 + end: 165 + - source: hardcoded-password + style: secondary + start: 167 + end: 185 + - source: '"hardcoded-password"' + style: secondary + start: 166 + end: 186 + - source: ("hardcoded-password") + style: secondary + start: 165 + end: 187 + - source: Some("hardcoded-password") + style: secondary + start: 161 + end: 187 + - source: ("admin", Some("hardcoded-password")) + style: secondary + start: 151 + end: 188 + - source: client + style: secondary + start: 53 + end: 59 + - source: reqwest::Client::new() + style: secondary + start: 62 + end: 84 + - source: let client = reqwest::Client::new(); + style: secondary + start: 49 + end: 85 + - source: |- + let resp = client.delete("http://httpbin.org/delete") + .basic_auth("admin", Some("hardcoded-password")) + .send() + .await?; + style: secondary + start: 86 + end: 205 + ? | + async fn test2() -> Result<(), reqwest::Error> { + let client = reqwest::Client::new(); + let resp = client.put("http://httpbin.org/delete") + .bearer_auth("hardcoded-token") + .send() + .await?; + println!("body = {:?}", resp); + Ok(()) + } + : labels: + - source: |- + client.put("http://httpbin.org/delete") + .bearer_auth("hardcoded-token") + style: primary + start: 97 + end: 168 + - source: client + style: secondary + start: 97 + end: 103 + - source: client.put + style: secondary + start: 97 + end: 107 + - source: client.put("http://httpbin.org/delete") + style: secondary + start: 97 + end: 136 + - source: bearer_auth + style: secondary + start: 138 + end: 149 + - source: |- + client.put("http://httpbin.org/delete") + .bearer_auth + style: secondary + start: 97 + end: 149 + - source: client + style: secondary + start: 53 + end: 59 + - source: reqwest::Client::new() + style: secondary + start: 62 + end: 84 + - source: let client = reqwest::Client::new(); + style: secondary + start: 49 + end: 85 + - source: |- + let resp = client.put("http://httpbin.org/delete") + .bearer_auth("hardcoded-token") + .send() + .await?; + style: secondary + start: 86 + end: 185 + - source: hardcoded-token + style: secondary + start: 151 + end: 166 + - source: '"hardcoded-token"' + style: secondary + start: 150 + end: 167 + - source: ("hardcoded-token") + style: secondary + start: 149 + end: 168 diff --git a/tests/rust/secrets-reqwest-hardcoded-auth-rust-test.yml b/tests/rust/secrets-reqwest-hardcoded-auth-rust-test.yml new file mode 100644 index 00000000..84dad42e --- /dev/null +++ b/tests/rust/secrets-reqwest-hardcoded-auth-rust-test.yml @@ -0,0 +1,43 @@ +id: secrets-reqwest-hardcoded-auth-rust +valid: + - | + async fn test1(pass: &str) -> Result<(), reqwest::Error> { + let client = reqwest::Client::new(); + let resp = client.delete("http://httpbin.org/delete") + .basic_auth("admin", Some(pass)) + .send() + .await?; + println!("body = {:?}", resp); + Ok(()) + } + - | + async fn test3() -> Result<(), reqwest::Error> { + let client = reqwest::Client::new(); + let resp = client.post("http://httpbin.org/post") + .bearer_auth("user", Some("hardcoded-password-123")) + .send() + .await?; + println!("body = {:?}", resp); + Ok(()) + } +invalid: + - | + async fn test1() -> Result<(), reqwest::Error> { + let client = reqwest::Client::new(); + let resp = client.delete("http://httpbin.org/delete") + .basic_auth("admin", Some("hardcoded-password")) + .send() + .await?; + println!("body = {:?}", resp); + Ok(()) + } + - | + async fn test2() -> Result<(), reqwest::Error> { + let client = reqwest::Client::new(); + let resp = client.put("http://httpbin.org/delete") + .bearer_auth("hardcoded-token") + .send() + .await?; + println!("body = {:?}", resp); + Ok(()) + } From bfdec53faef7ff356be7fe453637e4244a59058e Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 5 Dec 2024 17:22:25 +0530 Subject: [PATCH 2/5] tokio-postgres-empty-password-rust --- .../tokio-postgres-empty-password-rust.yml | 290 +++++++++++ ...-postgres-empty-password-rust-snapshot.yml | 457 ++++++++++++++++++ ...okio-postgres-empty-password-rust-test.yml | 79 +++ 3 files changed, 826 insertions(+) create mode 100644 rules/rust/security/tokio-postgres-empty-password-rust.yml create mode 100644 tests/__snapshots__/tokio-postgres-empty-password-rust-snapshot.yml create mode 100644 tests/rust/tokio-postgres-empty-password-rust-test.yml diff --git a/rules/rust/security/tokio-postgres-empty-password-rust.yml b/rules/rust/security/tokio-postgres-empty-password-rust.yml new file mode 100644 index 00000000..8cd65cf5 --- /dev/null +++ b/rules/rust/security/tokio-postgres-empty-password-rust.yml @@ -0,0 +1,290 @@ +id: tokio-postgres-empty-password-rust +language: rust +severity: warning +message: >- + The application uses an empty credential. This can lead to unauthorized + access by either an internal or external malicious actor. It is + recommended to rotate the secret and retrieve them from a secure secret + vault or Hardware Security Module (HSM), alternatively environment + variables can be used if allowed by your company policy. +note: >- + [CWE-287] Improper Authentication. + [REFERENCES] + - https://docs.rs/tokio-postgres/latest/tokio_postgres/ + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures +utils: + MATCH_PATTERN_WITH_INSTANCE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: "^password$" + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string_literal + not: + has: + stopBy: neighbor + kind: string_content + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: let_declaration + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: call_expression + pattern: tokio_postgres::Config::new() + + MATCH_PASSWORD_DIRECTLY: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + has: + stopBy: neighbor + kind: call_expression + pattern: tokio_postgres::Config::new() + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: '^password$' + - has: + stopBy: end + kind: arguments + has: + stopBy: end + kind: string_literal + not: + has: + stopBy: neighbor + kind: string_content + + MATCH_PATTERN_PASSWORD_WITH_ITS_INSTANCE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + has: + stopBy: neighbor + kind: call_expression + pattern: tokio_postgres::Config::new() + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: '^password$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: identifier + pattern: $E + - inside: + stopBy: end + kind: let_declaration + follows: + stopby: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: end + kind: identifier + pattern: $E + - has: + stopBy: end + kind: string_literal + not: + has: + stopBy: end + kind: string_content + + MATCH_PATTERN_WITH_INSTANCE_&_PASSWORD_WITH_ITS_INSTANCE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: "^password$" + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: identifier + pattern: $Z + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: let_declaration + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: call_expression + pattern: tokio_postgres::Config::new() + - inside: + stopBy: end + kind: block + has: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $Z + - has: + stopBy: neighbor + kind: string_literal + not: + has: + stopBy: neighbor + kind: string_content + +rule: + kind: call_expression + any: + - matches: MATCH_PATTERN_WITH_INSTANCE + - matches: MATCH_PASSWORD_DIRECTLY + - matches: MATCH_PATTERN_PASSWORD_WITH_ITS_INSTANCE + - matches: MATCH_PATTERN_WITH_INSTANCE_&_PASSWORD_WITH_ITS_INSTANCE \ No newline at end of file diff --git a/tests/__snapshots__/tokio-postgres-empty-password-rust-snapshot.yml b/tests/__snapshots__/tokio-postgres-empty-password-rust-snapshot.yml new file mode 100644 index 00000000..710d553c --- /dev/null +++ b/tests/__snapshots__/tokio-postgres-empty-password-rust-snapshot.yml @@ -0,0 +1,457 @@ +id: tokio-postgres-empty-password-rust +snapshots: + ? | + async fn test1() -> Result<(), anyhow::Error> { + let mut config = tokio_postgres::Config::new(); + as = ""; + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + let (client, connection) = config.connect(NoTls).await?; + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + Ok(()) + } + : labels: + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + style: primary + start: 105 + end: 224 + - source: config + style: secondary + start: 105 + end: 111 + - source: |- + config + .host + style: secondary + start: 105 + end: 118 + - source: (std::env::var("HOST").expect("set HOST")) + style: secondary + start: 118 + end: 160 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + style: secondary + start: 105 + end: 160 + - source: user + style: secondary + start: 163 + end: 167 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user + style: secondary + start: 105 + end: 167 + - source: (std::env::var("USER").expect("set USER")) + style: secondary + start: 167 + end: 209 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + style: secondary + start: 105 + end: 209 + - source: password + style: secondary + start: 212 + end: 220 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password + style: secondary + start: 105 + end: 220 + - source: as + style: secondary + start: 221 + end: 223 + - source: (as) + style: secondary + start: 220 + end: 224 + - source: config + style: secondary + start: 56 + end: 62 + - source: tokio_postgres::Config::new() + style: secondary + start: 65 + end: 94 + - source: let mut config = tokio_postgres::Config::new(); + style: secondary + start: 48 + end: 95 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + style: secondary + start: 105 + end: 274 + - source: as + style: secondary + start: 96 + end: 98 + - source: '""' + style: secondary + start: 101 + end: 103 + - source: as = "" + style: secondary + start: 96 + end: 103 + - source: as = ""; + style: secondary + start: 96 + end: 104 + - source: |- + { + let mut config = tokio_postgres::Config::new(); + as = ""; + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + let (client, connection) = config.connect(NoTls).await?; + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + Ok(()) + } + style: secondary + start: 46 + end: 466 + ? | + async fn test1() -> Result<(), anyhow::Error> { + let mut config = tokio_postgres::Config::new(); + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("") + .port(std::env::var("PORT").expect("set PORT")); + Ok(()) + } + : labels: + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("") + style: primary + start: 96 + end: 212 + - source: config + style: secondary + start: 96 + end: 102 + - source: |- + config + .host + style: secondary + start: 96 + end: 108 + - source: (std::env::var("HOST").expect("set HOST")) + style: secondary + start: 108 + end: 150 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + style: secondary + start: 96 + end: 150 + - source: user + style: secondary + start: 152 + end: 156 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user + style: secondary + start: 96 + end: 156 + - source: (std::env::var("USER").expect("set USER")) + style: secondary + start: 156 + end: 198 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + style: secondary + start: 96 + end: 198 + - source: password + style: secondary + start: 200 + end: 208 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password + style: secondary + start: 96 + end: 208 + - source: '""' + style: secondary + start: 209 + end: 211 + - source: ("") + style: secondary + start: 208 + end: 212 + - source: config + style: secondary + start: 56 + end: 62 + - source: tokio_postgres::Config::new() + style: secondary + start: 65 + end: 94 + - source: let mut config = tokio_postgres::Config::new(); + style: secondary + start: 48 + end: 95 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("") + .port(std::env::var("PORT").expect("set PORT")); + style: secondary + start: 96 + end: 261 + ? | + async fn test2() -> Result<(), anyhow::Error> { + as = ""; + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(as) + .dbname("ninja") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls) + .await + .map_err(|e| { + error!(log, "failed to connect to {}: {}", &shard_host_name, e); + Error::new(ErrorKind::Other, e) + })?; + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + : labels: + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(as) + style: primary + start: 84 + end: 177 + - source: tokio_postgres::Config::new() + style: secondary + start: 84 + end: 113 + - source: |- + tokio_postgres::Config::new() + .host + style: secondary + start: 84 + end: 119 + - source: (shard_host_name.as_str()) + style: secondary + start: 119 + end: 145 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + style: secondary + start: 84 + end: 145 + - source: user + style: secondary + start: 147 + end: 151 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user + style: secondary + start: 84 + end: 151 + - source: ("postgres") + style: secondary + start: 151 + end: 163 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + style: secondary + start: 84 + end: 163 + - source: password + style: secondary + start: 165 + end: 173 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password + style: secondary + start: 84 + end: 173 + - source: as + style: secondary + start: 174 + end: 176 + - source: (as) + style: secondary + start: 173 + end: 177 + - source: as + style: secondary + start: 48 + end: 50 + - source: '""' + style: secondary + start: 53 + end: 55 + - source: as = "" + style: secondary + start: 48 + end: 55 + - source: as = ""; + style: secondary + start: 48 + end: 56 + - source: |- + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(as) + .dbname("ninja") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls) + .await + .map_err(|e| { + error!(log, "failed to connect to {}: {}", &shard_host_name, e); + Error::new(ErrorKind::Other, e) + })?; + style: secondary + start: 57 + end: 393 + ? |- + async fn test2() -> Result<(), anyhow::Error> { + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("") + .dbname("ninja") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls) + .await + .map_err(|e| { + error!(log, "failed to connect to {}: {}", &shard_host_name, e); + Error::new(ErrorKind::Other, e) + })?; + : labels: + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("") + style: primary + start: 75 + end: 168 + - source: tokio_postgres::Config::new() + style: secondary + start: 75 + end: 104 + - source: |- + tokio_postgres::Config::new() + .host + style: secondary + start: 75 + end: 110 + - source: (shard_host_name.as_str()) + style: secondary + start: 110 + end: 136 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + style: secondary + start: 75 + end: 136 + - source: user + style: secondary + start: 138 + end: 142 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user + style: secondary + start: 75 + end: 142 + - source: ("postgres") + style: secondary + start: 142 + end: 154 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + style: secondary + start: 75 + end: 154 + - source: password + style: secondary + start: 156 + end: 164 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password + style: secondary + start: 75 + end: 164 + - source: '""' + style: secondary + start: 165 + end: 167 + - source: ("") + style: secondary + start: 164 + end: 168 diff --git a/tests/rust/tokio-postgres-empty-password-rust-test.yml b/tests/rust/tokio-postgres-empty-password-rust-test.yml new file mode 100644 index 00000000..fe118ccf --- /dev/null +++ b/tests/rust/tokio-postgres-empty-password-rust-test.yml @@ -0,0 +1,79 @@ +id: tokio-postgres-empty-password-rust +valid: + - | + let mut config = tokio_postgres::Config::new(); + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(std::env::var("PASSWORD").expect("set PASSWORD")) + .port(std::env::var("PORT").expect("set PORT")); + let (client, connection) = config.connect(NoTls).await?; + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + Ok(()) + } +invalid: + - | + async fn test1() -> Result<(), anyhow::Error> { + let mut config = tokio_postgres::Config::new(); + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("") + .port(std::env::var("PORT").expect("set PORT")); + Ok(()) + } + - | + async fn test1() -> Result<(), anyhow::Error> { + let mut config = tokio_postgres::Config::new(); + as = ""; + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + let (client, connection) = config.connect(NoTls).await?; + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + Ok(()) + } + - | + async fn test2() -> Result<(), anyhow::Error> { + as = ""; + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(as) + .dbname("ninja") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls) + .await + .map_err(|e| { + error!(log, "failed to connect to {}: {}", &shard_host_name, e); + Error::new(ErrorKind::Other, e) + })?; + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + - | + async fn test2() -> Result<(), anyhow::Error> { + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("") + .dbname("ninja") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls) + .await + .map_err(|e| { + error!(log, "failed to connect to {}: {}", &shard_host_name, e); + Error::new(ErrorKind::Other, e) + })?; \ No newline at end of file From 339ec6223d6f5c158d8ffad699b549dc4e39c08b Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Thu, 5 Dec 2024 17:23:35 +0530 Subject: [PATCH 3/5] tokio-postgres-hardcoded-password-rust --- ...tokio-postgres-hardcoded-password-rust.yml | 287 +++++++++++ ...tgres-hardcoded-password-rust-snapshot.yml | 452 ++++++++++++++++++ ...-postgres-hardcoded-password-rust-test.yml | 59 +++ 3 files changed, 798 insertions(+) create mode 100644 rules/rust/security/tokio-postgres-hardcoded-password-rust.yml create mode 100644 tests/__snapshots__/tokio-postgres-hardcoded-password-rust-snapshot.yml create mode 100644 tests/rust/tokio-postgres-hardcoded-password-rust-test.yml diff --git a/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml b/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml new file mode 100644 index 00000000..5aa5ee38 --- /dev/null +++ b/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml @@ -0,0 +1,287 @@ +id: tokio-postgres-hardcoded-password-rust +language: rust +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. It is + recommended to rotate the secret and retrieve them from a secure secret + vault or Hardware Security Module (HSM), alternatively environment + variables can be used if allowed by your company policy. +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://docs.rs/tokio-postgres/latest/tokio_postgres/ + - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures +utils: + MATCH_PATTERN_WITH_INSTANCE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: "^password$" + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: let_declaration + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: call_expression + pattern: postgres::Config::new() + + MATCH_PASSWORD_DIRECTLY: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + has: + stopBy: neighbor + kind: call_expression + pattern: postgres::Config::new() + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: '^password$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + + MATCH_PATTERN_PASSWORD_WITH_ITS_INSTANCE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + has: + stopBy: neighbor + kind: call_expression + pattern: postgres::Config::new() + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: '^password$' + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: identifier + pattern: $E + - inside: + stopBy: end + kind: block + has: + stopby: end + kind: expression_statement + has: + stopBy: end + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $E + - has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + + MATCH_PATTERN_WITH_INSTANCE_&_PASSWORD_WITH_ITS_INSTANCE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: field_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + - has: + stopBy: neighbor + kind: arguments + - has: + stopBy: neighbor + kind: field_identifier + regex: "^password$" + - has: + stopBy: neighbor + kind: arguments + has: + stopBy: neighbor + kind: identifier + pattern: $Z + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: let_declaration + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $C + - has: + stopBy: neighbor + kind: call_expression + pattern: postgres::Config::new() + - inside: + stopBy: end + kind: block + has: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $Z + - has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + +rule: + kind: call_expression + any: + - matches: MATCH_PATTERN_WITH_INSTANCE + - matches: MATCH_PASSWORD_DIRECTLY + - matches: MATCH_PATTERN_PASSWORD_WITH_ITS_INSTANCE + - matches: MATCH_PATTERN_WITH_INSTANCE_&_PASSWORD_WITH_ITS_INSTANCE \ No newline at end of file diff --git a/tests/__snapshots__/tokio-postgres-hardcoded-password-rust-snapshot.yml b/tests/__snapshots__/tokio-postgres-hardcoded-password-rust-snapshot.yml new file mode 100644 index 00000000..d3e4f995 --- /dev/null +++ b/tests/__snapshots__/tokio-postgres-hardcoded-password-rust-snapshot.yml @@ -0,0 +1,452 @@ +id: tokio-postgres-hardcoded-password-rust +snapshots: + ? | + fn test1() { + let mut config = postgres::Config::new(); + as = "hardcoded-password"; + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + let client = config.connect(NoTls).unwrap(); + Ok(()) + } + : labels: + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + style: primary + start: 82 + end: 201 + - source: config + style: secondary + start: 82 + end: 88 + - source: |- + config + .host + style: secondary + start: 82 + end: 95 + - source: (std::env::var("HOST").expect("set HOST")) + style: secondary + start: 95 + end: 137 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + style: secondary + start: 82 + end: 137 + - source: user + style: secondary + start: 140 + end: 144 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user + style: secondary + start: 82 + end: 144 + - source: (std::env::var("USER").expect("set USER")) + style: secondary + start: 144 + end: 186 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + style: secondary + start: 82 + end: 186 + - source: password + style: secondary + start: 189 + end: 197 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password + style: secondary + start: 82 + end: 197 + - source: as + style: secondary + start: 198 + end: 200 + - source: (as) + style: secondary + start: 197 + end: 201 + - source: config + style: secondary + start: 21 + end: 27 + - source: postgres::Config::new() + style: secondary + start: 30 + end: 53 + - source: let mut config = postgres::Config::new(); + style: secondary + start: 13 + end: 54 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + style: secondary + start: 82 + end: 251 + - source: as + style: secondary + start: 55 + end: 57 + - source: hardcoded-password + style: secondary + start: 61 + end: 79 + - source: '"hardcoded-password"' + style: secondary + start: 60 + end: 80 + - source: as = "hardcoded-password" + style: secondary + start: 55 + end: 80 + - source: as = "hardcoded-password"; + style: secondary + start: 55 + end: 81 + - source: |- + { + let mut config = postgres::Config::new(); + as = "hardcoded-password"; + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + let client = config.connect(NoTls).unwrap(); + Ok(()) + } + style: secondary + start: 11 + end: 305 + ? | + fn test1() { + let mut config = postgres::Config::new(); + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("hardcoded-password") + .port(std::env::var("PORT").expect("set PORT")); + let client = config.connect(NoTls).unwrap(); + Ok(()) + } + : labels: + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("hardcoded-password") + style: primary + start: 55 + end: 192 + - source: config + style: secondary + start: 55 + end: 61 + - source: |- + config + .host + style: secondary + start: 55 + end: 68 + - source: (std::env::var("HOST").expect("set HOST")) + style: secondary + start: 68 + end: 110 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + style: secondary + start: 55 + end: 110 + - source: user + style: secondary + start: 113 + end: 117 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user + style: secondary + start: 55 + end: 117 + - source: (std::env::var("USER").expect("set USER")) + style: secondary + start: 117 + end: 159 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + style: secondary + start: 55 + end: 159 + - source: password + style: secondary + start: 162 + end: 170 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password + style: secondary + start: 55 + end: 170 + - source: hardcoded-password + style: secondary + start: 172 + end: 190 + - source: '"hardcoded-password"' + style: secondary + start: 171 + end: 191 + - source: ("hardcoded-password") + style: secondary + start: 170 + end: 192 + - source: config + style: secondary + start: 21 + end: 27 + - source: postgres::Config::new() + style: secondary + start: 30 + end: 53 + - source: let mut config = postgres::Config::new(); + style: secondary + start: 13 + end: 54 + - source: |- + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("hardcoded-password") + .port(std::env::var("PORT").expect("set PORT")); + style: secondary + start: 55 + end: 242 + ? | + fn test2() { + asa = "cvsdgsdvvbdfbd"; + let (client, connection) = postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(asa) + .dbname("moray") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls); + Ok(()) + } + : labels: + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(asa) + style: primary + start: 64 + end: 152 + - source: postgres::Config::new() + style: secondary + start: 64 + end: 87 + - source: |- + postgres::Config::new() + .host + style: secondary + start: 64 + end: 93 + - source: (shard_host_name.as_str()) + style: secondary + start: 93 + end: 119 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + style: secondary + start: 64 + end: 119 + - source: user + style: secondary + start: 121 + end: 125 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user + style: secondary + start: 64 + end: 125 + - source: ("postgres") + style: secondary + start: 125 + end: 137 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + style: secondary + start: 64 + end: 137 + - source: password + style: secondary + start: 139 + end: 147 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password + style: secondary + start: 64 + end: 147 + - source: asa + style: secondary + start: 148 + end: 151 + - source: (asa) + style: secondary + start: 147 + end: 152 + - source: asa + style: secondary + start: 13 + end: 16 + - source: cvsdgsdvvbdfbd + style: secondary + start: 20 + end: 34 + - source: '"cvsdgsdvvbdfbd"' + style: secondary + start: 19 + end: 35 + - source: asa = "cvsdgsdvvbdfbd" + style: secondary + start: 13 + end: 35 + - source: asa = "cvsdgsdvvbdfbd"; + style: secondary + start: 13 + end: 36 + - source: |- + { + asa = "cvsdgsdvvbdfbd"; + let (client, connection) = postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(asa) + .dbname("moray") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls); + Ok(()) + } + style: secondary + start: 11 + end: 248 + ? |- + fn test2() { + let (client, connection) = postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("hardcoded-password") + .dbname("moray") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls); + Ok(()) + } + : labels: + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("hardcoded-password") + style: primary + start: 40 + end: 145 + - source: postgres::Config::new() + style: secondary + start: 40 + end: 63 + - source: |- + postgres::Config::new() + .host + style: secondary + start: 40 + end: 69 + - source: (shard_host_name.as_str()) + style: secondary + start: 69 + end: 95 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + style: secondary + start: 40 + end: 95 + - source: user + style: secondary + start: 97 + end: 101 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user + style: secondary + start: 40 + end: 101 + - source: ("postgres") + style: secondary + start: 101 + end: 113 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + style: secondary + start: 40 + end: 113 + - source: password + style: secondary + start: 115 + end: 123 + - source: |- + postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password + style: secondary + start: 40 + end: 123 + - source: hardcoded-password + style: secondary + start: 125 + end: 143 + - source: '"hardcoded-password"' + style: secondary + start: 124 + end: 144 + - source: ("hardcoded-password") + style: secondary + start: 123 + end: 145 diff --git a/tests/rust/tokio-postgres-hardcoded-password-rust-test.yml b/tests/rust/tokio-postgres-hardcoded-password-rust-test.yml new file mode 100644 index 00000000..faa5af06 --- /dev/null +++ b/tests/rust/tokio-postgres-hardcoded-password-rust-test.yml @@ -0,0 +1,59 @@ +id: tokio-postgres-hardcoded-password-rust +valid: + - | + async fn test1() -> Result<(), anyhow::Error> { + let mut config = tokio_postgres::Config::new(); + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("") + .port(std::env::var("PORT").expect("set PORT")); + Ok(()) + } +invalid: + - | + fn test1() { + let mut config = postgres::Config::new(); + as = "hardcoded-password"; + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password(as) + .port(std::env::var("PORT").expect("set PORT")); + let client = config.connect(NoTls).unwrap(); + Ok(()) + } + - | + fn test2() { + asa = "cvsdgsdvvbdfbd"; + let (client, connection) = postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password(asa) + .dbname("moray") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls); + Ok(()) + } + - | + fn test1() { + let mut config = postgres::Config::new(); + config + .host(std::env::var("HOST").expect("set HOST")) + .user(std::env::var("USER").expect("set USER")) + .password("hardcoded-password") + .port(std::env::var("PORT").expect("set PORT")); + let client = config.connect(NoTls).unwrap(); + Ok(()) + } + - | + fn test2() { + let (client, connection) = postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("hardcoded-password") + .dbname("moray") + .keepalives_idle(std::time::Duration::from_secs(30)) + .connect(NoTls); + Ok(()) + } \ No newline at end of file From db972e77d4d8b852e10940374da388a04baad025 Mon Sep 17 00:00:00 2001 From: ESS ENN Date: Fri, 13 Dec 2024 10:59:18 +0530 Subject: [PATCH 4/5] Changed tokio-postgres-hardcoded-password-rust --- rules/rust/security/tokio-postgres-hardcoded-password-rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml b/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml index 5aa5ee38..be145527 100644 --- a/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml +++ b/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml @@ -13,6 +13,7 @@ note: >- [REFERENCES] - https://docs.rs/tokio-postgres/latest/tokio_postgres/ - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures + utils: MATCH_PATTERN_WITH_INSTANCE: kind: call_expression From 8cc8cd66aae53a20336922d54c180bfebf066854 Mon Sep 17 00:00:00 2001 From: ESS ENN Date: Fri, 13 Dec 2024 11:10:37 +0530 Subject: [PATCH 5/5] Changed tokio-postgres-hardcoded-password-rust again --- .../tokio-postgres-hardcoded-password-rust.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml b/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml index be145527..5ba7d4ec 100644 --- a/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml +++ b/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml @@ -78,7 +78,7 @@ utils: - has: stopBy: neighbor kind: call_expression - pattern: postgres::Config::new() + pattern: tokio_postgres::Config::new() MATCH_PASSWORD_DIRECTLY: kind: call_expression @@ -105,7 +105,7 @@ utils: has: stopBy: neighbor kind: call_expression - pattern: postgres::Config::new() + pattern: tokio_postgres::Config::new() - has: stopBy: neighbor kind: arguments @@ -154,7 +154,7 @@ utils: has: stopBy: neighbor kind: call_expression - pattern: postgres::Config::new() + pattern: tokio_postgres::Config::new() - has: stopBy: neighbor kind: arguments @@ -257,7 +257,7 @@ utils: - has: stopBy: neighbor kind: call_expression - pattern: postgres::Config::new() + pattern: tokio_tokio_postgres::Config::new() - inside: stopBy: end kind: block @@ -285,4 +285,4 @@ rule: - matches: MATCH_PATTERN_WITH_INSTANCE - matches: MATCH_PASSWORD_DIRECTLY - matches: MATCH_PATTERN_PASSWORD_WITH_ITS_INSTANCE - - matches: MATCH_PATTERN_WITH_INSTANCE_&_PASSWORD_WITH_ITS_INSTANCE \ No newline at end of file + - matches: MATCH_PATTERN_WITH_INSTANCE_&_PASSWORD_WITH_ITS_INSTANCE