I am trying to write a function that resolves a path (provided by the user) relative to a directory, ensuring that the result is inside the directory. The one below seems to work, but I am counting on community eyeballs to tell me if I left any holes in it, or that I overcomplicated it Does not need to be super-secure (just to prevent users shooting themselves in the foot), but portability would be nice. I tested on Linux. OS X and windows tests would be welcome.
"""
ensure_proper_subpath(dir, subpath)
Return the normalized `dir/subpath`, ensuring that it is inside `dir`, otherwise
raising an error. *None of the paths are required to exist, the function operates
on paths, not the filesystem.*
"""
function ensure_proper_subpath(dir, subpath)
norm_dir = normpath(dir)
norm_subpath = normpath(joinpath(norm_dir, subpath))
@assert startswith(norm_subpath, norm_dir) "$(subpath) not in $(dir)."
norm_subpath
end
ensure_proper_subpath("/tmp", "foo") # "/tmp/foo"
ensure_proper_subpath("/tmp/dir/", "foo") # "/tmp/dir/foo"
ensure_proper_subpath("/tmp/dir/", "../foo") # ERROR
ensure_proper_subpath("/tmp/", "dir/../foo") # "/tmp/foo"
ensure_proper_subpath("/tmp/", "dir/../../foo") # ERROR