mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
Rust: Implement query.
This commit is contained in:
13
rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml
Normal file
13
rust/ql/lib/codeql/rust/frameworks/sqlx.model.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/rust-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["sqlx_core::query::query", "Argument[0]", "database-store", "manual"]
|
||||
- ["sqlx_core::query_as::query_as", "Argument[0]", "database-store", "manual"]
|
||||
- ["sqlx_core::query_with::query_with", "Argument[0]", "database-store", "manual"]
|
||||
- ["sqlx_core::query_as_with::query_as_with", "Argument[0]", "database-store", "manual"]
|
||||
- ["sqlx_core::query_scalar::query_scalar", "Argument[0]", "database-store", "manual"]
|
||||
- ["sqlx_core::query_scalar_with::query_scalar_with", "Argument[0]", "database-store", "manual"]
|
||||
- ["sqlx_core::raw_sql::raw_sql", "Argument[0]", "database-store", "manual"]
|
||||
- ["<_ as sqlx_core::executor::Executor>::execute", "Argument[0]", "database-store", "manual"]
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about cleartext storage
|
||||
* of sensitive information in a database.
|
||||
*/
|
||||
|
||||
import rust
|
||||
private import codeql.rust.dataflow.DataFlow
|
||||
private import codeql.rust.dataflow.internal.DataFlowImpl
|
||||
private import codeql.rust.security.SensitiveData
|
||||
private import codeql.rust.Concepts
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks and barriers for detecting cleartext storage
|
||||
* of sensitive information in a database, as well as extension points for
|
||||
* adding your own.
|
||||
*/
|
||||
module CleartextStorageDatabase {
|
||||
/**
|
||||
* A data flow source for cleartext storage vulnerabilities.
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for cleartext storage vulnerabilities.
|
||||
*/
|
||||
abstract class Sink extends QuerySink::Range {
|
||||
override string getSinkType() { result = "CleartextStorageDatabase" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A barrier for cleartext storage vulnerabilities.
|
||||
*/
|
||||
abstract class Barrier extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* Sensitive data, considered as a flow source.
|
||||
*/
|
||||
private class SensitiveDataAsSource extends Source instanceof SensitiveData { }
|
||||
|
||||
/**
|
||||
* A sink for cleartext storage vulnerabilities from model data.
|
||||
*/
|
||||
private class ModelsAsDataSink extends Sink {
|
||||
ModelsAsDataSink() { exists(string s | sinkNode(this, s) and s.matches("database-store")) }
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,44 @@
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
import codeql.rust.dataflow.TaintTracking
|
||||
import codeql.rust.security.CleartextStorageDatabaseExtensions
|
||||
|
||||
select 0
|
||||
/**
|
||||
* A taint configuration from sensitive information to expressions that are
|
||||
* stored in a database.
|
||||
*/
|
||||
module CleartextStorageDatabaseConfig implements DataFlow::ConfigSig {
|
||||
import CleartextStorageDatabase
|
||||
|
||||
predicate isSource(DataFlow::Node node) { node instanceof Source }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
|
||||
|
||||
predicate isBarrierIn(DataFlow::Node node) {
|
||||
// make sources barriers so that we only report the closest instance
|
||||
isSource(node)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// flow from `a` to `&a`
|
||||
node2.asExpr().getExpr().(RefExpr).getExpr() = node1.asExpr().getExpr()
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
module CleartextStorageDatabaseFlow = TaintTracking::Global<CleartextStorageDatabaseConfig>;
|
||||
|
||||
import CleartextStorageDatabaseFlow::PathGraph
|
||||
|
||||
from
|
||||
CleartextStorageDatabaseFlow::PathNode sourceNode, CleartextStorageDatabaseFlow::PathNode sinkNode
|
||||
where CleartextStorageDatabaseFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode, sourceNode, sinkNode,
|
||||
"This operation stores '" + sinkNode.toString() +
|
||||
"' in a database. It may contain unencrypted sensitive data from $@.", sourceNode,
|
||||
sourceNode.getNode().toString()
|
||||
|
||||
@@ -1 +1,91 @@
|
||||
| 0 |
|
||||
#select
|
||||
| test_storage.rs:62:13:62:23 | ...::query | test_storage.rs:33:97:33:114 | get_phone_number(...) | test_storage.rs:62:13:62:23 | ...::query | This operation stores '...::query' in a database. It may contain unencrypted sensitive data from $@. | test_storage.rs:33:97:33:114 | get_phone_number(...) | get_phone_number(...) |
|
||||
| test_storage.rs:77:13:77:25 | ...::raw_sql | test_storage.rs:33:97:33:114 | get_phone_number(...) | test_storage.rs:77:13:77:25 | ...::raw_sql | This operation stores '...::raw_sql' in a database. It may contain unencrypted sensitive data from $@. | test_storage.rs:33:97:33:114 | get_phone_number(...) | get_phone_number(...) |
|
||||
| test_storage.rs:81:13:81:23 | ...::query | test_storage.rs:33:97:33:114 | get_phone_number(...) | test_storage.rs:81:13:81:23 | ...::query | This operation stores '...::query' in a database. It may contain unencrypted sensitive data from $@. | test_storage.rs:33:97:33:114 | get_phone_number(...) | get_phone_number(...) |
|
||||
| test_storage.rs:87:13:87:23 | ...::query | test_storage.rs:33:97:33:114 | get_phone_number(...) | test_storage.rs:87:13:87:23 | ...::query | This operation stores '...::query' in a database. It may contain unencrypted sensitive data from $@. | test_storage.rs:33:97:33:114 | get_phone_number(...) | get_phone_number(...) |
|
||||
| test_storage.rs:101:13:101:23 | ...::query | test_storage.rs:33:97:33:114 | get_phone_number(...) | test_storage.rs:101:13:101:23 | ...::query | This operation stores '...::query' in a database. It may contain unencrypted sensitive data from $@. | test_storage.rs:33:97:33:114 | get_phone_number(...) | get_phone_number(...) |
|
||||
edges
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:62:25:62:37 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:62:25:62:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:62:25:62:46 | insert_query2.as_str() | provenance | MaD:4 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:62:25:62:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:77:27:77:39 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:77:27:77:48 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:77:27:77:48 | insert_query2.as_str() | provenance | MaD:4 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:77:27:77:48 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:81:25:81:37 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:81:25:81:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:81:25:81:46 | insert_query2.as_str() | provenance | MaD:4 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:81:25:81:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:87:25:87:37 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:87:25:87:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:87:25:87:46 | insert_query2.as_str() | provenance | MaD:4 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:87:25:87:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:101:25:101:37 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:101:25:101:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:101:25:101:46 | insert_query2.as_str() | provenance | MaD:4 |
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | test_storage.rs:101:25:101:46 | insert_query2.as_str() | provenance | MaD:5 |
|
||||
| test_storage.rs:33:25:33:114 | ... + ... | test_storage.rs:33:9:33:21 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:25:33:114 | ... + ... | test_storage.rs:33:25:33:121 | ... + ... | provenance | MaD:3 |
|
||||
| test_storage.rs:33:25:33:121 | ... + ... | test_storage.rs:33:9:33:21 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:96:33:114 | &... | test_storage.rs:33:9:33:21 | insert_query2 | provenance | |
|
||||
| test_storage.rs:33:96:33:114 | &... | test_storage.rs:33:25:33:114 | ... + ... | provenance | |
|
||||
| test_storage.rs:33:97:33:114 | get_phone_number(...) | test_storage.rs:33:96:33:114 | &... | provenance | Config |
|
||||
| test_storage.rs:62:25:62:37 | insert_query2 | test_storage.rs:62:25:62:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:62:25:62:37 | insert_query2 | test_storage.rs:62:25:62:46 | insert_query2.as_str() [&ref] | provenance | MaD:4 |
|
||||
| test_storage.rs:62:25:62:37 | insert_query2 | test_storage.rs:62:25:62:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:62:25:62:46 | insert_query2.as_str() | test_storage.rs:62:13:62:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| test_storage.rs:62:25:62:46 | insert_query2.as_str() [&ref] | test_storage.rs:62:13:62:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| test_storage.rs:77:27:77:39 | insert_query2 | test_storage.rs:77:27:77:48 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:77:27:77:39 | insert_query2 | test_storage.rs:77:27:77:48 | insert_query2.as_str() [&ref] | provenance | MaD:4 |
|
||||
| test_storage.rs:77:27:77:39 | insert_query2 | test_storage.rs:77:27:77:48 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:77:27:77:48 | insert_query2.as_str() | test_storage.rs:77:13:77:25 | ...::raw_sql | provenance | MaD:2 Sink:MaD:2 |
|
||||
| test_storage.rs:77:27:77:48 | insert_query2.as_str() [&ref] | test_storage.rs:77:13:77:25 | ...::raw_sql | provenance | MaD:2 Sink:MaD:2 |
|
||||
| test_storage.rs:81:25:81:37 | insert_query2 | test_storage.rs:81:25:81:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:81:25:81:37 | insert_query2 | test_storage.rs:81:25:81:46 | insert_query2.as_str() [&ref] | provenance | MaD:4 |
|
||||
| test_storage.rs:81:25:81:37 | insert_query2 | test_storage.rs:81:25:81:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:81:25:81:46 | insert_query2.as_str() | test_storage.rs:81:13:81:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| test_storage.rs:81:25:81:46 | insert_query2.as_str() [&ref] | test_storage.rs:81:13:81:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| test_storage.rs:87:25:87:37 | insert_query2 | test_storage.rs:87:25:87:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:87:25:87:37 | insert_query2 | test_storage.rs:87:25:87:46 | insert_query2.as_str() [&ref] | provenance | MaD:4 |
|
||||
| test_storage.rs:87:25:87:37 | insert_query2 | test_storage.rs:87:25:87:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:87:25:87:46 | insert_query2.as_str() | test_storage.rs:87:13:87:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| test_storage.rs:87:25:87:46 | insert_query2.as_str() [&ref] | test_storage.rs:87:13:87:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| test_storage.rs:101:25:101:37 | insert_query2 | test_storage.rs:101:25:101:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:101:25:101:37 | insert_query2 | test_storage.rs:101:25:101:46 | insert_query2.as_str() [&ref] | provenance | MaD:4 |
|
||||
| test_storage.rs:101:25:101:37 | insert_query2 | test_storage.rs:101:25:101:46 | insert_query2.as_str() [&ref] | provenance | MaD:5 |
|
||||
| test_storage.rs:101:25:101:46 | insert_query2.as_str() | test_storage.rs:101:13:101:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
| test_storage.rs:101:25:101:46 | insert_query2.as_str() [&ref] | test_storage.rs:101:13:101:23 | ...::query | provenance | MaD:1 Sink:MaD:1 |
|
||||
models
|
||||
| 1 | Sink: sqlx_core::query::query; Argument[0]; database-store |
|
||||
| 2 | Sink: sqlx_core::raw_sql::raw_sql; Argument[0]; database-store |
|
||||
| 3 | Summary: <alloc::string::String as core::ops::arith::Add>::add; Argument[self]; ReturnValue; value |
|
||||
| 4 | Summary: <alloc::string::String>::as_str; Argument[self]; ReturnValue; value |
|
||||
| 5 | Summary: <core::str>::as_str; Argument[self]; ReturnValue; value |
|
||||
nodes
|
||||
| test_storage.rs:33:9:33:21 | insert_query2 | semmle.label | insert_query2 |
|
||||
| test_storage.rs:33:25:33:114 | ... + ... | semmle.label | ... + ... |
|
||||
| test_storage.rs:33:25:33:121 | ... + ... | semmle.label | ... + ... |
|
||||
| test_storage.rs:33:96:33:114 | &... | semmle.label | &... |
|
||||
| test_storage.rs:33:97:33:114 | get_phone_number(...) | semmle.label | get_phone_number(...) |
|
||||
| test_storage.rs:62:13:62:23 | ...::query | semmle.label | ...::query |
|
||||
| test_storage.rs:62:25:62:37 | insert_query2 | semmle.label | insert_query2 |
|
||||
| test_storage.rs:62:25:62:46 | insert_query2.as_str() | semmle.label | insert_query2.as_str() |
|
||||
| test_storage.rs:62:25:62:46 | insert_query2.as_str() [&ref] | semmle.label | insert_query2.as_str() [&ref] |
|
||||
| test_storage.rs:77:13:77:25 | ...::raw_sql | semmle.label | ...::raw_sql |
|
||||
| test_storage.rs:77:27:77:39 | insert_query2 | semmle.label | insert_query2 |
|
||||
| test_storage.rs:77:27:77:48 | insert_query2.as_str() | semmle.label | insert_query2.as_str() |
|
||||
| test_storage.rs:77:27:77:48 | insert_query2.as_str() [&ref] | semmle.label | insert_query2.as_str() [&ref] |
|
||||
| test_storage.rs:81:13:81:23 | ...::query | semmle.label | ...::query |
|
||||
| test_storage.rs:81:25:81:37 | insert_query2 | semmle.label | insert_query2 |
|
||||
| test_storage.rs:81:25:81:46 | insert_query2.as_str() | semmle.label | insert_query2.as_str() |
|
||||
| test_storage.rs:81:25:81:46 | insert_query2.as_str() [&ref] | semmle.label | insert_query2.as_str() [&ref] |
|
||||
| test_storage.rs:87:13:87:23 | ...::query | semmle.label | ...::query |
|
||||
| test_storage.rs:87:25:87:37 | insert_query2 | semmle.label | insert_query2 |
|
||||
| test_storage.rs:87:25:87:46 | insert_query2.as_str() | semmle.label | insert_query2.as_str() |
|
||||
| test_storage.rs:87:25:87:46 | insert_query2.as_str() [&ref] | semmle.label | insert_query2.as_str() [&ref] |
|
||||
| test_storage.rs:101:13:101:23 | ...::query | semmle.label | ...::query |
|
||||
| test_storage.rs:101:25:101:37 | insert_query2 | semmle.label | insert_query2 |
|
||||
| test_storage.rs:101:25:101:46 | insert_query2.as_str() | semmle.label | insert_query2.as_str() |
|
||||
| test_storage.rs:101:25:101:46 | insert_query2.as_str() [&ref] | semmle.label | insert_query2.as_str() [&ref] |
|
||||
subpaths
|
||||
|
||||
@@ -30,7 +30,7 @@ async fn test_storage_sql_command(url: &str) -> Result<(), sqlx::Error> {
|
||||
let select_query1 = String::from("SELECT * FROM CONTACTS WHERE ID = ") + id;
|
||||
let select_query2 = String::from("SELECT * FROM CONTACTS WHERE SSN = '") + &get_social_security_number() + "'";
|
||||
let insert_query1 = String::from("INSERT INTO CONTACTS(ID, HARMLESS) VALUES(") + id + ", '" + &get_harmless() + "')";
|
||||
let insert_query2 = String::from("INSERT INTO CONTACTS(ID, PHONE) VALUES(") + id + ", '" + &get_phone_number() + "')";
|
||||
let insert_query2 = String::from("INSERT INTO CONTACTS(ID, PHONE) VALUES(") + id + ", '" + &get_phone_number() + "')"; // $ Source[rust/cleartext-storage-database]
|
||||
let update_query1 = String::from("UPDATE CONTACTS SET HARMLESS='") + &get_harmless() + "' WHERE ID=" + id;
|
||||
let update_query2 = String::from("UPDATE CONTACTS SET EMAIL='") + &get_email() + "' WHERE ID=" + id;
|
||||
let s1 = &get_social_security_number();
|
||||
@@ -59,7 +59,7 @@ async fn test_storage_sql_command(url: &str) -> Result<(), sqlx::Error> {
|
||||
|
||||
// execute queries - MySQL, prepared query
|
||||
let _ = sqlx::query(insert_query1.as_str()).execute(&pool1).await?;
|
||||
let _ = sqlx::query(insert_query2.as_str()).execute(&pool1).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(insert_query2.as_str()).execute(&pool1).await?; // $ Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_harmless()).execute(&pool1).await?;
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_social_security_number()).execute(&pool1).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(&s1).execute(&pool1).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
@@ -74,17 +74,17 @@ async fn test_storage_sql_command(url: &str) -> Result<(), sqlx::Error> {
|
||||
|
||||
// execute queries - SQLite, direct variant
|
||||
let _ = sqlx::raw_sql(insert_query1.as_str()).execute(&mut conn2).await?;
|
||||
let _ = sqlx::raw_sql(insert_query2.as_str()).execute(&mut conn2).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::raw_sql(insert_query2.as_str()).execute(&mut conn2).await?; // $ Alert[rust/cleartext-storage-database]
|
||||
|
||||
// execute queries - SQLite, prepared query
|
||||
let _ = sqlx::query(insert_query1.as_str()).execute(&mut conn2).await?;
|
||||
let _ = sqlx::query(insert_query2.as_str()).execute(&mut conn2).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(insert_query2.as_str()).execute(&mut conn2).await?; // $ Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_harmless()).execute(&mut conn2).await?;
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_social_security_number()).execute(&mut conn2).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
|
||||
// execute queries - SQLite, prepared query variant
|
||||
let _ = sqlx::query(insert_query1.as_str()).fetch(&mut conn2);
|
||||
let _ = sqlx::query(insert_query2.as_str()).fetch(&mut conn2); // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(insert_query2.as_str()).fetch(&mut conn2); // $ Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_harmless()).fetch(&mut conn2);
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_social_security_number()).fetch(&mut conn2); // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
|
||||
@@ -98,7 +98,7 @@ async fn test_storage_sql_command(url: &str) -> Result<(), sqlx::Error> {
|
||||
|
||||
// execute queries - PostgreSQL, prepared query
|
||||
let _ = sqlx::query(insert_query1.as_str()).execute(&pool3).await?;
|
||||
let _ = sqlx::query(insert_query2.as_str()).execute(&pool3).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(insert_query2.as_str()).execute(&pool3).await?; // $ Alert[rust/cleartext-storage-database]
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_harmless()).execute(&pool3).await?;
|
||||
let _ = sqlx::query(prepared_query.as_str()).bind(get_social_security_number()).execute(&pool3).await?; // $ MISSING: Alert[rust/cleartext-storage-database]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user