in src/main/java/org/apache/sling/auth/core/AuthUtil.java [456:517]
public static boolean isRedirectValid(final HttpServletRequest request, final String target) {
if (target == null || target.length() == 0) {
getLog().warn("isRedirectValid: Redirect target must not be empty or null");
return false;
}
try {
new URI(target);
} catch (URISyntaxException e) {
getLog().warn("isRedirectValid: Redirect target '{}' contains illegal characters", target);
return false;
}
if (target.contains("://")) {
getLog().warn("isRedirectValid: Redirect target '{}' must not be an URL", target);
return false;
}
if (target.contains("//") || target.contains("/../") || target.contains("/./") || target.endsWith("/.")
|| target.endsWith("/..")) {
getLog().warn("isRedirectValid: Redirect target '{}' is not normalized", target);
return false;
}
final String ctxPath = getContextPath(request);
if (ctxPath.length() > 0 && !target.startsWith(ctxPath)) {
getLog().warn("isRedirectValid: Redirect target '{}' does not start with servlet context path '{}'",
target, ctxPath);
return false;
}
// special case of requesting the servlet context root path
if (ctxPath.length() == target.length()) {
return true;
}
final String localTarget = target.substring(ctxPath.length());
if (!localTarget.startsWith("/")) {
getLog().warn(
"isRedirectValid: Redirect target '{}' without servlet context path '{}' must be an absolute path",
target, ctxPath);
return false;
}
final int query = localTarget.indexOf('?');
final String path = (query > 0) ? localTarget.substring(0, query) : localTarget;
ResourceResolver resolver = getResourceResolver(request);
// assume all is fine if the path resolves to a resource
if (resolver != null && !ResourceUtil.isNonExistingResource(resolver.resolve(request, path))) {
return true;
}
// not resolving to a resource, check for illegal characters
final Pattern illegal = Pattern.compile("[<>'\"]");
if (illegal.matcher(path).find()) {
getLog().warn("isRedirectValid: Redirect target '{}' must not contain any of <>'\"", target);
return false;
}
return true;
}