20

In Python (tried this in 2.7 and below) it looks like a file created using tempfile.NamedTemporaryFile doesn't seem to obey the umask directive:

import os, tempfile
os.umask(022)
f1 = open ("goodfile", "w")
f2 = tempfile.NamedTemporaryFile(dir='.')
f2.name

Out[33]: '/Users/foo/tmp4zK9Fe'

ls -l
-rw-------  1 foo  foo  0 May 10 13:29 /Users/foo/tmp4zK9Fe
-rw-r--r--  1 foo  foo  0 May 10 13:28 /Users/foo/goodfile

Any idea why NamedTemporaryFile won't pick up the umask? Is there any way to do this during file creation?

I can always workaround this with os.chmod(), but I was hoping for something that did the right thing during file creation.

shreddd
  • 10,975
  • 9
  • 33
  • 34

2 Answers2

45

This is a security feature. The NamedTemporaryFile is always created with mode 0600, hardcoded at tempfile.py, line 235, because it is private to your process until you open it up with chmod. There is no constructor argument to change this behavior.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 10
    Thanks - gotta love an answer that links to a specific line in the source! – shreddd May 12 '12 at 03:16
  • 3
    Thanks for your answer. I'll just note that this is bizarre, or else I'm missing another way to do what I want. I simply wnat to use a NamedTemporaryFile just so I can throw it away if I run into errors generating it, but move it on success to a file that I might otherwise have created with a plain open(name, 'w"). Seems like a feature request is called for.... – nealmcb Nov 14 '17 at 05:29
21

In case it might help someone, I wanted to do more or less the same thing, here is the code I have used:

import os
from tempfile import NamedTemporaryFile

def UmaskNamedTemporaryFile(*args, **kargs):
    fdesc = NamedTemporaryFile(*args, **kargs)
    # we need to set umask to get its current value. As noted
    # by Florian Brucker (comment), this is a potential security
    # issue, as it affects all the threads. Considering that it is
    # less a problem to create a file with permissions 000 than 666,
    # we use 666 as the umask temporary value.
    umask = os.umask(0o666)
    os.umask(umask)
    os.chmod(fdesc.name, 0o666 & ~umask)
    return fdesc
Pierre
  • 6,047
  • 1
  • 30
  • 49
  • 2
    Just what I wanted! Thank you very much for teasing out the low-level plumbing we're forced to do! :) – nealmcb Nov 14 '17 at 05:34