In https://github.com/golang/go/blob/f882d89b768bcfbd02b209acf0d525f4dbdd8f09/src/io/ioutil/tempfile.go#L64 The prefix and suffix extracted from the variable pattern are used in filepath.Join. Since there is no filtering in place, this could lead to directory traversal vulnerabilities.
For example, the following value for pattern can create an unexpected behaviour:
ioutil.TempFile("/tmp", path.Base("../../somewhere/else.*.suffix"))
A less-surprising behaviour would be to call path.Base:
name := filepath.Join(dir, path.Base(prefix+nextRandom()+suffix))
Are there any examples of real Go code that does not pass a string constant as the second argument to ioutil.TempFile?
I did a quick Github search for it and couldn't find it in the first few pages. But that's only publicly available code
Regardless, the current behaviour is unexpected and this small change can avoid people shooting themself in the foot.
Well, it's a tradeoff. If there are programs intentionally using directory traversal, we break them. If there are programs accidentally using it, we fix them. If we don't know of any actual cases that would be fixed, the conservative approach is to leave well enough alone.
I couldn't find any publicly available code using the directory traversal on purpose. My guess is that people would put the traversal in the first argument if they need to...
If we can't find examples of it being used either intentionally or unintentionally, in doubt I'd make it behave safely, which presumably is not going to break much, but might prevent security issues in the future.
Also, pattern is not even documented to accept path separators, and they definitely make more send in dir.
@ianlancetaylor what do you think?
The comment by @FiloSottile sounds reasonable to me.
name := filepath.Join(dir, path.Base(prefix+nextRandom()+suffix))
Please don't do this. What if suffix has a slash in it? Then the randomness is removed entirely.
If we're going to do anything at all, we should simply make TempFile return an error when pattern contains a file system path separator.
We shouldn't make this problematic case (which we think does not happen ever in real programs) silently succeed with an unexpected meaning. But assuming we simply return an error instead, this seems like a likely accept based on the discussion. Everyone agrees with doing something and no one thinks it matters for real programs.
Leaving open for a week for final comments.
No change in consensus, so accepting.
Change https://golang.org/cl/212597 mentions this issue: ioutil: reject path separators in TempDir, TempFile pattern
Most helpful comment
If we can't find examples of it being used either intentionally or unintentionally, in doubt I'd make it behave safely, which presumably is not going to break much, but might prevent security issues in the future.
Also,
patternis not even documented to accept path separators, and they definitely make more send indir.