Similar to the allowRelative option for Joi.string().uri() but to mandate that the uri is relative.
Why?
A common use case for passing urls around in query string is to perform some subsequent redirection e.g.
http:\\www.example.com\do-something?returnUrl=\summary
It's very likely that you would only ever want the returnUrl to be relative to the current domain. Doing so can also prevent Open Redirection Attacks.
We are currently using the is-relative-url package to ensure the returnUrl is local.
Alternatively, Microsoft's C# algorithm looks like this (here's a blog which includes a coffeescript implementation of the same):
public static bool IsUrlLocalToHost(this HttpRequestBase request, string url)
{
return !url.IsEmpty() &&
((url[0] == '/' && (url.Length == 1 ||
(url[1] != '/' && url[1] != '\\'))) || // "/" or "/foo" but not "//" or "/\"
(url.Length > 1 &&
url[0] == '~' && url[1] == '/')); // "~/" or "~/foo"
}
This could be useful to base something off (removing the tilde ~ logic as it is only relevent to ASP).
It would be nice if we could have Joi do this for us. Thoughts?
This shouldn't be a major change, happy to take a PR about it. Prefer shorter relativeOnly though.
Fixed by #1034.
I warn you that //google.com is still accepted as relative by relativeOnly thus making it less useful, because you still have to manually check the redirect url.
My approach:
const schema = Joi.object({
redirect_to_relative: Joi.string().uri({
relativeOnly: true
}).regex(/^\/\//, { invert: true })
});
Technically it is a relative URI, relative to the root. It is following the RFC if I remember well.
Yes, it conforms to the RFC, but it doesn't solve the redirection problem stated in the first post by @davidjamesstone, because it is still open to redirection attacks.
I propose to add Joi.string().uri({ isPathAndHash: true }). Path and hash definitions may be found here.
Because hash fragment is not passed to the server it must be percent-encoded into query string parameter (e.g. http://localhost/login?redirect_to_path=/protected#foo, but percent encoded) which is then validated by Joi.
Or you may come up with a more flexible configuration like:
Joi.string().uri({ madeOfOnly: ['path', 'hash'] })Joi.string().uri({ madeOfOnly: ['host', 'pathname'] }).Joi.string().uri({ doesntInclude: ['protocol'] }).This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.