@@ -13,10 +13,10 @@ fn tainted_path_handler_bad(
1313//#[handler]
1414fn tainted_path_handler_good ( Query ( file_name) : Query < String > ) -> Result < String > {
1515 // 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
1717 return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
1818 }
19- let file_path = PathBuf :: from ( file_name) ;
19+ let file_path = PathBuf :: from ( file_name) ; // $ path-injection-barrier (following the last `.contains` check)
2020 fs:: read_to_string ( file_path) . map_err ( InternalServerError ) // $ path-injection-sink
2121}
2222
@@ -29,25 +29,50 @@ fn tainted_path_handler_folder_good(Query(file_path): Query<String>) -> Result<S
2929 if !file_path. starts_with ( public_path) {
3030 return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
3131 }
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
3333}
3434
3535//#[handler]
3636fn tainted_path_handler_folder_almost_good1 (
37- Query ( file_path) : Query < String > , // $ MISSING: Source=remote4
37+ Query ( file_path) : Query < String > , // $ MISSING: Source=remote2
3838) -> Result < String > {
3939 let public_path = PathBuf :: from ( "/var/www/public_html" ) ;
4040 let file_path = public_path. join ( PathBuf :: from ( file_path) ) ;
4141 // BAD: the path could still contain `..` and escape the public folder
4242 if !file_path. starts_with ( public_path) {
4343 return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
4444 }
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
4671}
4772
4873//#[handler]
4974fn tainted_path_handler_folder_almost_good2 (
50- Query ( file_path) : Query < String > , // $ MISSING: Source=remote5
75+ Query ( file_path) : Query < String > , // $ MISSING: Source=remote4
5176) -> Result < String > {
5277 let public_path = PathBuf :: from ( "/var/www/public_html" ) ;
5378 let file_path = public_path. join ( PathBuf :: from ( file_path) ) ;
@@ -56,7 +81,21 @@ fn tainted_path_handler_folder_almost_good2(
5681 if file_path. starts_with ( public_path) {
5782 return Err ( Error :: from_status ( StatusCode :: BAD_REQUEST ) ) ;
5883 }
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
6099}
61100
62101fn sinks ( path1 : & Path , path2 : & Path ) {
0 commit comments