@@ -41,6 +41,12 @@ public String rewriteRedirect(final String url)
4141 if (StringUtils .isEmpty (url ))
4242 return "/" ;
4343
44+ // Reject any URL that isn't plainly http(s) or a server-relative path. This stops dangerous schemes
45+ // (javascript:, data:, vbscript:, ...) being carried through to the /redirect-warning template where
46+ // a user click would otherwise execute them in-origin.
47+ if (!isHttpOrRelative (url ))
48+ return "/" ;
49+
4450 URI uri = URI .create (url );
4551
4652 if (StringUtils .startsWithIgnoreCase (uri .getPath (), "/user-manager" ))
@@ -54,11 +60,35 @@ else if (isSafe(url))
5460 }
5561
5662
63+ /**
64+ * Returns true if the URL is either a server-relative path (and not protocol-relative), or uses the http/https
65+ * scheme. Any other scheme (javascript:, data:, file:, vbscript:, ...) is rejected.
66+ */
67+ private static boolean isHttpOrRelative (final String url )
68+ {
69+ if (StringUtils .isBlank (url ))
70+ return true ;
71+
72+ // Server-relative path (but not "//..." which is protocol-relative)
73+ if (url .startsWith ("/" ) && !url .startsWith ("//" ))
74+ return true ;
75+
76+ // Explicit http / https only
77+ if (StringUtils .startsWithIgnoreCase (url , "http://" ) || StringUtils .startsWithIgnoreCase (url , "https://" ))
78+ return true ;
79+
80+ return false ;
81+ }
82+
83+
5784 boolean isSafe (final String url )
5885 {
5986 if (StringUtils .isBlank (url ))
6087 return true ;
6188
89+ if (!isHttpOrRelative (url ))
90+ return false ;
91+
6292 if (allowAllRelativeRedirects && (url .startsWith ("/" ) && !url .startsWith ("//" ) || url .startsWith (".." )))
6393 return true ;
6494 else if (isKnownClientService (url ))
0 commit comments