mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
Add QL test
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
#select
|
||||
| src/main.rs:10:5:10:22 | ...::read_to_string | src/main.rs:6:11:6:19 | file_name | src/main.rs:10:5:10:22 | ...::read_to_string | This path depends on a $@. | src/main.rs:6:11:6:19 | file_name | user-provided value |
|
||||
| src/main.rs:20:5:20:22 | ...::read_to_string | src/main.rs:14:36:14:44 | file_name | src/main.rs:20:5:20:22 | ...::read_to_string | This path depends on a $@. | src/main.rs:14:36:14:44 | file_name | user-provided value |
|
||||
| src/main.rs:45:5:45:22 | ...::read_to_string | src/main.rs:37:11:37:19 | file_path | src/main.rs:45:5:45:22 | ...::read_to_string | This path depends on a $@. | src/main.rs:37:11:37:19 | file_path | user-provided value |
|
||||
edges
|
||||
| src/main.rs:6:11:6:19 | file_name | src/main.rs:8:35:8:43 | file_name | provenance | |
|
||||
| src/main.rs:8:9:8:17 | file_path | src/main.rs:10:24:10:32 | file_path | provenance | |
|
||||
| src/main.rs:8:21:8:44 | ...::from(...) | src/main.rs:8:9:8:17 | file_path | provenance | |
|
||||
| src/main.rs:8:35:8:43 | file_name | src/main.rs:8:21:8:44 | ...::from(...) | provenance | MaD:3 |
|
||||
| src/main.rs:10:24:10:32 | file_path | src/main.rs:10:5:10:22 | ...::read_to_string | provenance | MaD:1 Sink:MaD:1 |
|
||||
| src/main.rs:14:36:14:44 | file_name | src/main.rs:19:35:19:43 | file_name | provenance | |
|
||||
| src/main.rs:19:9:19:17 | file_path | src/main.rs:20:24:20:32 | file_path | provenance | |
|
||||
| src/main.rs:19:21:19:44 | ...::from(...) | src/main.rs:19:9:19:17 | file_path | provenance | |
|
||||
| src/main.rs:19:35:19:43 | file_name | src/main.rs:19:21:19:44 | ...::from(...) | provenance | MaD:3 |
|
||||
| src/main.rs:20:24:20:32 | file_path | src/main.rs:20:5:20:22 | ...::read_to_string | provenance | MaD:1 Sink:MaD:1 |
|
||||
| src/main.rs:37:11:37:19 | file_path | src/main.rs:40:52:40:60 | file_path | provenance | |
|
||||
| src/main.rs:40:9:40:17 | file_path | src/main.rs:45:24:45:32 | file_path | provenance | |
|
||||
| src/main.rs:40:21:40:62 | public_path.join(...) | src/main.rs:40:9:40:17 | file_path | provenance | |
|
||||
| src/main.rs:40:38:40:61 | ...::from(...) | src/main.rs:40:21:40:62 | public_path.join(...) | provenance | MaD:2 |
|
||||
| src/main.rs:40:52:40:60 | file_path | src/main.rs:40:38:40:61 | ...::from(...) | provenance | MaD:3 |
|
||||
| src/main.rs:45:24:45:32 | file_path | src/main.rs:45:5:45:22 | ...::read_to_string | provenance | MaD:1 Sink:MaD:1 |
|
||||
models
|
||||
| 1 | Sink: lang:std; crate::fs::read_to_string; path-injection; Argument[0] |
|
||||
| 2 | Summary: lang:std; <crate::path::Path>::join; Argument[0]; ReturnValue; taint |
|
||||
| 3 | Summary: lang:std; <crate::path::PathBuf as crate::convert::From>::from; Argument[0]; ReturnValue; taint |
|
||||
nodes
|
||||
| src/main.rs:6:11:6:19 | file_name | semmle.label | file_name |
|
||||
| src/main.rs:8:9:8:17 | file_path | semmle.label | file_path |
|
||||
| src/main.rs:8:21:8:44 | ...::from(...) | semmle.label | ...::from(...) |
|
||||
| src/main.rs:8:35:8:43 | file_name | semmle.label | file_name |
|
||||
| src/main.rs:10:5:10:22 | ...::read_to_string | semmle.label | ...::read_to_string |
|
||||
| src/main.rs:10:24:10:32 | file_path | semmle.label | file_path |
|
||||
| src/main.rs:14:36:14:44 | file_name | semmle.label | file_name |
|
||||
| src/main.rs:19:9:19:17 | file_path | semmle.label | file_path |
|
||||
| src/main.rs:19:21:19:44 | ...::from(...) | semmle.label | ...::from(...) |
|
||||
| src/main.rs:19:35:19:43 | file_name | semmle.label | file_name |
|
||||
| src/main.rs:20:5:20:22 | ...::read_to_string | semmle.label | ...::read_to_string |
|
||||
| src/main.rs:20:24:20:32 | file_path | semmle.label | file_path |
|
||||
| src/main.rs:37:11:37:19 | file_path | semmle.label | file_path |
|
||||
| src/main.rs:40:9:40:17 | file_path | semmle.label | file_path |
|
||||
| src/main.rs:40:21:40:62 | public_path.join(...) | semmle.label | public_path.join(...) |
|
||||
| src/main.rs:40:38:40:61 | ...::from(...) | semmle.label | ...::from(...) |
|
||||
| src/main.rs:40:52:40:60 | file_path | semmle.label | file_path |
|
||||
| src/main.rs:45:5:45:22 | ...::read_to_string | semmle.label | ...::read_to_string |
|
||||
| src/main.rs:45:24:45:32 | file_path | semmle.label | file_path |
|
||||
subpaths
|
||||
testFailures
|
||||
| src/main.rs:14:36:14:44 | file_name | Unexpected result: Source |
|
||||
| src/main.rs:20:5:20:22 | ...::read_to_string | Unexpected result: Alert |
|
||||
| src/main.rs:50:38:50:56 | //... | Missing result: Source=remote5 |
|
||||
| src/main.rs:59:64:59:122 | //... | Missing result: Alert[rust/path-injection]=remote5 |
|
||||
@@ -0,0 +1,4 @@
|
||||
query: queries/security/CWE-022/TaintedPath.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -0,0 +1,19 @@
|
||||
import rust
|
||||
import codeql.rust.security.TaintedPathExtensions
|
||||
import utils.test.InlineExpectationsTest
|
||||
|
||||
module TaintedPathSinksTest implements TestSig {
|
||||
string getARelevantTag() { result = "path-injection-sink" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(TaintedPath::Sink sink |
|
||||
location = sink.getLocation() and
|
||||
location.getFile().getBaseName() != "" and
|
||||
element = sink.toString() and
|
||||
tag = "path-injection-sink" and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<TaintedPathSinksTest>
|
||||
3
rust/ql/test/query-tests/security/CWE-022/options.yml
Normal file
3
rust/ql/test/query-tests/security/CWE-022/options.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
qltest_cargo_check: true
|
||||
qltest_dependencies:
|
||||
- poem = { version = "3.1.7" }
|
||||
62
rust/ql/test/query-tests/security/CWE-022/src/main.rs
Normal file
62
rust/ql/test/query-tests/security/CWE-022/src/main.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use poem::{error::InternalServerError, handler, http::StatusCode, web::Query, Error, Result};
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
//#[handler]
|
||||
fn tainted_path_handler_bad(
|
||||
Query(file_name): Query<String>, // $ Source=remote1
|
||||
) -> Result<String> {
|
||||
let file_path = PathBuf::from(file_name);
|
||||
// BAD: This could read any file on the filesystem.
|
||||
fs::read_to_string(file_path).map_err(InternalServerError) // $ path-injection-sink Alert[rust/path-injection]=remote1
|
||||
}
|
||||
|
||||
//#[handler]
|
||||
fn tainted_path_handler_good(Query(file_name): Query<String>) -> Result<String> {
|
||||
// GOOD: ensure that the filename has no path separators or parent directory references
|
||||
if file_name.contains("..") || file_name.contains("/") || file_name.contains("\\") {
|
||||
return Err(Error::from_status(StatusCode::BAD_REQUEST));
|
||||
}
|
||||
let file_path = PathBuf::from(file_name);
|
||||
fs::read_to_string(file_path).map_err(InternalServerError) // $ path-injection-sink
|
||||
}
|
||||
|
||||
//#[handler]
|
||||
fn tainted_path_handler_folder_good(Query(file_path): Query<String>) -> Result<String> {
|
||||
let public_path = PathBuf::from("/var/www/public_html");
|
||||
let file_path = public_path.join(PathBuf::from(file_path));
|
||||
let file_path = file_path.canonicalize().unwrap();
|
||||
// GOOD: ensure that the path stays within the public folder
|
||||
if !file_path.starts_with(public_path) {
|
||||
return Err(Error::from_status(StatusCode::BAD_REQUEST));
|
||||
}
|
||||
fs::read_to_string(file_path).map_err(InternalServerError) // $ path-injection-sink
|
||||
}
|
||||
|
||||
//#[handler]
|
||||
fn tainted_path_handler_folder_almost_good1(
|
||||
Query(file_path): Query<String>, // $ Source=remote4
|
||||
) -> Result<String> {
|
||||
let public_path = PathBuf::from("/var/www/public_html");
|
||||
let file_path = public_path.join(PathBuf::from(file_path));
|
||||
// BAD: the path could still contain `..` and escape the public folder
|
||||
if !file_path.starts_with(public_path) {
|
||||
return Err(Error::from_status(StatusCode::BAD_REQUEST));
|
||||
}
|
||||
fs::read_to_string(file_path).map_err(InternalServerError) // $ path-injection-sink Alert[rust/path-injection]=remote4
|
||||
}
|
||||
|
||||
//#[handler]
|
||||
fn tainted_path_handler_folder_almost_good2(
|
||||
Query(file_path): Query<String>, // $ Source=remote5
|
||||
) -> Result<String> {
|
||||
let public_path = PathBuf::from("/var/www/public_html");
|
||||
let file_path = public_path.join(PathBuf::from(file_path));
|
||||
let file_path = file_path.canonicalize().unwrap();
|
||||
// BAD: the check to ensure that the path stays within the public folder is wrong
|
||||
if file_path.starts_with(public_path) {
|
||||
return Err(Error::from_status(StatusCode::BAD_REQUEST));
|
||||
}
|
||||
fs::read_to_string(file_path).map_err(InternalServerError) // $ path-injection-sink Alert[rust/path-injection]=remote5
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Reference in New Issue
Block a user