Skip to content

Commit 3637595

Browse files
committed
Fix @pattern sanitizer for TaintedPath
1 parent de6f6f9 commit 3637595

3 files changed

Lines changed: 17 additions & 8 deletions

File tree

java/ql/lib/semmle/code/java/security/PathSanitizer.qll

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,12 @@ private class DirectoryCharactersGuard extends PathGuard {
470470
Expr checkedExpr;
471471
boolean branch;
472472

473-
DirectoryCharactersGuard() { isMatchesCall(this, checkedExpr, branch) }
473+
DirectoryCharactersGuard() {
474+
// Annotations are handled directly as barriers in `DirectoryCharactersSanitizer`,
475+
// since they don't dominate the sanitized expression and so can't act as barrier guards.
476+
not this instanceof Annotation and
477+
isMatchesCall(this, checkedExpr, branch)
478+
}
474479

475480
override Expr getCheckedExpr() { result = checkedExpr }
476481

@@ -493,7 +498,15 @@ private predicate directoryCharactersGuard(Guard g, Expr e, boolean branch) {
493498
*/
494499
private class DirectoryCharactersSanitizer extends PathInjectionSanitizer {
495500
DirectoryCharactersSanitizer() {
496-
this.asExpr() instanceof ReplaceDirectoryCharactersSanitizer or
501+
this.asExpr() instanceof ReplaceDirectoryCharactersSanitizer
502+
or
497503
this = DataFlow::BarrierGuard<directoryCharactersGuard/3>::getABarrierNode()
504+
or
505+
// Annotations don't fit into the model of barrier guards because the
506+
// annotation doesn't dominate the sanitized expression, so we instead
507+
// treat them as barriers directly.
508+
exists(RegexMatch rm | rm instanceof Annotation and isMatchesCall(rm, _, true) |
509+
this.asExpr() = rm.getString()
510+
)
498511
}
499512
}

java/ql/test/query-tests/security/CWE-022/semmle/tests/SanitizationTests2.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ public ResponseEntity<String> vulnerablePathInjection(@RequestParam("path") Stri
2121

2222
@GetMapping("/product/vuln/path-injection-fix")
2323
public ResponseEntity<String> vulnerablePathInjectionFix(@RequestParam("path")
24-
@javax.validation.constraints.Pattern(regexp = "[a-zA-Z0-9]*") String path) throws IOException { // $ SPURIOUS: Source
25-
try (FileInputStream stream = new FileInputStream(path)) { // $ SPURIOUS: Alert
24+
@javax.validation.constraints.Pattern(regexp = "[a-zA-Z0-9]*") String path) throws IOException {
25+
try (FileInputStream stream = new FileInputStream(path)) {
2626
byte[] fileContents = stream.readNBytes(1024);
2727
return ResponseEntity.ok(new String(fileContents, StandardCharsets.UTF_8));
2828
}

java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#select
22
| SanitizationTests2.java:16:59:16:62 | path | SanitizationTests2.java:14:59:14:91 | path : String | SanitizationTests2.java:16:59:16:62 | path | This path depends on a $@. | SanitizationTests2.java:14:59:14:91 | path | user-provided value |
3-
| SanitizationTests2.java:25:59:25:62 | path | SanitizationTests2.java:23:62:24:139 | path : String | SanitizationTests2.java:25:59:25:62 | path | This path depends on a $@. | SanitizationTests2.java:23:62:24:139 | path | user-provided value |
43
| TaintedPath.java:16:71:16:78 | filename | TaintedPath.java:13:58:13:78 | getInputStream(...) : InputStream | TaintedPath.java:16:71:16:78 | filename | This path depends on a $@. | TaintedPath.java:13:58:13:78 | getInputStream(...) | user-provided value |
54
| Test.java:37:52:37:68 | (...)... | Test.java:32:16:32:45 | getParameter(...) : String | Test.java:37:52:37:68 | (...)... | This path depends on a $@. | Test.java:32:16:32:45 | getParameter(...) | user-provided value |
65
| Test.java:39:32:39:48 | (...)... | Test.java:32:16:32:45 | getParameter(...) : String | Test.java:39:32:39:48 | (...)... | This path depends on a $@. | Test.java:32:16:32:45 | getParameter(...) | user-provided value |
@@ -80,7 +79,6 @@
8079
| Test.java:204:20:204:36 | (...)... | Test.java:32:16:32:45 | getParameter(...) : String | Test.java:204:20:204:36 | (...)... | This path depends on a $@. | Test.java:32:16:32:45 | getParameter(...) | user-provided value |
8180
edges
8281
| SanitizationTests2.java:14:59:14:91 | path : String | SanitizationTests2.java:16:59:16:62 | path | provenance | Sink:MaD:23 |
83-
| SanitizationTests2.java:23:62:24:139 | path : String | SanitizationTests2.java:25:59:25:62 | path | provenance | Sink:MaD:23 |
8482
| TaintedPath.java:13:17:13:89 | new BufferedReader(...) : BufferedReader | TaintedPath.java:14:27:14:40 | filenameReader : BufferedReader | provenance | |
8583
| TaintedPath.java:13:36:13:88 | new InputStreamReader(...) : InputStreamReader | TaintedPath.java:13:17:13:89 | new BufferedReader(...) : BufferedReader | provenance | MaD:74 |
8684
| TaintedPath.java:13:58:13:78 | getInputStream(...) : InputStream | TaintedPath.java:13:36:13:88 | new InputStreamReader(...) : InputStreamReader | provenance | Src:MaD:72 MaD:76 |
@@ -318,8 +316,6 @@ models
318316
nodes
319317
| SanitizationTests2.java:14:59:14:91 | path : String | semmle.label | path : String |
320318
| SanitizationTests2.java:16:59:16:62 | path | semmle.label | path |
321-
| SanitizationTests2.java:23:62:24:139 | path : String | semmle.label | path : String |
322-
| SanitizationTests2.java:25:59:25:62 | path | semmle.label | path |
323319
| TaintedPath.java:13:17:13:89 | new BufferedReader(...) : BufferedReader | semmle.label | new BufferedReader(...) : BufferedReader |
324320
| TaintedPath.java:13:36:13:88 | new InputStreamReader(...) : InputStreamReader | semmle.label | new InputStreamReader(...) : InputStreamReader |
325321
| TaintedPath.java:13:58:13:78 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |

0 commit comments

Comments
 (0)