diff --git a/rules/cpp/sizeof-this-cpp.yml b/rules/cpp/sizeof-this-cpp.yml new file mode 100644 index 00000000..3044adf0 --- /dev/null +++ b/rules/cpp/sizeof-this-cpp.yml @@ -0,0 +1,44 @@ +id: sizeof-this-cpp +language: cpp +severity: warning +message: >- + Do not use `sizeof(this)` to get the number of bytes of the object in + memory. It returns the size of the pointer, not the size of the object. +note: >- + [CWE-467]: Use of sizeof() on a Pointer Type + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/ARR01-C.+Do+not+apply+the+sizeof+operator+to+a+pointer+when+taking+the+size+of+an+array +utils: + match_sizeof_this: + kind: sizeof_expression + has: + kind: parenthesized_expression + has: + kind: this + regex: "^this$" + inside: + stopBy: end + kind: return_statement + inside: + kind: compound_statement + follows: + kind: function_declarator + inside: + kind: function_definition + +rule: + kind: sizeof_expression + all: + - has: + stopBy: end + kind: this + - not: + has: + stopBy: end + any: + - nthChild: 2 + - kind: pointer_expression + - kind: ERROR + - kind: sizeof_expression + + 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..25c939bd --- /dev/null +++ b/rules/rust/security/tokio-postgres-empty-password-rust.yml @@ -0,0 +1,248 @@ +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_FOLLOW_1: + follows: + stopBy: end + any: + - kind: let_declaration + all: + - has: + kind: identifier + pattern: $CONFIG + - has: + kind: call_expression + regex: ^tokio_postgres::Config::new\(\)$ + - kind: let_declaration + all: + - has: + kind: identifier + pattern: $CONFIG + - has: + kind: call_expression + regex: ^Config::new\(\)$ + any: + - follows: + stopBy: end + kind: use_declaration + has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config$ + - inside: + stopBy: end + follows: + stopBy: end + kind: use_declaration + has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config$ + + +rule: + kind: call_expression + not: + has: + stopBy: end + kind: ERROR + any: + # CONFIG IS DIRECT AND PWD IS DIRECT + - all: + - has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config::new()$ + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string_literal + not: + has: + kind: string_content + nthChild: 1 + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression + # CONFIG IS DIRECT AND PWD IS INSTANCE + - all: + - has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config::new()$ + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: identifier + pattern: $PASSWORD + inside: + stopBy: end + follows: + stopBy: end + any: + - kind: let_declaration + has: + kind: identifier + pattern: $PASSWORD + precedes: + stopBy: end + kind: string_literal + not: + has: + kind: string_content + - kind: expression_statement + has: + kind: assignment_expression + has: + kind: identifier + pattern: $PASSWORD + precedes: + stopBy: end + kind: string_literal + not: + has: + kind: string_content + + nthChild: 1 + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression + # CONFIG IS INSTANCE AND PWD IS DIRECT + - all: + - has: + stopBy: end + kind: identifier + pattern: $CONFIG + any: + - inside: + stopBy: end + matches: MATCH_FOLLOW_1 + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string_literal + not: + has: + kind: string_content + nthChild: 1 + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression + # CONFIG IS INSTANCE AND PWD IS INSTANCE + - all: + - has: + stopBy: end + kind: identifier + pattern: $CONFIG + any: + - inside: + stopBy: end + matches: MATCH_FOLLOW_1 + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: identifier + pattern: $PASSWORD + nthChild: 1 + inside: + stopBy: end + follows: + stopBy: end + any: + - kind: let_declaration + all: + - has: + kind: identifier + pattern: $PASSWORD + - has: + kind: string_literal + not: + has: + kind: string_content + - kind: expression_statement + has: + kind: assignment_expression + all: + - has: + kind: identifier + pattern: $PASSWORD + - has: + kind: string_literal + not: + has: + kind: string_content + + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression + 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..d7c8d491 --- /dev/null +++ b/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml @@ -0,0 +1,240 @@ +id: tokio-postgres-hardcoded-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_FOLLOW_1: + follows: + stopBy: end + any: + - kind: let_declaration + all: + - has: + kind: identifier + pattern: $CONFIG + - has: + kind: call_expression + regex: ^tokio_postgres::Config::new\(\)$ + - kind: let_declaration + all: + - has: + kind: identifier + pattern: $CONFIG + - has: + kind: call_expression + regex: ^Config::new\(\)$ + any: + - follows: + stopBy: end + kind: use_declaration + has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config$ + - inside: + stopBy: end + follows: + stopBy: end + kind: use_declaration + has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config$ + + +rule: + kind: call_expression + not: + has: + stopBy: end + kind: ERROR + any: + # CONFIG IS DIRECT AND PWD IS DIRECT + - all: + - has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config::new()$ + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string_literal + has: + kind: string_content + nthChild: 1 + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression + # CONFIG IS DIRECT AND PWD IS INSTANCE + - all: + - has: + stopBy: end + kind: scoped_identifier + regex: ^tokio_postgres::Config::new()$ + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: identifier + pattern: $PASSWORD + inside: + stopBy: end + follows: + stopBy: end + any: + - kind: let_declaration + has: + kind: identifier + pattern: $PASSWORD + precedes: + stopBy: end + kind: string_literal + has: + kind: string_content + - kind: expression_statement + has: + kind: assignment_expression + has: + kind: identifier + pattern: $PASSWORD + precedes: + stopBy: end + kind: string_literal + has: + kind: string_content + + nthChild: 1 + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression + # CONFIG IS INSTANCE AND PWD IS DIRECT + - all: + - has: + stopBy: end + kind: identifier + pattern: $CONFIG + any: + - inside: + stopBy: end + matches: MATCH_FOLLOW_1 + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: string_literal + has: + kind: string_content + nthChild: 1 + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression + # CONFIG IS INSTANCE AND PWD IS INSTANCE + - all: + - has: + stopBy: end + kind: identifier + pattern: $CONFIG + any: + - inside: + stopBy: end + matches: MATCH_FOLLOW_1 + - has: + kind: field_expression + regex: \.password$ + nthChild: 1 + - has: + kind: arguments + nthChild: 2 + has: + stopBy: end + kind: identifier + pattern: $PASSWORD + nthChild: 1 + inside: + stopBy: end + follows: + stopBy: end + any: + - kind: let_declaration + all: + - has: + kind: identifier + pattern: $PASSWORD + - has: + kind: string_literal + has: + kind: string_content + - kind: expression_statement + has: + kind: assignment_expression + all: + - has: + kind: identifier + pattern: $PASSWORD + - has: + kind: string_literal + has: + kind: string_content + + all: + - not: + has: + stopBy: end + nthChild: 2 + - not: + has: + stopBy: end + any: + - kind: block + - kind: array_expression diff --git a/tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml b/tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml index a3e9c11c..89c27d11 100644 --- a/tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml +++ b/tests/__snapshots__/cbc-padding-oracle-java-snapshot.yml @@ -1,2 +1,9 @@ id: cbc-padding-oracle-java -snapshots: {} +snapshots: + ? | + Cipher.getInstance("AES/CBC/PKCS5Padding"); + : labels: + - source: Cipher.getInstance("AES/CBC/PKCS5Padding") + style: primary + start: 0 + end: 42 diff --git a/tests/__snapshots__/sizeof-this-cpp-snapshot.yml b/tests/__snapshots__/sizeof-this-cpp-snapshot.yml new file mode 100644 index 00000000..9875c137 --- /dev/null +++ b/tests/__snapshots__/sizeof-this-cpp-snapshot.yml @@ -0,0 +1,2 @@ +id: sizeof-this-cpp +snapshots: {} 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..199a0f9e --- /dev/null +++ b/tests/__snapshots__/tokio-postgres-empty-password-rust-snapshot.yml @@ -0,0 +1,54 @@ +id: tokio-postgres-empty-password-rust +snapshots: + ? |- + async fn okTest2() -> 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) + })?; + + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + + Ok(()) + } + : labels: + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("") + style: primary + start: 79 + end: 184 + - source: tokio_postgres::Config::new + style: secondary + start: 79 + end: 106 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password + style: secondary + start: 79 + end: 180 + - source: '""' + style: secondary + start: 181 + end: 183 + - source: ("") + style: secondary + start: 180 + end: 184 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..211d2a32 --- /dev/null +++ b/tests/__snapshots__/tokio-postgres-hardcoded-password-rust-snapshot.yml @@ -0,0 +1,58 @@ +id: tokio-postgres-hardcoded-password-rust +snapshots: + ? |- + async fn okTest2() -> Result<(), anyhow::Error> { + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("myPassword") + .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); + } + }); + + Ok(()) + } + : labels: + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("myPassword") + style: primary + start: 79 + end: 194 + - source: tokio_postgres::Config::new + style: secondary + start: 79 + end: 106 + - source: |- + tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password + style: secondary + start: 79 + end: 180 + - source: myPassword + style: secondary + start: 182 + end: 192 + - source: '"myPassword"' + style: secondary + start: 181 + end: 193 + - source: ("myPassword") + style: secondary + start: 180 + end: 194 diff --git a/tests/cpp/size-of-this-test.yml b/tests/cpp/size-of-this-test.yml new file mode 100644 index 00000000..343b2a66 --- /dev/null +++ b/tests/cpp/size-of-this-test.yml @@ -0,0 +1,7 @@ +id: sizeof-this-cpp +valid: + - | + return sizeof(*this); +invalid: + - | + return sizeof(this); 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..2b85b2c4 --- /dev/null +++ b/tests/rust/tokio-postgres-empty-password-rust-test.yml @@ -0,0 +1,50 @@ +id: tokio-postgres-empty-password-rust +valid: + - | + async fn okTest2() -> Result<(), anyhow::Error> { + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("postgres") + .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); + } + }); + + Ok(()) + } + +invalid: + - | + async fn okTest2() -> 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) + })?; + + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + + Ok(()) + } \ No newline at end of file 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..895e52e4 --- /dev/null +++ b/tests/rust/tokio-postgres-hardcoded-password-rust-test.yml @@ -0,0 +1,50 @@ +id: tokio-postgres-hardcoded-password-rust +valid: + - | + async fn okTest2() -> 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) + })?; + + tokio::spawn(async move { + if let Err(e) = connection.await { + tracing::error!("postgres db connection error: {}", e); + } + }); + + Ok(()) + } + +invalid: + - | + async fn okTest2() -> Result<(), anyhow::Error> { + let (client, connection) = tokio_postgres::Config::new() + .host(shard_host_name.as_str()) + .user("postgres") + .password("myPassword") + .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); + } + }); + + Ok(()) + } \ No newline at end of file