classification
Title: Use tempfile instead of /tmp in examples
Type: security Stage: resolved
Components: Documentation Versions: Python 3.4, Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: docs@python Nosy List: Henri.Salo, davbo, docs@python, eric.araujo, gmwils, grubert, maurobaraldi, petri.lehtinen, python-dev, techtonik, terry.reedy, vinay.sajip
Priority: normal Keywords: easy, patch

Created on 2010-06-03 21:11 by Henri.Salo, last changed 2013-02-23 18:40 by petri.lehtinen. This issue is now closed.

Files
File name Uploaded Description Edit
py3k-docs.patch maurobaraldi, 2010-11-20 19:31 review
tmp_logging_howto.diff davbo, 2011-06-26 12:44 diff of logging example using /tmp/ review
Issue8890.patch gmwils, 2013-02-23 17:06 review
Issue8890-3.2.patch gmwils, 2013-02-23 17:45 review
Issue8890-3.3.patch gmwils, 2013-02-23 17:46 review
Messages (29)
msg106982 - (view) Author: Henri Salo (Henri.Salo) Date: 2010-06-03 21:11
Module logging has dangerous examples as one can see from: <http://docs.python.org/library/logging.html#simple-examples> 15.6.1.1:

> import logging
> LOG_FILENAME = '/tmp/logging_example.out'
> logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
> logging.debug('This message should go to the log file')

It is not very wise to guide programmers to create programming mistakes. More information about the situation from: <http://www.owasp.org/index.php/Insecure_Temporary_File>.
msg106985 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-06-03 21:36
Would you be kind enough to provide a doc patch that would advertise using the tempfile module?
msg106987 - (view) Author: anatoly techtonik (techtonik) Date: 2010-06-03 21:50
import logging
- LOG_FILENAME = '/tmp/logging_example.out'
+ LOG_FILENAME = 'example.log'
  logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
  logging.debug('This message should go to the log file')
msg106988 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-06-03 21:55
Nice, this example doesn’t require explaining tempfile and is shorter.
Add a notice before the code that you need to be in a directory with
write rights for this to work and I’m +1.
msg106994 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2010-06-03 22:35
Documenation fix checked into trunk (r81680).
msg106995 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-06-03 22:39
Thanks Vinay. You miss a closing paren in your commit.
msg107012 - (view) Author: Henri Salo (Henri.Salo) Date: 2010-06-04 07:33
Please note that there is other similar examples as well. Even on the same page.
msg107016 - (view) Author: Henri Salo (Henri.Salo) Date: 2010-06-04 08:04
We should review all of these:

