CVE-2014-1858 (Python, published 2018-01-08T19:29Z)
Description: value: __init__.py in f2py in NumPy before 1.8.1 allows local users to write to arbitrary files via a symlink attack on a temporary file.
Severity: LOW (CVSS v3 base score: 5.5)
Weakness: CWE-20 \u2014 Improper Input Validation
The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
Repository: https://github.com/numpy/numpy
Files changed:
numpy/core/tests/test_memmap.py
numpy/core/tests/test_multiarray.py
numpy/f2py/__init__.py
numpy/f2py/f2py2e.py
numpy/lib/tests/test_io.py
Commit message: ENH: remove insecure mktemp use

mktemp only returns a filename, a malicous user could replace it before
it gets used.


Vulnerable code:
from tempfile import NamedTemporaryFile, TemporaryFile, mktemp
        tmpname = mktemp('', 'mmap')
        fp = memmap(tmpname, dtype=self.dtype, mode='w+',
                       shape=self.shape)
        fp[:] = self.data[:]
        del fp
        os.unlink(tmpname)
        tmpname = mktemp('', 'mmap')
        fp = memmap(tmpname, dtype=self.dtype, mode='w+',
                       shape=self.shape)
        abspath = os.path.abspath(tmpname)
        fp[:] = self.data[:]
        self.assertEqual(abspath, fp.filename)
        b = fp[:1]
        self.assertEqual(abspath, b.filename)
        del b
        del fp
        os.unlink(tmpname)
        self.filename = tempfile.mktemp()
        if os.path.isfile(self.filename):
            os.unlink(self.filename)
            #tmp_file.close()
        os.unlink(self.filename)
        os.unlink(self.filename)

        os.unlink(self.filename)

        os.unlink(self.filename)
        fname = os.path.join(tempfile.mktemp()+'.f')
        fname = source_fn

    f = open(fname, 'w')
    f.write(source)
    f.close()

    args = ' -c -m %s %s %s'%(modulename, fname, extra_args)
    c = '%s -c "import numpy.f2py as f2py2e;f2py2e.main()" %s' %(sys.executable, args)
    s, o = exec_command(c)
    if source_fn is None:
        try: os.remove(fname)
        except OSError: pass
                   Default is tempfile.mktemp().
        build_dir = os.path.join(tempfile.mktemp())
from tempfile import mkstemp, mktemp, NamedTemporaryFile
        tmp = mktemp(suffix='.npz')
        np.savez(tmp, a=a)
        del a
        npfile = np.load(tmp)
        a = npfile['a']
        npfile.close()
        os.remove(tmp)

Fixed code:
from tempfile import NamedTemporaryFile, TemporaryFile
        with NamedTemporaryFile() as tmp:
            fp = memmap(tmp.name, dtype=self.dtype, mode='w+',
                        shape=self.shape)
            fp[:] = self.data[:]
            del fp
        with NamedTemporaryFile() as tmp:
            fp = memmap(tmp.name, dtype=self.dtype, mode='w+',
                        shape=self.shape)
            abspath = os.path.abspath(tmp.name)
            fp[:] = self.data[:]
            self.assertEqual(abspath, fp.filename)
            b = fp[:1]
            self.assertEqual(abspath, b.filename)
            del b
            del fp
        self.file = tempfile.NamedTemporaryFile()
        self.filename = self.file.name
        self.file.close()
        f = tempfile.NamedTemporaryFile(suffix='.f')
        f = open(source_fn, 'w')

    try:
        f.write(source)
        f.flush()

        args = ' -c -m %s %s %s'%(modulename, f.name, extra_args)
        c = '%s -c "import numpy.f2py as f2py2e;f2py2e.main()" %s' % \
                (sys.executable, args)
        s, o = exec_command(c)
    finally:
        f.close()
                   Default is tempfile.mkdtemp().
        build_dir = tempfile.mkdtemp()
import shutil
import contextlib
from tempfile import mkstemp, mkdtemp, NamedTemporaryFile
@contextlib.contextmanager
def tempdir(change_dir=False):
    tmpdir = mkdtemp()
    yield tmpdir
    shutil.rmtree(tmpdir)

        with tempdir() as tmpdir:
            tmp = open(os.path.join(tmpdir, "file.npz"), "w")
            np.savez(tmp, a=a)
            del a
            npfile = np.load(tmp)
            a = npfile['a']
            npfile.close()