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 )); // $MISSING: 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
+ @ RequestMapping (produces = {"application/json" })
103
+ private static class ClassContentTypeSafe {
104
+ public ResponseEntity <String > test (String userControlled ) {
105
+ return ResponseEntity .ok (userControlled );
106
+ }
107
+
108
+ @ GetMapping (value = "/abc" )
109
+ public String testDirectReturn (String userControlled ) {
110
+ return userControlled ;
111
+ }
112
+
113
+ @ GetMapping (value = "/xyz" , produces = {"text/html" })
114
+ public ResponseEntity <String > overridesWithUnsafe (String userControlled ) {
115
+ return ResponseEntity .ok (userControlled ); // $MISSING: xss
116
+ }
117
+
118
+ @ GetMapping (value = "/abc" )
119
+ public ResponseEntity <String > overridesWithUnsafe2 (String userControlled ) {
120
+ return ResponseEntity .ok ().contentType (MediaType .TEXT_HTML ).body (userControlled ); // $MISSING: xss
121
+ }
122
+ }
123
+
124
+ @ RequestMapping (produces = {"text/html" })
125
+ private static class ClassContentTypeUnsafe {
126
+ public ResponseEntity <String > test (String userControlled ) {
127
+ return ResponseEntity .ok (userControlled ); // $MISSING: xss
128
+ }
129
+
130
+ @ GetMapping (value = "/abc" )
131
+ public String testDirectReturn (String userControlled ) {
132
+ return userControlled ; //$MISSING: xss
133
+ }
134
+
135
+ @ GetMapping (value = "/xyz" , produces = {"application/json" })
136
+ public ResponseEntity <String > overridesWithSafe (String userControlled ) {
137
+ return ResponseEntity .ok (userControlled );
138
+ }
139
+
140
+ public ResponseEntity <String > overridesWithSafe2 (String userControlled ) {
141
+ return ResponseEntity .ok ().contentType (MediaType .APPLICATION_JSON ).body (userControlled );
142
+ }
143
+ }
144
+
145
+ @ GetMapping (value = "/abc" )
146
+ public static ResponseEntity <String > entityWithNoMediaType (String userControlled ) {
147
+ return ResponseEntity .ok (userControlled ); // $xss
148
+ }
149
+
150
+ @ GetMapping (value = "/abc" )
151
+ public static String stringWithNoMediaType (String userControlled ) {
152
+ return userControlled ; // $xss
153
+ }
154
+
155
+ }
0 commit comments