@@ -13,10 +13,10 @@ fn tainted_path_handler_bad(
13
13
//#[handler]
14
14
fn tainted_path_handler_good ( Query ( file_name) : Query < String > ) -> Result < String > {
15
15
// GOOD: ensure that the filename has no path separators or parent directory references
16
- if file_name. contains ( ".." ) || file_name. contains ( "/" ) || file_name. contains ( "\\ " ) {
16
+ if file_name. contains ( ".." ) || file_name. contains ( "/" ) || file_name. contains ( "\\ " ) { // $ path-injection-barrier
17
17
return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
18
18
}
19
- let file_path = PathBuf :: from ( file_name) ;
19
+ let file_path = PathBuf :: from ( file_name) ; // $ path-injection-barrier (following the last `.contains` check)
20
20
fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink
21
21
}
22
22
@@ -29,25 +29,50 @@ fn tainted_path_handler_folder_good(Query(file_path): Query<String>) -> Result<S
29
29
if !file_path. starts_with ( public_path) {
30
30
return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
31
31
}
32
- fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink
32
+ fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink MISSING: path-injection-checked
33
33
}
34
34
35
35
//#[handler]
36
36
fn tainted_path_handler_folder_almost_good1 (
37
- Query ( file_path) : Query < String > , // $ MISSING: Source=remote4
37
+ Query ( file_path) : Query < String > , // $ MISSING: Source=remote2
38
38
) -> Result < String > {
39
39
let public_path = PathBuf :: from ( "/var/www/public_html" ) ;
40
40
let file_path = public_path. join ( PathBuf :: from ( file_path) ) ;
41
41
// BAD: the path could still contain `..` and escape the public folder
42
42
if !file_path. starts_with ( public_path) {
43
43
return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
44
44
}
45
- fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink MISSING: Alert[rust/path-injection]=remote4 -- we cannot resolve the `join` call above, because it needs a `PathBuf -> Path` `Deref`
45
+ fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink MISSING: path-injection-checked Alert[rust/path-injection]=remote2 -- we cannot resolve the `join` call above, because it needs a `PathBuf -> Path` `Deref`
46
+ }
47
+
48
+ //#[handler]
49
+ fn tainted_path_handler_folder_good_simpler ( Query ( file_path) : Query < String > ) -> Result < String > {
50
+ let public_path = "/var/www/public_html" ;
51
+ let file_path = Path :: new ( & file_path) ;
52
+ let file_path = file_path. canonicalize ( ) . unwrap ( ) ;
53
+ // GOOD: ensure that the path stays within the public folder
54
+ if !file_path. starts_with ( public_path) {
55
+ return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
56
+ }
57
+ fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink MISSING: path-injection-checked
58
+ }
59
+
60
+ //#[handler]
61
+ fn tainted_path_handler_folder_almost_good1_simpler (
62
+ Query ( file_path) : Query < String > , // $ MISSING: Source=remote3
63
+ ) -> Result < String > {
64
+ let public_path = "/var/www/public_html" ;
65
+ let file_path = Path :: new ( & file_path) ;
66
+ // BAD: the path could still contain `..` and escape the public folder
67
+ if !file_path. starts_with ( public_path) {
68
+ return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
69
+ }
70
+ fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-checked path-injection-sink MISSING: Alert[rust/path-injection]=remote3
46
71
}
47
72
48
73
//#[handler]
49
74
fn tainted_path_handler_folder_almost_good2 (
50
- Query ( file_path) : Query < String > , // $ MISSING: Source=remote5
75
+ Query ( file_path) : Query < String > , // $ MISSING: Source=remote4
51
76
) -> Result < String > {
52
77
let public_path = PathBuf :: from ( "/var/www/public_html" ) ;
53
78
let file_path = public_path. join ( PathBuf :: from ( file_path) ) ;
@@ -56,7 +81,21 @@ fn tainted_path_handler_folder_almost_good2(
56
81
if file_path. starts_with ( public_path) {
57
82
return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
58
83
}
59
- fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink MISSING: Alert[rust/path-injection]=remote5 -- we cannot resolve the `join` call above, because it needs a `PathBuf -> Path` `Deref`
84
+ fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink MISSING: path-injection-checked Alert[rust/path-injection]=remote4 -- we cannot resolve the `join` call above, because it needs a `PathBuf -> Path` `Deref`
85
+ }
86
+
87
+ //#[handler]
88
+ fn tainted_path_handler_folder_almost_good3 (
89
+ Query ( file_path) : Query < String > , // $ MISSING: Source=remote5
90
+ ) -> Result < String > {
91
+ let public_path = "/var/www/public_html" ;
92
+ let file_path = Path :: new ( & file_path) ;
93
+ // BAD: the starts_with check is ineffective before canonicalization, the path could still contain `..`
94
+ if !file_path. starts_with ( public_path) {
95
+ return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
96
+ }
97
+ let file_path = file_path. canonicalize ( ) . unwrap ( ) ; // $ path-injection-checked
98
+ fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink MISSING: Alert[rust/path-injection]=remote5
60
99
}
61
100
62
101
fn sinks ( path1 : & Path , path2 : & Path ) {
0 commit comments