Skip to content

Commit 18fbda6

Browse files
committed
chore: add more tests for the path traversal sanitizer
1 parent a536b63 commit 18fbda6

File tree

3 files changed

+300
-0
lines changed

3 files changed

+300
-0
lines changed

sanitizers/src/test/java/com/example/BUILD.bazel

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,71 @@ java_fuzz_target_test(
8888
],
8989
)
9090

91+
[java_fuzz_target_test(
92+
name = "FilePathTraversalPass_" + method,
93+
srcs = [
94+
"FilePathTraversalPass.java",
95+
],
96+
env = {
97+
"JAZZER_FUZZ": "1",
98+
},
99+
fuzzer_args = [
100+
"-runs=0",
101+
],
102+
target_class = "com.example.FilePathTraversalPass",
103+
target_method = method,
104+
verify_crash_reproducer = False,
105+
runtime_deps = [
106+
"@maven//:org_junit_jupiter_junit_jupiter_engine",
107+
],
108+
deps = [
109+
"//deploy:jazzer-junit",
110+
"@maven//:org_junit_jupiter_junit_jupiter_api",
111+
],
112+
) for method in [
113+
"beforeEachWorks",
114+
"overwritingBeforeEachWorks",
115+
"allow",
116+
"targetMissed",
117+
"onion",
118+
]]
119+
120+
[java_fuzz_target_test(
121+
name = "FilePathTraversalCrash_" + method,
122+
srcs = [
123+
"FilePathTraversalCrash.java",
124+
],
125+
allowed_findings = [
126+
"com.code_intelligence.jazzer.api.FuzzerSecurityIssueCritical",
127+
],
128+
env = {
129+
"JAZZER_FUZZ": "1",
130+
},
131+
expect_number_of_findings = 1,
132+
fuzzer_args = [
133+
"-runs=0",
134+
],
135+
target_class = "com.example.FilePathTraversalCrash",
136+
target_method = method,
137+
verify_crash_reproducer = False,
138+
runtime_deps = [
139+
"@maven//:org_junit_jupiter_junit_jupiter_engine",
140+
],
141+
deps = [
142+
"//deploy:jazzer-junit",
143+
"@maven//:org_junit_jupiter_junit_jupiter_api",
144+
],
145+
) for method in [
146+
"beforeEachWorks",
147+
"overwritingBeforeEachWorks",
148+
"crashWhenAllowIsFalse",
149+
"crashWhenDefaultTarget",
150+
"onionTarget",
151+
"cascadedTarget",
152+
"absoluteToRelative",
153+
"relativeToAbsolute",
154+
]]
155+
91156
java_fuzz_target_test(
92157
name = "OsCommandInjectionProcessBuilder",
93158
srcs = [
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright 2025 Code Intelligence GmbH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example;
18+
19+
import com.code_intelligence.jazzer.api.BugDetectors;
20+
import com.code_intelligence.jazzer.api.SilentCloseable;
21+
import com.code_intelligence.jazzer.junit.FuzzTest;
22+
import java.io.FileInputStream;
23+
import java.io.IOException;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
26+
import org.junit.jupiter.api.BeforeEach;
27+
28+
public class FilePathTraversalCrash {
29+
@BeforeEach
30+
public void setUp() {
31+
BugDetectors.setFilePathTraversalTarget(() -> Paths.get("..", "..", "hello"));
32+
}
33+
34+
@FuzzTest
35+
void beforeEachWorks(boolean ignore) throws Exception {
36+
tryPathTraversal("..", "..", "hello");
37+
}
38+
39+
@FuzzTest
40+
void overwritingBeforeEachWorks(boolean ignore) {
41+
try (SilentCloseable unused = setTarget("..", "..", "jazzer-hey")) {
42+
tryPathTraversal("..", "..", "jazzer-hey");
43+
}
44+
}
45+
46+
@FuzzTest
47+
void crashWhenAllowIsFalse(boolean ignore) {
48+
try (SilentCloseable unused = BugDetectors.setFilePathTraversalAllowPath((Path p) -> false)) {
49+
tryPathTraversal("any-path-is-bad");
50+
}
51+
}
52+
53+
@FuzzTest
54+
void crashWhenDefaultTarget(boolean ignore) {
55+
try (SilentCloseable unused = BugDetectors.setFilePathTraversalAllowPath((Path p) -> true)) {
56+
tryPathTraversal("..", "..", "hello");
57+
}
58+
}
59+
60+
@FuzzTest
61+
void onionTarget(boolean ignore) {
62+
try (SilentCloseable unused = setTarget("..", "..", "jazzer-hey")) {
63+
try (SilentCloseable unused1 = setTarget("..", "..", "jazzer-hey1")) {
64+
try (SilentCloseable unused2 = setTarget("..", "..", "jazzer-hey2")) {
65+
tryPathTraversal("..", "..", "jazzer-hey2");
66+
}
67+
}
68+
}
69+
}
70+
71+
@FuzzTest
72+
void cascadedTarget(boolean ignore) {
73+
try (SilentCloseable ignore1 = setTarget("..", "..", "jazzer-hey")) {
74+
// ignore
75+
}
76+
try (SilentCloseable ignore2 = setTarget("..", "..", "jazzer-hey1")) {
77+
// ignore
78+
}
79+
try (SilentCloseable ignore3 = setTarget("..", "..", "jazzer-hey2")) {
80+
tryPathTraversal("..", "..", "jazzer-hey2");
81+
}
82+
}
83+
84+
@FuzzTest
85+
void absoluteToRelative(boolean ignore) {
86+
final Path cwd = Paths.get("").toAbsolutePath();
87+
final Path target = Paths.get("test", "A");
88+
// set absolute target
89+
try (SilentCloseable ignore1 = setTarget(cwd.resolve(target))) {
90+
// try to read relative path
91+
tryPathTraversal(target);
92+
}
93+
}
94+
95+
@FuzzTest
96+
void relativeToAbsolute(boolean ignore) {
97+
final Path cwd = Paths.get("").toAbsolutePath();
98+
final Path target = Paths.get("test", "A");
99+
// set relative target
100+
try (SilentCloseable ignore1 = setTarget(target)) {
101+
// try to read absolute path
102+
tryPathTraversal(cwd.resolve(target));
103+
}
104+
}
105+
106+
private static SilentCloseable setTarget(String first, String... rest) {
107+
return setTarget(Paths.get(first, rest));
108+
}
109+
110+
private static SilentCloseable setTarget(Path p) {
111+
return BugDetectors.setFilePathTraversalTarget(() -> p);
112+
}
113+
114+
private static void tryPathTraversal(String part1, String... rest) {
115+
Path path = Paths.get(part1, rest);
116+
try (FileInputStream fis = new FileInputStream(path.toString())) {
117+
fis.read();
118+
} catch (NullPointerException | IOException ignored) {
119+
}
120+
}
121+
122+
private static void tryPathTraversal(Path path) {
123+
try (FileInputStream fis = new FileInputStream(path.toString())) {
124+
fis.read();
125+
} catch (NullPointerException | IOException ignored) {
126+
}
127+
}
128+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2025 Code Intelligence GmbH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example;
18+
19+
import com.code_intelligence.jazzer.api.BugDetectors;
20+
import com.code_intelligence.jazzer.api.SilentCloseable;
21+
import com.code_intelligence.jazzer.junit.FuzzTest;
22+
import java.io.FileInputStream;
23+
import java.io.IOException;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
26+
import org.junit.jupiter.api.BeforeEach;
27+
28+
public class FilePathTraversalPass {
29+
@BeforeEach
30+
public void setUp() {
31+
setTarget(Paths.get("..", "..", "hello"));
32+
}
33+
34+
@FuzzTest
35+
void beforeEachWorks(boolean ignore) {
36+
tryPathTraversal("test");
37+
}
38+
39+
@FuzzTest
40+
void overwritingBeforeEachWorks(boolean ignore) {
41+
try (SilentCloseable ignore1 = setTarget(Paths.get("..", "..", "jazzer-hey"))) {
42+
tryPathTraversal("..", "..", "hello");
43+
}
44+
}
45+
46+
@FuzzTest
47+
void allow(boolean ignore) {
48+
try (SilentCloseable ignore1 =
49+
BugDetectors.setFilePathTraversalAllowPath((Path p) -> p.toString().contains("secret"))) {
50+
tryPathTraversal("my-secret-file");
51+
}
52+
}
53+
54+
@FuzzTest
55+
void targetMissed(boolean ignore) {
56+
try (SilentCloseable ignore1 =
57+
BugDetectors.setFilePathTraversalAllowPath((Path ignoredAgain) -> true)) {
58+
tryPathTraversal("some-path");
59+
}
60+
}
61+
62+
@FuzzTest
63+
void onion(boolean ignore) {
64+
final Path jazzerHello = Paths.get("..", "..", "hello");
65+
final Path jazzerTest = Paths.get("test");
66+
final Path jazzerHey = Paths.get("..", "..", "jazzer-hey");
67+
final Path jazzerHey1 = Paths.get("..", "..", "jazzer-hey1");
68+
69+
try (SilentCloseable ignored = setTarget(jazzerHey)) {
70+
tryPathTraversal(jazzerHello);
71+
try (SilentCloseable ignored1 = setTarget(jazzerTest)) {
72+
tryPathTraversal(jazzerHey);
73+
try (SilentCloseable ignored2 = setTarget(jazzerHey1)) {
74+
tryPathTraversal(jazzerTest);
75+
}
76+
tryPathTraversal(jazzerHey);
77+
tryPathTraversal(jazzerHey1);
78+
}
79+
tryPathTraversal(jazzerTest);
80+
tryPathTraversal(jazzerHey1);
81+
tryPathTraversal(jazzerHello);
82+
}
83+
}
84+
85+
private static SilentCloseable setTarget(String first, String... rest) {
86+
return setTarget(Paths.get(first, rest));
87+
}
88+
89+
private static SilentCloseable setTarget(Path p) {
90+
return BugDetectors.setFilePathTraversalTarget(() -> p);
91+
}
92+
93+
private static void tryPathTraversal(String first, String... rest) {
94+
Path path = Paths.get(first, rest);
95+
try (FileInputStream fis = new FileInputStream(path.toString())) {
96+
fis.read();
97+
} catch (NullPointerException | IOException ignored) {
98+
}
99+
}
100+
101+
private static void tryPathTraversal(Path path) {
102+
try (FileInputStream fis = new FileInputStream(path.toString())) {
103+
fis.read();
104+
} catch (NullPointerException | IOException ignored) {
105+
}
106+
}
107+
}

0 commit comments

Comments
 (0)