install/index.rst:   python setup.py build --build-base=/tmp/pybuild/foo-1.0
install/index.rst:   python setup.py install --install-base=/tmp
install/index.rst:would install pure modules to :file:`{/tmp/python/lib}` in the first case, and
install/index.rst:to :file:`{/tmp/lib}` in the second case.  (For the second case, you probably
install/index.rst:want to supply an installation base of :file:`/tmp/python`.)
library/pipes.rst:   >>> f=t.open('/tmp/1', 'w')
library/pipes.rst:   >>> open('/tmp/1').read()
library/mailcap.rst:   >>> mailcap.findmatch(d, 'video/mpeg', filename='/tmp/tmp1223')
library/mailcap.rst:   ('xmpeg /tmp/tmp1223', {'view': 'xmpeg %s'})
library/logging.rst:   LOG_FILENAME = '/tmp/logging_rotatingfile_example.out'
library/logging.rst:   /tmp/logging_rotatingfile_example.out
library/logging.rst:   /tmp/logging_rotatingfile_example.out.1
library/logging.rst:   /tmp/logging_rotatingfile_example.out.2
library/logging.rst:   /tmp/logging_rotatingfile_example.out.3
library/logging.rst:   /tmp/logging_rotatingfile_example.out.4
library/logging.rst:   /tmp/logging_rotatingfile_example.out.5
library/logging.rst:The most current file is always :file:`/tmp/logging_rotatingfile_example.out`,
library/logging.rst:                       filename='/tmp/myapp.log',
library/logging.rst:which results in output (written to ``/tmp/myapp.log``) which should look
library/atexit.rst:       _count = int(open("/tmp/counter").read())
library/atexit.rst:       open("/tmp/counter", "w").write("%d" % _count)
library/imghdr.rst:   >>> imghdr.what('/tmp/bass.gif')
library/tempfile.rst:         '/var/folders/5q/5qTPn6xq2RaWqk+1Ytw3-U+++TI/-Tmp-/tmpG7V1Y0'
library/tempfile.rst:      * On all other platforms, the directories :file:`/tmp`, :file:`/var/tmp`, and
library/tempfile.rst:        :file:`/usr/tmp`, in that order.
library/posixfile.rst:   file = posixfile.open('/tmp/test', 'w')
library/cgi.rst:   cgitb.enable(display=0, logdir="/tmp")
library/optparse.rst:   prog -v --report /tmp/report.txt foo bar
library/optparse.rst:takes one argument, ``"/tmp/report.txt"`` is an option argument.  ``"foo"`` and
library/rexec.rst:   :file:`/tmp` or uploading it to the :file:`/incoming` directory of your public
library/rexec.rst::file:`/tmp` to be written, we can subclass the :class:`RExec` class::
library/rexec.rst:               # check filename : must begin with /tmp/
library/rexec.rst:               if file[:5]!='/tmp/':
library/rexec.rst:                   raise IOError("can't write outside /tmp")
library/rexec.rst:called :file:`/tmp/foo/../bar`.  To fix this, the :meth:`r_open` method would
library/rexec.rst:have to simplify the filename to :file:`/tmp/bar`, which would require splitting
library/compiler.rst::file:`/tmp/doublelib.py`.  ::
library/compiler.rst:   >>> mod = compiler.parseFile("/tmp/doublelib.py")
library/zipimport.rst:subdirectory.  For example, the path :file:`/tmp/example.zip/lib/` would only
library/zipimport.rst:   $ unzip -l /tmp/example.zip
library/zipimport.rst:   Archive:  /tmp/example.zip
library/zipimport.rst:   >>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
library/zipimport.rst:   '/tmp/example.zip/jwzthreading.py'
library/trace.rst:   # make a report, placing output in /tmp
library/trace.rst:   r.write_results(show_missing=True, coverdir="/tmp")
library/nntplib.rst:   >>> f = open('/tmp/article')
library/bsddb.rst:   >>> db = bsddb.btopen('/tmp/spam.db', 'c')
library/sqlite3.rst::file:`/tmp/example` file::
library/sqlite3.rst:   conn = sqlite3.connect('/tmp/example')
tutorial/inputoutput.rst:   >>> f = open('/tmp/workfile', 'w')
tutorial/inputoutput.rst:   <open file '/tmp/workfile', mode 'w' at 80a0960>
tutorial/inputoutput.rst:   >>> f = open('/tmp/workfile', 'r+')
tutorial/inputoutput.rst:    >>> with open('/tmp/workfile', 'r') as f:
whatsnew/2.3.rst:   amk@nyman:~/src/python$ unzip -l /tmp/example.zip
whatsnew/2.3.rst:   Archive:  /tmp/example.zip
whatsnew/2.3.rst:   >>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
whatsnew/2.3.rst:   '/tmp/example.zip/jwzthreading.py'
whatsnew/2.3.rst:subdirectory; for example, the path :file:`/tmp/example.zip/lib/` would only
whatsnew/2.3.rst:     >>> os.stat("/tmp").st_mtime
whatsnew/2.3.rst:     >>> os.stat("/tmp").st_mtime
whatsnew/2.0.rst:   output = UTF8_streamwriter( open( '/tmp/output', 'wb') )
whatsnew/2.0.rst:   input = UTF8_streamreader( open( '/tmp/output', 'rb') )
whatsnew/2.6.rst:      shutil.copytree('Doc/library', '/tmp/library',
whatsnew/2.6.rst:    # to the /tmp directory.
whatsnew/2.6.rst:    z.extract('Python/sysmodule.c', '/tmp')
whatsnew/2.6.rst:    plistlib.writePlist(data_struct, '/tmp/customizations.plist')
whatsnew/2.6.rst:    new_struct = plistlib.readPlist('/tmp/customizations.plist')
whatsnew/2.7.rst:    -> ./python.exe argparse-example.py -v -o /tmp/output -C 4 file1 file2
whatsnew/2.7.rst:    {'output': '/tmp/output',
whatsnew/2.4.rst:   sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
whatsnew/2.4.rst:   sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)
whatsnew/2.5.rst:     dest = mailbox.mbox('/tmp/mbox')
whatsnew/2.5.rst::file:`/tmp/example` file::
whatsnew/2.5.rst:   conn = sqlite3.connect('/tmp/example')

I can't change the status of resolution.
msg107052 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2010-06-04 13:45
Other logging cases contained /tmp/ has now been removed, the missing parenthesis added and the result checked in to trunk (r81684). 

I'll keep the issue open for the cases which remain in the other documentation. but remove myself from the assigned-to and change the resolution to "accepted".
msg107053 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-06-04 13:47
Thanks for the listing Henri. Not all of these examples have to be changed; I’ll review them in some days if you want.
msg107061 - (view) Author: Henri Salo (Henri.Salo) Date: 2010-06-04 14:56
Please review the changes for the quality of the documentation. There probably is still more places to change. References can be made to: <http://docs.python.org/library/tempfile.html#tempfile.mkstemp>
msg107110 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2010-06-04 23:16
Henri, the owasp link you gave in your opening post now gives Bad Title error msg.
msg107164 - (view) Author: Henri Salo (Henri.Salo) Date: 2010-06-05 23:47
No it does not.

http://www.owasp.org/index.php/Insecure_Temporary_File
msg121527 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-11-19 14:54
Who wants to make a patch to update the documentation?

For command-line examples (like “python setup.py install --install-base /tmp”), someone has to research what standard variable to use (TMPDIR, TMP, something else?).
msg121528 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-11-19 15:04
Patch submission guidelines are found at http://www.python.org/dev/patches/

Since patches are made for the py3k branch, some matches in Henri’s grep won’t get patched: bsddb, compiler, posixfile and rexec have been removed.  The person that will commit the patch will have to edit those too when merging into 2.7, unless a kind soul provides one patch per branch (not a requirement).

Last remark: tempfile is a false positive; editing old whatsnew is not worth it IMO.
msg121732 - (view) Author: Mauro Navarro Baraldi (maurobaraldi) Date: 2010-11-20 19:31
Replace to most use of /tmp/tempfile for just tempfile, as sugested before.
msg121955 - (view) Author: Mauro Navarro Baraldi (maurobaraldi) Date: 2010-11-21 18:23
Reviewing this thread and talking with another friends, I thought that the pythonic way to solve it should be use the tempfile module.

And here is a suggestion using the logging module with tempfile.

> import logging
> import tempfile
> fp, LOG_FILENAME = tempfile.mkstemp(suffix=".log")
> logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
> logging.debug('This message should go to the log file')
> LOG_FILENAME
'/tmp/tmprBhZz1.log'
msg122114 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2010-11-22 12:18
Actually, I don't think it's a great idea in general to use temporary files for logging, though of course there are specific cases where one might do this. So for the logging examples in the docs (which used '/tmp/XXX') I just removed the '/tmp/' part.
msg122124 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2010-11-22 13:59
Whatsnew documents are not edited after the corresponding release is done.

Using either /home/user or tempfile depending on the example seems good to me.
msg122128 - (view) Author: anatoly techtonik (techtonik) Date: 2010-11-22 14:35
On Mon, Nov 22, 2010 at 3:59 PM, Éric Araujo <report@bugs.python.org> wrote:
>
> Using either /home/user or tempfile depending on the example seems good to me.

There is no /home/user on Windows.
msg139174 - (view) Author: Dave King (davbo) Date: 2011-06-26 12:44
Spotted another use of /tmp/ in the logging howto. Attached a diff.
msg139176 - (view) Author: Roundup Robot (python-dev) Date: 2011-06-26 13:29
New changeset 1ed71544fceb by Raymond Hettinger in branch '3.2':
Issue #8890: Remove /tmp from examples.
http://hg.python.org/cpython/rev/1ed71544fceb

New changeset fcf242243d46 by Raymond Hettinger in branch 'default':
Issue #8890: Remove /tmp from examples.
http://hg.python.org/cpython/rev/fcf242243d46
msg139183 - (view) Author: engelbert gruber (grubert) * Date: 2011-06-26 14:51
Assumption:

  /tmp is used in examples so the examples work 
  because /tmp is always writeable

module tempfile is for creating temporary files, the name of which is unimported, when a user is trying code from documentation it might be hard on him/her to additionally guess/save the random filenames.

``grep tmp -r CPython3.3/Doc`` (trimmed results and grouped)

* Doc/distutils/install.rst, Doc/install/install.rst:

  e.g. ``--install-base=/tmp`` 

  maybe ``--install-base=<other-python-base-directory>``
  if someone installs to another directory, one has a reason and 
  therefore knows the directory.

* all other e.g. ::

    Doc/library/sqlite3.rst::file:`/tmp/example` file::
    Doc/library/sqlite3.rst:   conn = sqlite3.connect('/tmp/example')

  use ``/tmp`` because it is writeable, but assuming the user wants
  to program i think it is not so big a burden to assume him/her to
  grasp the concept of directories, files and write protection.

  So either it can be left out, as in sqlite3.rst, maybe a file 
  extension would be more helpful, or replaced by a placeholder
  like ``<my-log-directory>`` or ``<directory-for-tempfiles>``.

  I am unsure about the ``<>`` chars ?

list of files:

Doc/distutils/install.rst
Doc/documenting/fromlatex.rst
Doc/howto/logging-cookbook.rst
Doc/install/install.rst
Doc/library/atexit.rst
Doc/library/cgi.rst
Doc/library/imghdr.rst
Doc/library/mailcap.rst
Doc/library/nntplib.rst
Doc/library/optparse.rst
Doc/library/packaging.database.rst
Doc/library/packaging.pypi.simple.rst
Doc/library/pipes.rst
Doc/library/sqlite3.rst
Doc/library/tempfile.rst
Doc/library/trace.rst
Doc/library/zipimport.rst
Doc/tools/sphinxext/susp-ignored.csv
Doc/tutorial/inputoutput.rst

So which way ?
msg154744 - (view) Author: Petri Lehtinen (petri.lehtinen) * (Python committer) Date: 2012-03-02 07:27
I think this issue was closed too hastily. Only the logging documentation has been fixed.

@grubert: I agree with the assumption that /tmp is mostly used because it's writable. In my opinion, the directory could just be left out and only leave the file name.
msg182768 - (view) Author: Geoff Wilson (gmwils) * Date: 2013-02-23 17:06
Patch for 2.7, with most references to /tmp removed or replaced.

References remain in Doc/install/index.rst and Doc/library/rexec.rst as they seem to make sense in context.
msg182779 - (view) Author: Geoff Wilson (gmwils) * Date: 2013-02-23 17:45
Attaching patch for 3.2 (Issue8890-3.2.patch)
msg182780 - (view) Author: Geoff Wilson (gmwils) * Date: 2013-02-23 17:46
Attaching patch for 3.3 that also works for 3.4/default (Issue8890-3.3.patch)
msg182789 - (view) Author: Roundup Robot (python-dev) Date: 2013-02-23 18:39
New changeset 488957f9b664 by Petri Lehtinen in branch '2.7':
Issue #8890: Stop advertising an insecure use of /tmp in docs
http://hg.python.org/cpython/rev/488957f9b664

New changeset 7556601180c8 by Petri Lehtinen in branch '3.2':
Issue #8890: Stop advertising an insecure use of /tmp in docs
http://hg.python.org/cpython/rev/7556601180c8

New changeset 18e20e146396 by Petri Lehtinen in branch '3.3':
Issue #8890: Stop advertising an insecure use of /tmp in docs
http://hg.python.org/cpython/rev/18e20e146396

New changeset 6b0ca4cb7e4e by Petri Lehtinen in branch 'default':
Issue #8890: Stop advertising an insecure use of /tmp in docs
http://hg.python.org/cpython/rev/6b0ca4cb7e4e
msg182790 - (view) Author: Petri Lehtinen (petri.lehtinen) * (Python committer) Date: 2013-02-23 18:40
Applied, thanks!
History
Date User Action Args
2013-02-23 18:40:07petri.lehtinensetstatus: open -> closed
versions: + Python 3.4
messages: + msg182790

resolution: accepted -> fixed
stage: patch review -> resolved
2013-02-23 18:39:04python-devsetmessages: + msg182789
2013-02-23 17:46:11gmwilssetfiles: + Issue8890-3.3.patch

messages: + msg182780
2013-02-23 17:45:31gmwilssetfiles: + Issue8890-3.2.patch

messages: + msg182779
2013-02-23 17:06:41gmwilssetfiles: + Issue8890.patch
nosy: + gmwils
messages: + msg182768

2012-03-02 07:27:51petri.lehtinensetstatus: closed -> open
versions: + Python 3.3, - Python 3.1
nosy: + petri.lehtinen

messages: + msg154744
2011-06-26 14:51:18grubertsetnosy: + grubert
messages: + msg139183
2011-06-26 13:30:07rhettingersetstatus: open -> closed
2011-06-26 13:29:43python-devsetnosy: + python-dev
messages: + msg139176
2011-06-26 12:44:26davbosetfiles: + tmp_logging_howto.diff
nosy: + davbo
messages: + msg139174

2010-11-22 14:35:08techtoniksetmessages: + msg122128
2010-11-22 13:59:39eric.araujosetmessages: + msg122124
stage: needs patch -> patch review
2010-11-22 12:18:34vinay.sajipsetmessages: + msg122114
2010-11-21 18:41:43eric.araujosetassignee: docs@python
components: + Documentation, - Demos and Tools
nosy: terry.reedy, vinay.sajip, techtonik, eric.araujo, docs@python, Henri.Salo, maurobaraldi
2010-11-21 18:23:26maurobaraldisetnosy: terry.reedy, vinay.sajip, techtonik, eric.araujo, docs@python, Henri.Salo, maurobaraldi
messages: + msg121955
components: + Demos and Tools, - Documentation
2010-11-20 19:31:20maurobaraldisetfiles: + py3k-docs.patch

nosy: + maurobaraldi
messages: + msg121732

keywords: + patch
2010-11-19 15:04:21eric.araujosetmessages: + msg121528
2010-11-19 14:54:49eric.araujosetversions: - Python 2.6
title: Modules have dangerous examples in documentation -> Use tempfile instead of /tmp in examples
messages: + msg121527

keywords: + easy
stage: needs patch
2010-06-05 23:47:32Henri.Salosetmessages: + msg107164
2010-06-04 23:16:21terry.reedysetnosy: + terry.reedy
messages: + msg107110
2010-06-04 14:56:21Henri.Salosettitle: Module logging has dangerous examples -> Modules have dangerous examples in documentation
2010-06-04 14:56:00Henri.Salosetmessages: + msg107061
2010-06-04 13:47:25eric.araujosetmessages: + msg107053
2010-06-04 13:45:13vinay.sajipsetassignee: vinay.sajip -> (no value)
messages: + msg107052
resolution: fixed -> accepted
nosy: vinay.sajip, techtonik, eric.araujo, docs@python, Henri.Salo
2010-06-04 08:04:31Henri.Salosetmessages: + msg107016
2010-06-04 07:33:42Henri.Salosetstatus: closed -> open

messages: + msg107012
2010-06-03 22:39:32eric.araujosetmessages: + msg106995
2010-06-03 22:35:36vinay.sajipsetstatus: open -> closed

nosy: + vinay.sajip
messages: + msg106994

assignee: docs@python -> vinay.sajip
resolution: fixed
2010-06-03 21:55:36eric.araujosetmessages: + msg106988
2010-06-03 21:50:59techtoniksetnosy: + techtonik
messages: + msg106987
2010-06-03 21:36:20eric.araujosetversions: + Python 3.1, Python 2.7, Python 3.2
nosy: + docs@python, eric.araujo

messages: + msg106985

assignee: docs@python
components: + Documentation, - None
2010-06-03 21:11:53Henri.Salocreate