Skip to content

Commit 26b37ad

Browse files
committed
Correct Micronaut cookie and map coverage
1 parent 6ac1a72 commit 26b37ad

5 files changed

Lines changed: 54 additions & 14 deletions

File tree

java/ql/test/library-tests/frameworks/micronaut/MicronautControllerTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import io.micronaut.http.annotation.*;
22
import io.micronaut.http.*;
33
import io.micronaut.http.cookie.Cookies;
4+
import io.micronaut.http.cookie.Cookie;
45
import java.io.InputStream;
56
import java.io.Reader;
67

@@ -72,6 +73,10 @@ void testHttpParameters(HttpParameters parameters) {
7273
@Get("/cookies")
7374
void testCookies(Cookies cookies) {
7475
sink(cookies); // $hasTaintFlow
76+
sink(cookies.getValue("session")); // $hasTaintFlow
77+
for (java.util.Map.Entry<String, Cookie> entry : cookies) {
78+
sink(entry.getValue()); // $hasTaintFlow
79+
}
7580
}
7681

7782
@Post("/stream")

java/ql/test/library-tests/frameworks/micronaut/MicronautHttpRequestTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ void testCookies(HttpRequest<?> request) {
4747
sink(cookie.getPath()); // $hasTaintFlow
4848
sink(request.getCookies().getAll()); // $hasTaintFlow
4949
sink(request.getCookies().findCookie("session")); // $hasTaintFlow
50+
sink(request.getCookies().getValue("session")); // $hasTaintFlow
51+
sink(request.getCookies().values().iterator().next()); // $hasTaintFlow
52+
sink(request.getCookies().asMap().get("session")); // $hasTaintFlow
53+
for (Map.Entry<String, Cookie> entry : request.getCookies()) {
54+
sink(entry.getValue()); // $hasTaintFlow
55+
}
5056
}
5157

5258
@Get("/uri")

java/ql/test/query-tests/security/CWE-113/semmle/tests/MicronautResponseSplitting.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import io.micronaut.http.HttpResponse;
55
import io.micronaut.http.MutableHttpResponse;
66
import java.util.Collections;
7+
import java.util.HashMap;
8+
import java.util.Map;
79

810
@Controller("/headers")
911
public class MicronautResponseSplitting {
@@ -26,4 +28,22 @@ public MutableHttpResponse<?> badMap(@QueryValue String headerValue) {
2628
// BAD: user-controlled header value
2729
return HttpResponse.ok().headers(Collections.singletonMap("X-Custom", headerValue));
2830
}
31+
32+
@Get("/bad-map-mutation")
33+
public MutableHttpResponse<?> badMapMutation(@QueryValue String headerValue) {
34+
Map<CharSequence, CharSequence> headers = new HashMap<>();
35+
headers.put("X-Custom", headerValue);
36+
return HttpResponse.ok().headers(headers);
37+
}
38+
39+
@Get("/good-map")
40+
public MutableHttpResponse<?> goodMap() {
41+
return HttpResponse.ok().headers(Collections.singletonMap("X-Custom", "safe"));
42+
}
43+
44+
@Get("/good-map-sanitized")
45+
public MutableHttpResponse<?> goodMapSanitized(@QueryValue String headerValue) {
46+
String sanitized = headerValue.replace('\n', ' ').replace('\r', ' ');
47+
return HttpResponse.ok().headers(Collections.singletonMap("X-Custom", sanitized));
48+
}
2949
}

java/ql/test/query-tests/security/CWE-113/semmle/tests/ResponseSplitting.expected

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
#select
2-
| MicronautResponseSplitting.java:14:53:14:63 | headerValue | MicronautResponseSplitting.java:12:39:12:68 | headerValue : String | MicronautResponseSplitting.java:14:53:14:63 | headerValue | This header depends on a $@, which may cause a response-splitting vulnerability. | MicronautResponseSplitting.java:12:39:12:68 | headerValue | user-provided value |
3-
| MicronautResponseSplitting.java:27:42:27:90 | singletonMap(...) | MicronautResponseSplitting.java:25:42:25:71 | headerValue : String | MicronautResponseSplitting.java:27:42:27:90 | singletonMap(...) | This header depends on a $@, which may cause a response-splitting vulnerability. | MicronautResponseSplitting.java:25:42:25:71 | headerValue | user-provided value |
2+
| MicronautResponseSplitting.java:16:53:16:63 | headerValue | MicronautResponseSplitting.java:14:39:14:68 | headerValue : String | MicronautResponseSplitting.java:16:53:16:63 | headerValue | This header depends on a $@, which may cause a response-splitting vulnerability. | MicronautResponseSplitting.java:14:39:14:68 | headerValue | user-provided value |
3+
| MicronautResponseSplitting.java:29:42:29:90 | singletonMap(...) | MicronautResponseSplitting.java:27:42:27:71 | headerValue : String | MicronautResponseSplitting.java:29:42:29:90 | singletonMap(...) | This header depends on a $@, which may cause a response-splitting vulnerability. | MicronautResponseSplitting.java:27:42:27:71 | headerValue | user-provided value |
4+
| MicronautResponseSplitting.java:36:42:36:48 | headers | MicronautResponseSplitting.java:33:50:33:79 | headerValue : String | MicronautResponseSplitting.java:36:42:36:48 | headers | This header depends on a $@, which may cause a response-splitting vulnerability. | MicronautResponseSplitting.java:33:50:33:79 | headerValue | user-provided value |
45
| ResponseSplitting.java:23:23:23:28 | cookie | ResponseSplitting.java:22:39:22:66 | getParameter(...) : String | ResponseSplitting.java:23:23:23:28 | cookie | This header depends on a $@, which may cause a response-splitting vulnerability. | ResponseSplitting.java:22:39:22:66 | getParameter(...) | user-provided value |
56
| ResponseSplitting.java:28:38:28:72 | getParameter(...) | ResponseSplitting.java:28:38:28:72 | getParameter(...) | ResponseSplitting.java:28:38:28:72 | getParameter(...) | This header depends on a $@, which may cause a response-splitting vulnerability. | ResponseSplitting.java:28:38:28:72 | getParameter(...) | user-provided value |
67
| ResponseSplitting.java:29:38:29:72 | getParameter(...) | ResponseSplitting.java:29:38:29:72 | getParameter(...) | ResponseSplitting.java:29:38:29:72 | getParameter(...) | This header depends on a $@, which may cause a response-splitting vulnerability. | ResponseSplitting.java:29:38:29:72 | getParameter(...) | user-provided value |
78
| ResponseSplitting.java:59:27:59:57 | replaceFirst(...) | ResponseSplitting.java:53:14:53:48 | getParameter(...) : String | ResponseSplitting.java:59:27:59:57 | replaceFirst(...) | This header depends on a $@, which may cause a response-splitting vulnerability. | ResponseSplitting.java:53:14:53:48 | getParameter(...) | user-provided value |
89
edges
9-
| MicronautResponseSplitting.java:12:39:12:68 | headerValue : String | MicronautResponseSplitting.java:14:53:14:63 | headerValue | provenance | Sink:MaD:1 |
10-
| MicronautResponseSplitting.java:25:42:25:71 | headerValue : String | MicronautResponseSplitting.java:27:79:27:89 | headerValue : String | provenance | |
11-
| MicronautResponseSplitting.java:27:79:27:89 | headerValue : String | MicronautResponseSplitting.java:27:42:27:90 | singletonMap(...) | provenance | MaD:7 Sink:MaD:2 |
10+
| MicronautResponseSplitting.java:14:39:14:68 | headerValue : String | MicronautResponseSplitting.java:16:53:16:63 | headerValue | provenance | Sink:MaD:1 |
11+
| MicronautResponseSplitting.java:27:42:27:71 | headerValue : String | MicronautResponseSplitting.java:29:79:29:89 | headerValue : String | provenance | |
12+
| MicronautResponseSplitting.java:29:79:29:89 | headerValue : String | MicronautResponseSplitting.java:29:42:29:90 | singletonMap(...) | provenance | MaD:7 Sink:MaD:2 |
13+
| MicronautResponseSplitting.java:33:50:33:79 | headerValue : String | MicronautResponseSplitting.java:35:33:35:43 | headerValue : String | provenance | |
14+
| MicronautResponseSplitting.java:35:9:35:15 | headers [post update] : HashMap [<map.value>] : String | MicronautResponseSplitting.java:36:42:36:48 | headers | provenance | Sink:MaD:2 |
15+
| MicronautResponseSplitting.java:35:33:35:43 | headerValue : String | MicronautResponseSplitting.java:35:9:35:15 | headers [post update] : HashMap [<map.value>] : String | provenance | MaD:8 |
1216
| ResponseSplitting.java:22:20:22:67 | new Cookie(...) : Cookie | ResponseSplitting.java:23:23:23:28 | cookie | provenance | Sink:MaD:3 |
13-
| ResponseSplitting.java:22:39:22:66 | getParameter(...) : String | ResponseSplitting.java:22:20:22:67 | new Cookie(...) : Cookie | provenance | Src:MaD:5 MaD:8 |
17+
| ResponseSplitting.java:22:39:22:66 | getParameter(...) : String | ResponseSplitting.java:22:20:22:67 | new Cookie(...) : Cookie | provenance | Src:MaD:5 MaD:9 |
1418
| ResponseSplitting.java:53:14:53:48 | getParameter(...) : String | ResponseSplitting.java:59:27:59:27 | t : String | provenance | Src:MaD:5 |
1519
| ResponseSplitting.java:59:27:59:27 | t : String | ResponseSplitting.java:59:27:59:57 | replaceFirst(...) | provenance | MaD:6 Sink:MaD:4 |
1620
models
@@ -21,13 +25,18 @@ models
2125
| 5 | Source: javax.servlet; ServletRequest; false; getParameter; (String); ; ReturnValue; remote; manual |
2226
| 6 | Summary: java.lang; String; false; replaceFirst; ; ; Argument[this]; ReturnValue; taint; manual |
2327
| 7 | Summary: java.util; Collections; false; singletonMap; (Object,Object); ; Argument[1]; ReturnValue.MapValue; value; manual |
24-
| 8 | Summary: javax.servlet.http; Cookie; false; Cookie; ; ; Argument[1]; Argument[this]; taint; manual |
28+
| 8 | Summary: java.util; Map; true; put; (Object,Object); ; Argument[1]; Argument[this].MapValue; value; manual |
29+
| 9 | Summary: javax.servlet.http; Cookie; false; Cookie; ; ; Argument[1]; Argument[this]; taint; manual |
2530
nodes
26-
| MicronautResponseSplitting.java:12:39:12:68 | headerValue : String | semmle.label | headerValue : String |
27-
| MicronautResponseSplitting.java:14:53:14:63 | headerValue | semmle.label | headerValue |
28-
| MicronautResponseSplitting.java:25:42:25:71 | headerValue : String | semmle.label | headerValue : String |
29-
| MicronautResponseSplitting.java:27:42:27:90 | singletonMap(...) | semmle.label | singletonMap(...) |
30-
| MicronautResponseSplitting.java:27:79:27:89 | headerValue : String | semmle.label | headerValue : String |
31+
| MicronautResponseSplitting.java:14:39:14:68 | headerValue : String | semmle.label | headerValue : String |
32+
| MicronautResponseSplitting.java:16:53:16:63 | headerValue | semmle.label | headerValue |
33+
| MicronautResponseSplitting.java:27:42:27:71 | headerValue : String | semmle.label | headerValue : String |
34+
| MicronautResponseSplitting.java:29:42:29:90 | singletonMap(...) | semmle.label | singletonMap(...) |
35+
| MicronautResponseSplitting.java:29:79:29:89 | headerValue : String | semmle.label | headerValue : String |
36+
| MicronautResponseSplitting.java:33:50:33:79 | headerValue : String | semmle.label | headerValue : String |
37+
| MicronautResponseSplitting.java:35:9:35:15 | headers [post update] : HashMap [<map.value>] : String | semmle.label | headers [post update] : HashMap [<map.value>] : String |
38+
| MicronautResponseSplitting.java:35:33:35:43 | headerValue : String | semmle.label | headerValue : String |
39+
| MicronautResponseSplitting.java:36:42:36:48 | headers | semmle.label | headers |
3140
| ResponseSplitting.java:22:20:22:67 | new Cookie(...) : Cookie | semmle.label | new Cookie(...) : Cookie |
3241
| ResponseSplitting.java:22:39:22:66 | getParameter(...) : String | semmle.label | getParameter(...) : String |
3342
| ResponseSplitting.java:23:23:23:28 | cookie | semmle.label | cookie |

java/ql/test/stubs/micronaut-4.x/io/micronaut/http/cookie/Cookies.java

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)