I have a rootPath that I trust and a relativePath that I don't. I want to combine them in such a way that I can be sure that the result is under rootPath and that the user can't use .. to get back past the starting point. I do want the relative path to allow things like: hello\..\world == world
System.IO.Path.GetFullPath?
To expand: use Path.Combine, then call GetFullPath on the result and check that that result starts with rootPath.
It won't protect you against hardlinks, but it should catch simple things like double-dots.
the above as code:
string Resolve(string fileName)
{
string root = FileRoot();
string ret = Path.GetFullPath(Path.Combine(root, fileName));
if (ret.StartsWith(root.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar)) return ret;
throw new ArgumentException("path resolved to out of accesable directroy");
}
You could just call Path.GetFullPath() and check if it starts with your trusted rootPath. If you tend to paranoia, check also that rootPath is rooted.
public Boolean IsPathSafe(String rootPath, String relativePath)
{
return rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()) &&
Path.IsPathRooted(rootPath) &&
Path.Combine(rootPath, relativePath).GetFullPath().StartsWith(rootPath);
}
For an explaination of the first test see Alex Martelli's comment on technophile's answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With