
When an include is not surrounded by empty lines, its content is inlined on the same line as the adjacent content. That can lead to broken tags and other display issues. This PR fixes all such includes and introduces a validation step that forbids introducing the same problem again.
150 lines
4.2 KiB
Plaintext
150 lines
4.2 KiB
Plaintext
Handling files is security-sensitive. It has led in the past to the following vulnerabilities:
|
|
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-0358[CVE-2018-0358]
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7560[CVE-2017-7560]
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-4015[CVE-2005-4015]
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3835[CVE-2018-3835]
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8008[CVE-2018-8008]
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2320[CVE-2010-2320]
|
|
|
|
Any access to the file system can create a vulnerability. Exposing a file's content, path or even its existence or absence is dangerous. It is also extremely risky to create or write files without making sure that their permission and content is safe and controlled. Using a file path or reading a file content must be always done with caution as they could have been tampered with.
|
|
|
|
|
|
The file system is a resource which can be easily exhausted. Opening too many files will use up all file descriptors, preventing other software from opening files. Filling the storage space will also prevent any additional write from happening.
|
|
|
|
|
|
This rule raises an issue when a function accessing the filesystem via a path-like object is called. It does not raise issues on already opened files access (ex: ``++file.readline()++``) because an issue is already raised by functions opening files (ex: ``++file = open(path)++``) The goal is to guide manual security code reviews by pointing to the initial filesystem access.
|
|
|
|
include::../ask-yourself.adoc[]
|
|
|
|
include::../recommended.adoc[]
|
|
|
|
== Sensitive Code Example
|
|
|
|
``++open++`` builtin
|
|
|
|
----
|
|
open(path, 'r') # Sensitive
|
|
----
|
|
|
|
``++fileinput++`` module
|
|
|
|
----
|
|
import fileinput
|
|
|
|
for line in fileinput.input(): # Sensitive
|
|
pass
|
|
|
|
with fileinput.FileInput(files=('setup.py', 'test.txt')) as file: # Sensitive
|
|
pass
|
|
----
|
|
|
|
``++linecache++`` module
|
|
|
|
----
|
|
import linecache
|
|
|
|
linecache.getline('setup.py', 5) # Sensitive
|
|
----
|
|
|
|
``++os++`` module.
|
|
|
|
----
|
|
import os
|
|
|
|
def access_filesystem(path, file_descriptor, mode, uid):
|
|
os.open(path, os.O_RDONLY) # Sensitive
|
|
os.chmod(path, mode) # Sensitive
|
|
os.chown(path, uid) # Sensitive
|
|
os.lchmod(path, mode) # Sensitive
|
|
os.lchown(path, uid) # Sensitive
|
|
os.chroot(path) # Sensitive
|
|
os.fdopen(file_descriptor) # Sensitive
|
|
os.link(path, path) # Sensitive
|
|
os.symlink(path, path) # Sensitive
|
|
os.mkdir(path, mode) # Sensitive
|
|
os.mkdir(path) # Sensitive
|
|
os.makedirs(path) # Sensitive
|
|
os.mkfifo(path) # Sensitive
|
|
os.mknod(path) # Sensitive
|
|
os.remove(path) # Sensitive
|
|
os.removedirs(path) # Sensitive
|
|
os.rename(path) # Sensitive
|
|
os.renames(path) # Sensitive
|
|
os.replace(path) # Sensitive
|
|
os.rmdir(path) # Sensitive
|
|
os.truncate(path, 42) # Sensitive
|
|
os.unlink(path) # Sensitive
|
|
----
|
|
|
|
``++pathlib++`` module
|
|
|
|
----
|
|
from pathlib import Path, PosixPath, WindowsPath
|
|
|
|
path = 'test.txt'
|
|
Path(path) # Sensitive
|
|
PosixPath(path) # Sensitive
|
|
WindowsPath(path) # Sensitive
|
|
----
|
|
|
|
``++shutil++`` module
|
|
|
|
----
|
|
import shutil
|
|
|
|
path1 = '/tmp/test1.txt'
|
|
path2 = '/tmp/test2.txt'
|
|
|
|
shutil.copyfile(path1, path2) # Sensitive
|
|
|
|
shutil.copymode(path1, path2) # Sensitive
|
|
|
|
shutil.copystat(path1, path2) # Sensitive
|
|
|
|
shutil.copy(path1, path2) # Sensitive
|
|
shutil.copy2(path1, path2) # Sensitive
|
|
|
|
shutil.copytree('/tmp/dir1', '/tmp/dir2') # Sensitive
|
|
shutil.rmtree('/tmp/mydir') # Sensitive
|
|
shutil.move('/tmp/dir3', '/tmp/dir4') # Sensitive
|
|
shutil.chown(path1) # Sensitive
|
|
|
|
shutil.make_archive('/tmp/archive', 'gztar', '/tmp/dir1') # Sensitive
|
|
shutil.unpack_archive('/tmp/archive.tar.gz') # Sensitive
|
|
----
|
|
|
|
``++tempfile++`` module. Accessing temporary files is also risky.
|
|
|
|
----
|
|
import tempfile
|
|
|
|
tempfile.TemporaryFile() # Sensitive
|
|
|
|
tempfile.NamedTemporaryFile() # Sensitive
|
|
|
|
tempfile.SpooledTemporaryFile() # Sensitive
|
|
|
|
tempfile.mkstemp() # Sensitive
|
|
|
|
tempfile.mktemp() # Sensitive and usually dangerous. Use tempfile.mkstemp instead.
|
|
----
|
|
|
|
include::../see.adoc[]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
include::../message.adoc[]
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::../comments-and-links.adoc[]
|
|
|
|
endif::env-github,rspecator-view[]
|