| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- #
- # SPDX-License-Identifier: Apache-2.0
- #
- r"""
- =================================
- B202: Test for tarfile.extractall
- =================================
- This plugin will look for usage of ``tarfile.extractall()``
- Severity are set as follows:
- * ``tarfile.extractalll(members=function(tarfile))`` - LOW
- * ``tarfile.extractalll(members=?)`` - member is not a function - MEDIUM
- * ``tarfile.extractall()`` - members from the archive is trusted - HIGH
- Use ``tarfile.extractall(members=function_name)`` and define a function
- that will inspect each member. Discard files that contain a directory
- traversal sequences such as ``../`` or ``\..`` along with all special filetypes
- unless you explicitly need them.
- :Example:
- .. code-block:: none
- >> Issue: [B202:tarfile_unsafe_members] tarfile.extractall used without
- any validation. You should check members and discard dangerous ones
- Severity: High Confidence: High
- CWE: CWE-22 (https://cwe.mitre.org/data/definitions/22.html)
- Location: examples/tarfile_extractall.py:8
- More Info:
- https://bandit.readthedocs.io/en/latest/plugins/b202_tarfile_unsafe_members.html
- 7 tar = tarfile.open(filename)
- 8 tar.extractall(path=tempfile.mkdtemp())
- 9 tar.close()
- .. seealso::
- - https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall
- - https://docs.python.org/3/library/tarfile.html#tarfile.TarInfo
- .. versionadded:: 1.7.5
- """
- import ast
- import bandit
- from bandit.core import issue
- from bandit.core import test_properties as test
- def exec_issue(level, members=""):
- if level == bandit.LOW:
- return bandit.Issue(
- severity=bandit.LOW,
- confidence=bandit.LOW,
- cwe=issue.Cwe.PATH_TRAVERSAL,
- text="Usage of tarfile.extractall(members=function(tarfile)). "
- "Make sure your function properly discards dangerous members "
- "{members}).".format(members=members),
- )
- elif level == bandit.MEDIUM:
- return bandit.Issue(
- severity=bandit.MEDIUM,
- confidence=bandit.MEDIUM,
- cwe=issue.Cwe.PATH_TRAVERSAL,
- text="Found tarfile.extractall(members=?) but couldn't "
- "identify the type of members. "
- "Check if the members were properly validated "
- "{members}).".format(members=members),
- )
- else:
- return bandit.Issue(
- severity=bandit.HIGH,
- confidence=bandit.HIGH,
- cwe=issue.Cwe.PATH_TRAVERSAL,
- text="tarfile.extractall used without any validation. "
- "Please check and discard dangerous members.",
- )
- def get_members_value(context):
- for keyword in context.node.keywords:
- if keyword.arg == "members":
- arg = keyword.value
- if isinstance(arg, ast.Call):
- return {"Function": arg.func.id}
- else:
- value = arg.id if isinstance(arg, ast.Name) else arg
- return {"Other": value}
- @test.test_id("B202")
- @test.checks("Call")
- def tarfile_unsafe_members(context):
- if all(
- [
- context.is_module_imported_exact("tarfile"),
- "extractall" in context.call_function_name,
- ]
- ):
- if "members" in context.call_keywords:
- members = get_members_value(context)
- if "Function" in members:
- return exec_issue(bandit.LOW, members)
- else:
- return exec_issue(bandit.MEDIUM, members)
- return exec_issue(bandit.HIGH)
|