Skip to content

Commit 9a9d902

Browse files
committed
Add support for os.tempnam and os.tmpnam.
1 parent 1d15d46 commit 9a9d902

File tree

4 files changed

+42
-17
lines changed

4 files changed

+42
-17
lines changed

python/ql/src/Security/CWE-377/InsecureTemporaryFile.qhelp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33

44
<overview>
55
<p>
6-
Creating a new temporary file using the <code>mktemp</code> function in the
7-
<code>tempfile</code> does not ensure exclusive access to the file, as it simply
8-
returns a filename that is guaranteed to be unique at the point when
9-
<code>mktemp</code> returns. Opening a file with this name must then happen
10-
separately, and there is no guarantee that these operations will happen
11-
atomically. Because of this, it may be possible for an attacker to interfere
12-
with the file before it is opened.
6+
Functions that create temporary file names (such as <code>tempfile.mktemp</code>
7+
and <code>os.tempnam</code>) are fundamentally insecure, as they do not
8+
ensure exclusive access to a file with the temporary name they return.
9+
The file name returned by these functions is guaranteed to be unique on
10+
creation but the file must be opened in a separate operation. There is no
11+
guarantee that the creation and open operations will happen atomically. This
12+
provides an opportunity for an attacker to interfere with the file before it is
13+
opened.
1314
</p>
1415
<p>
1516
Note that <code>mktemp</code> has been deprecated since Python 2.3.
@@ -28,8 +29,8 @@ file is intended to be accessed from other processes, consider using the
2829
<example>
2930
<p>
3031
The following piece of code opens a temporary file and writes a set of results
31-
to it. Because the filename is created using <code>mktemp</code>, another
32-
process may have accessed this file before it is opened using <code>open</code>.
32+
to it. Because the file name is created using <code>mktemp</code>, another
33+
process may access this file before it is opened using <code>open</code>.
3334
</p>
3435
<sample src="InsecureTemporaryFile.py" />
3536

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @name Insecure temporary file
3-
* @description Creating a temporary file using mktemp may be insecure.
3+
* @description Creating a temporary file name may be insecure.
44
* @id py/insecure-temporary-file
55
* @problem.severity error
66
* @sub-severity high
@@ -11,10 +11,21 @@
1111

1212
import python
1313

14-
FunctionObject mktemp() {
15-
result = any(ModuleObject m | m.getName() = "tempfile").getAttribute("mktemp")
14+
FunctionObject temporary_name_function(string mod, string function) {
15+
(
16+
mod = "tempfile" and function = "mktemp"
17+
or
18+
mod = "os" and
19+
(
20+
function = "tmpnam"
21+
or
22+
function = "tempnam"
23+
)
24+
) and
25+
result = any(ModuleObject m | m.getName() = mod).getAttribute(function)
1626
}
1727

18-
from CallNode c
19-
where c.getFunction().refersTo(mktemp())
20-
select c, "Call to deprecated function mktemp may be insecure."
28+
from CallNode c, string mod, string function
29+
where
30+
c.getFunction().refersTo(temporary_name_function(mod, function))
31+
select c, "Call to deprecated function $@.$@ may be insecure.", mod, function
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| InsecureTemporaryFile.py:4:16:4:23 | ControlFlowNode for mktemp() | Call to deprecated function mktemp may be insecure. |
1+
| InsecureTemporaryFile.py:5:16:5:23 | ControlFlowNode for mktemp() | Call to deprecated function $@.$@ may be insecure. | tempfile | mktemp |
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
from tempfile import mktemp
2+
import os
23

3-
def write_results(results):
4+
def write_results1(results):
45
filename = mktemp()
56
with open(filename, "w+") as f:
67
f.write(results)
78
print("Results written to", filename)
9+
10+
def write_results2(results):
11+
filename = os.tempnam()
12+
with open(filename, "w+") as f:
13+
f.write(results)
14+
print("Results written to", filename)
15+
16+
def write_results3(results):
17+
filename = os.tmpnam()
18+
with open(filename, "w+") as f:
19+
f.write(results)
20+
print("Results written to", filename)

0 commit comments

Comments
 (0)