1
+ import org .springframework .http .ResponseEntity ;
2
+ import org .springframework .http .MediaType ;
3
+ import org .springframework .http .HttpStatus ;
4
+ import org .springframework .web .bind .annotation .GetMapping ;
5
+ import org .springframework .web .bind .annotation .PostMapping ;
6
+ import org .springframework .web .bind .annotation .RequestMapping ;
7
+ import org .springframework .web .bind .annotation .RestController ;
8
+
9
+ import java .util .Optional ;
10
+
11
+ @ RestController
12
+ public class SpringXSS {
13
+
14
+ @ GetMapping
15
+ public static ResponseEntity <String > specificContentType (boolean safeContentType , boolean chainDirectly , String userControlled ) {
16
+
17
+ ResponseEntity .BodyBuilder builder = ResponseEntity .ok ();
18
+
19
+ if (safeContentType ) {
20
+ if (chainDirectly ) {
21
+ return builder .contentType (MediaType .TEXT_HTML ).body (userControlled ); // $xss
22
+ }
23
+ else {
24
+ ResponseEntity .BodyBuilder builder2 = builder .contentType (MediaType .TEXT_HTML );
25
+ return builder2 .body (userControlled ); // $xss
26
+ }
27
+ }
28
+ else {
29
+ if (chainDirectly ) {
30
+ return builder .contentType (MediaType .APPLICATION_JSON ).body (userControlled ); // $SPURIOUS: xss
31
+ }
32
+ else {
33
+ ResponseEntity .BodyBuilder builder2 = builder .contentType (MediaType .APPLICATION_JSON );
34
+ return builder2 .body (userControlled ); // $SPURIOUS: xss
35
+ }
36
+ }
37
+
38
+ }
39
+
40
+ @ GetMapping (value = "/xyz" , produces = MediaType .APPLICATION_JSON_VALUE )
41
+ public static ResponseEntity <String > methodContentTypeSafe (String userControlled ) {
42
+ return ResponseEntity .ok (userControlled );
43
+ }
44
+
45
+ @ PostMapping (value = "/xyz" , produces = MediaType .APPLICATION_JSON_VALUE )
46
+ public static ResponseEntity <String > methodContentTypeSafePost (String userControlled ) {
47
+ return ResponseEntity .ok (userControlled );
48
+ }
49
+
50
+ @ RequestMapping (value = "/xyz" , produces = MediaType .APPLICATION_JSON_VALUE )
51
+ public static ResponseEntity <String > methodContentTypeSafeRequest (String userControlled ) {
52
+ return ResponseEntity .ok (userControlled );
53
+ }
54
+
55
+ @ GetMapping (value = "/xyz" , produces = "application/json" )
56
+ public static ResponseEntity <String > methodContentTypeSafeStringLiteral (String userControlled ) {
57
+ return ResponseEntity .ok (userControlled );
58
+ }
59
+
60
+ @ GetMapping (value = "/xyz" , produces = MediaType .TEXT_HTML_VALUE )
61
+ public static ResponseEntity <String > methodContentTypeUnsafe (String userControlled ) {
62
+ return ResponseEntity .ok (userControlled ); // $MISSING: xss
63
+ }
64
+
65
+ @ GetMapping (value = "/xyz" , produces = "text/html" )
66
+ public static ResponseEntity <String > methodContentTypeUnsafeStringLiteral (String userControlled ) {
67
+ return ResponseEntity .ok (userControlled ); // $xss
68
+ }
69
+
70
+ @ GetMapping (value = "/xyz" , produces = {MediaType .TEXT_HTML_VALUE , MediaType .APPLICATION_JSON_VALUE })
71
+ public static ResponseEntity <String > methodContentTypeMaybeSafe (String userControlled ) {
72
+ return ResponseEntity .ok (userControlled ); // $xss
73
+ }
74
+
75
+ @ GetMapping (value = "/xyz" , produces = MediaType .APPLICATION_JSON_VALUE )
76
+ public static ResponseEntity <String > methodContentTypeSafeOverriddenWithUnsafe (String userControlled ) {
77
+ return ResponseEntity .ok ().contentType (MediaType .TEXT_HTML ).body (userControlled ); // $MISSING: xss
78
+ }
79
+
80
+ @ GetMapping (value = "/xyz" , produces = MediaType .TEXT_HTML_VALUE )
81
+ public static ResponseEntity <String > methodContentTypeUnsafeOverriddenWithSafe (String userControlled ) {
82
+ return ResponseEntity .ok ().contentType (MediaType .APPLICATION_JSON ).body (userControlled );
83
+ }
84
+
85
+ @ GetMapping (value = "/xyz" , produces = {"text/html" , "application/json" })
86
+ public static ResponseEntity <String > methodContentTypeMaybeSafeStringLiterals (String userControlled , int constructionMethod ) {
87
+ // Also try out some alternative constructors for the ResponseEntity:
88
+ switch (constructionMethod ) {
89
+ case 0 :
90
+ return ResponseEntity .ok (userControlled ); // $xss
91
+ case 1 :
92
+ return ResponseEntity .of (Optional .of (userControlled )); // $xss
93
+ case 2 :
94
+ return ResponseEntity .ok ().body (userControlled ); // $xss
95
+ case 3 :
96
+ return new ResponseEntity <String >(userControlled , HttpStatus .OK ); // $xss
97
+ default :
98
+ return null ;
99
+ }
100
+ }
101
+
102
+ @ RestController
103
+ @ RequestMapping (produces = {"application/json" })
104
+ private static class ClassContentTypeSafe {
105
+ @ GetMapping (value = "/abc" )
106
+ public ResponseEntity <String > test (String userControlled ) {
107
+ return ResponseEntity .ok (userControlled ); // $SPURIOUS: xss
108
+ }
109
+
110
+ @ GetMapping (value = "/abc" )
111
+ public String testDirectReturn (String userControlled ) {
112
+ return userControlled ; // $SPURIOUS: xss
113
+ }
114
+
115
+ @ GetMapping (value = "/xyz" , produces = {"text/html" })
116
+ public ResponseEntity <String > overridesWithUnsafe (String userControlled ) {
117
+ return ResponseEntity .ok (userControlled ); // $xss
118
+ }
119
+
120
+ @ GetMapping (value = "/abc" )
121
+ public ResponseEntity <String > overridesWithUnsafe2 (String userControlled ) {
122
+ return ResponseEntity .ok ().contentType (MediaType .TEXT_HTML ).body (userControlled ); // $xss
123
+ }
124
+ }
125
+
126
+ @ RestController
127
+ @ RequestMapping (produces = {"text/html" })
128
+ private static class ClassContentTypeUnsafe {
129
+ @ GetMapping (value = "/abc" )
130
+ public ResponseEntity <String > test (String userControlled ) {
131
+ return ResponseEntity .ok (userControlled ); // $xss
132
+ }
133
+
134
+ @ GetMapping (value = "/abc" )
135
+ public String testDirectReturn (String userControlled ) {
136
+ return userControlled ; // $xss
137
+ }
138
+
139
+ @ GetMapping (value = "/xyz" , produces = {"application/json" })
140
+ public ResponseEntity <String > overridesWithSafe (String userControlled ) {
141
+ return ResponseEntity .ok (userControlled ); // $SPURIOUS: xss
142
+ }
143
+
144
+ @ GetMapping (value = "/abc" )
145
+ public ResponseEntity <String > overridesWithSafe2 (String userControlled ) {
146
+ return ResponseEntity .ok ().contentType (MediaType .APPLICATION_JSON ).body (userControlled ); // $SPURIOUS: xss
147
+ }
148
+ }
149
+
150
+ @ GetMapping (value = "/abc" )
151
+ public static ResponseEntity <String > entityWithNoMediaType (String userControlled ) {
152
+ return ResponseEntity .ok (userControlled ); // $xss
153
+ }
154
+
155
+ @ GetMapping (value = "/abc" )
156
+ public static String stringWithNoMediaType (String userControlled ) {
157
+ return userControlled ; // $xss
158
+ }
159
+
160
+ }
0 commit comments