Warning: os.path.join surprising behaviour
Tuesday, 19 June 2007
>>> os.path.join("/a/b/c", "/d/e/f")
"/d/e/f"
This can be a problem if “/d/e/f” comes from an untrusted source.
As a safety measure, avoid using os.path.join in your web applications, roll your own and call it “safe_join”. You will sleep better.
The entry 'Warning: os.path.join surprising behaviour' was posted
on June 19th, 2007 at 1:26 pm
and is filed under IronPython, Python.
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.
No. 1 — June 19th, 2007 at 9:21 pm
Hm IMHO, this is a bug and should be reported. What do you think?
No. 2 — June 19th, 2007 at 9:26 pm
Ah, nevermind, there already are http://sourceforge.net/tracker/index.php?func=detail&aid=1209447&group_id=5470&atid=105470 and http://sourceforge.net/tracker/index.php?func=detail&aid=1688564&group_id=5470&atid=105470
No. 3 — June 19th, 2007 at 9:43 pm
How is that surprising? It is the documented behaviour, and usually desirable. The second path in your example is rooted.
No. 4 — June 19th, 2007 at 9:44 pm
Oh - and you can stop it by detecting/removing the leading “/”.
No. 5 — June 19th, 2007 at 11:58 pm
>>> os.path.join(”/a/b/c”, *”/d/e/f”.split(’/'))
‘/a/b/c/d/e/f’
It is a bit surprising.
No. 6 — June 19th, 2007 at 11:59 pm
It surprises me. But os.path.join is inherently unsafe: ‘../../../d/e/f’ would have the same effect as ‘/d/e/f’ here. Don’t let untrusted sources supply paths!
No. 7 — June 20th, 2007 at 9:04 am
Fuzzyman,
You are right that it’s documented. It doesn’t stop the behavior from being surprising.
About stripping leading “/”, you also need to strip the drive name on Windows platforms.
A better guard is to assert that the joined path is a subdirectory of the base.
e.g.
newpath = os.path.join(base, subpath)
assert newpath.find(base) == 0
Perhaps it should be annotated as being unsafe on web platforms.
Chui