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