2323@ Controller
2424public class UrlForwardTest extends HttpServlet implements Filter {
2525
26- // Spring-related test cases
26+ // Spring `ModelAndView` test cases
2727 @ GetMapping ("/bad1" )
2828 public ModelAndView bad1 (String url ) {
2929 return new ModelAndView (url ); // $ hasUrlForward
@@ -36,6 +36,7 @@ public ModelAndView bad2(String url) {
3636 return modelAndView ;
3737 }
3838
39+ // Spring `"forward:"` prefix test cases
3940 @ GetMapping ("/bad3" )
4041 public String bad3 (String url ) {
4142 return "forward:" + url + "/swagger-ui/index.html" ; // $ hasUrlForward
@@ -47,6 +48,7 @@ public ModelAndView bad4(String url) {
4748 return modelAndView ;
4849 }
4950
51+ // `RequestDispatcher` test cases from a Spring `GetMapping` entry point
5052 @ GetMapping ("/bad5" )
5153 public void bad5 (String url , HttpServletRequest request , HttpServletResponse response ) {
5254 try {
@@ -91,7 +93,7 @@ public void good1(String url, HttpServletRequest request, HttpServletResponse re
9193 }
9294 }
9395
94- // Non-Spring test cases (UnsafeRequest*Path*)
96+ // `RequestDispatcher` test cases from non-Spring entry points
9597 private static final String BASE_PATH = "/pages" ;
9698
9799 @ Override
@@ -132,7 +134,6 @@ public void doFilter3(ServletRequest request, ServletResponse response, FilterCh
132134 }
133135 }
134136
135- // Non-Spring test cases (UnsafeServletRequest*Dispatch*)
136137 @ Override
137138 // BAD: Request dispatcher constructed from `ServletContext` without input validation
138139 protected void doGet (HttpServletRequest request , HttpServletResponse response )
@@ -184,7 +185,7 @@ protected void doPut(HttpServletRequest request, HttpServletResponse response)
184185 }
185186
186187 // BAD: Request dispatcher without path traversal check
187- protected void doHead2 (HttpServletRequest request , HttpServletResponse response )
188+ protected void doHead1 (HttpServletRequest request , HttpServletResponse response )
188189 throws ServletException , IOException {
189190 String path = request .getParameter ("path" );
190191
@@ -196,7 +197,7 @@ protected void doHead2(HttpServletRequest request, HttpServletResponse response)
196197
197198 // BAD: Request dispatcher with path traversal check that does not decode
198199 // the user-supplied path; could bypass check with ".." encoded as "%2e%2e".
199- protected void doHead3 (HttpServletRequest request , HttpServletResponse response )
200+ protected void doHead2 (HttpServletRequest request , HttpServletResponse response )
200201 throws ServletException , IOException {
201202 String path = request .getParameter ("path" );
202203
@@ -207,7 +208,7 @@ protected void doHead3(HttpServletRequest request, HttpServletResponse response)
207208
208209 // BAD: Request dispatcher with path normalization and comparison, but
209210 // does not decode before normalization.
210- protected void doHead4 (HttpServletRequest request , HttpServletResponse response )
211+ protected void doHead3 (HttpServletRequest request , HttpServletResponse response )
211212 throws ServletException , IOException {
212213 String path = request .getParameter ("path" );
213214
@@ -220,7 +221,7 @@ protected void doHead4(HttpServletRequest request, HttpServletResponse response)
220221 }
221222
222223 // BAD: Request dispatcher with negation check and path normalization, but without URL decoding.
223- protected void doHead5 (HttpServletRequest request , HttpServletResponse response )
224+ protected void doHead4 (HttpServletRequest request , HttpServletResponse response )
224225 throws ServletException , IOException {
225226 String path = request .getParameter ("path" );
226227 // Since not decoded before normalization, "/%57EB-INF" can remain in the path and pass the `startsWith` check.
@@ -232,7 +233,7 @@ protected void doHead5(HttpServletRequest request, HttpServletResponse response)
232233 }
233234
234235 // BAD: Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
235- protected void doHead7 (HttpServletRequest request , HttpServletResponse response )
236+ protected void doHead5 (HttpServletRequest request , HttpServletResponse response )
236237 throws ServletException , IOException {
237238 String path = request .getParameter ("path" );
238239 path = URLDecoder .decode (path , "UTF-8" );
@@ -245,9 +246,9 @@ protected void doHead7(HttpServletRequest request, HttpServletResponse response)
245246 // GOOD: Request dispatcher with path traversal check and URL decoding in a loop to avoid double-encoding bypass
246247 protected void doHead6 (HttpServletRequest request , HttpServletResponse response )
247248 throws ServletException , IOException {
248- String path = request .getParameter ("path" ); // TODO: remove this debugging comment: // v
249+ String path = request .getParameter ("path" );
249250
250- if (path .contains ("%" )){ // TODO: remove this debugging comment: // v.getAnAccess()
251+ if (path .contains ("%" )){
251252 while (path .contains ("%" )) {
252253 path = URLDecoder .decode (path , "UTF-8" );
253254 }
@@ -259,7 +260,7 @@ protected void doHead6(HttpServletRequest request, HttpServletResponse response)
259260 }
260261
261262 // GOOD: Request dispatcher with URL encoding check and path traversal check
262- protected void doHead16 (HttpServletRequest request , HttpServletResponse response )
263+ protected void doHead7 (HttpServletRequest request , HttpServletResponse response )
263264 throws ServletException , IOException {
264265 String path = request .getParameter ("path" );
265266
@@ -270,41 +271,33 @@ protected void doHead16(HttpServletRequest request, HttpServletResponse response
270271 }
271272 }
272273
273- // TODO: clean-up
274- // BAD (I added): Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
275- // Tests urlEncoding BarrierGuard "a guard that considers a string safe because it is checked for URL encoding sequences,
276- // having previously been checked against a block-list of forbidden values."
277- protected void doHead10 (HttpServletRequest request , HttpServletResponse response )
274+ // BAD: Request dispatcher without URL decoding before WEB-INF and path traversal checks
275+ protected void doHead8 (HttpServletRequest request , HttpServletResponse response )
278276 throws ServletException , IOException {
279277 String path = request .getParameter ("path" );
280- if (path .contains ("%" )){ // BAD: wrong check
281- if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
282- // if (path.contains("%")){ // BAD: wrong check
278+ if (path .contains ("%" )){ // incorrect check
279+ if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
283280 request .getServletContext ().getRequestDispatcher (path ).include (request , response ); // $ hasUrlForward
284- // }
281+ }
285282 }
286283 }
287- }
288284
289- // TODO: clean-up
290- // "GOOD" (I added): Request dispatcher with path traversal check and single URL decoding; may be vulnerable to double-encoding
291- // Tests urlEncoding BarrierGuard "a guard that considers a string safe because it is checked for URL encoding sequences,
292- // having previously been checked against a block-list of forbidden values."
293- protected void doHead11 (HttpServletRequest request , HttpServletResponse response )
285+ // GOOD: Request dispatcher with WEB-INF, path traversal, and URL encoding checks
286+ protected void doHead9 (HttpServletRequest request , HttpServletResponse response )
294287 throws ServletException , IOException {
295288 String path = request .getParameter ("path" );
296289
297290 if (!path .startsWith ("/WEB-INF/" ) && !path .contains (".." )) {
298- if (!path .contains ("%" )){ // GOOD: right check
291+ if (!path .contains ("%" )){ // correct check
299292 request .getServletContext ().getRequestDispatcher (path ).include (request , response );
300293 }
301294 }
302295 }
303296
304297 // GOOD: Request dispatcher with path traversal check and URL decoding in a loop to avoid double-encoding bypass
305- protected void doHead8 (HttpServletRequest request , HttpServletResponse response )
298+ protected void doHead10 (HttpServletRequest request , HttpServletResponse response )
306299 throws ServletException , IOException {
307- String path = request .getParameter ("path" ); // TODO: remove this debugging comment: // v
300+ String path = request .getParameter ("path" );
308301 while (path .contains ("%" )) {
309302 path = URLDecoder .decode (path , "UTF-8" );
310303 }
@@ -314,12 +307,12 @@ protected void doHead8(HttpServletRequest request, HttpServletResponse response)
314307 }
315308 }
316309
317- // TODO: see if can fix?
318- // FP now....
319310 // GOOD: Request dispatcher with path traversal check and URL decoding in a loop to avoid double-encoding bypass
320- protected void doHead9 (HttpServletRequest request , HttpServletResponse response )
311+ protected void doHead11 (HttpServletRequest request , HttpServletResponse response )
321312 throws ServletException , IOException {
322- String path = request .getParameter ("path" ); // v
313+ String path = request .getParameter ("path" );
314+ // FP: we don't currently handle the scenario where the
315+ // `path.contains("%")` check is stored in a variable.
323316 boolean hasEncoding = path .contains ("%" );
324317 while (hasEncoding ) {
325318 path = URLDecoder .decode (path , "UTF-8" );
0 commit comments