CVE-2014-1859 (Python, published 2018-01-08T19:29Z)
Description: value: (1) core/tests/test_memmap.py, (2) core/tests/test_multiarray.py, (3) f2py/f2py2e.py, and (4) lib/tests/test_io.py in NumPy before 1.8.1 allow 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-59 \u2014 Improper Link Resolution Before File Access ('Link Following')
The product attempts to access a file based on the filename, but it does not properly prevent that filename from identifying a link or shortcut that resolves to an unintended resource.
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()