tarfile_unsafe_members.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #
  2. # SPDX-License-Identifier: Apache-2.0
  3. #
  4. r"""
  5. =================================
  6. B202: Test for tarfile.extractall
  7. =================================
  8. This plugin will look for usage of ``tarfile.extractall()``
  9. Severity are set as follows:
  10. * ``tarfile.extractalll(members=function(tarfile))`` - LOW
  11. * ``tarfile.extractalll(members=?)`` - member is not a function - MEDIUM
  12. * ``tarfile.extractall()`` - members from the archive is trusted - HIGH
  13. Use ``tarfile.extractall(members=function_name)`` and define a function
  14. that will inspect each member. Discard files that contain a directory
  15. traversal sequences such as ``../`` or ``\..`` along with all special filetypes
  16. unless you explicitly need them.
  17. :Example:
  18. .. code-block:: none
  19. >> Issue: [B202:tarfile_unsafe_members] tarfile.extractall used without
  20. any validation. You should check members and discard dangerous ones
  21. Severity: High Confidence: High
  22. CWE: CWE-22 (https://cwe.mitre.org/data/definitions/22.html)
  23. Location: examples/tarfile_extractall.py:8
  24. More Info:
  25. https://bandit.readthedocs.io/en/latest/plugins/b202_tarfile_unsafe_members.html
  26. 7 tar = tarfile.open(filename)
  27. 8 tar.extractall(path=tempfile.mkdtemp())
  28. 9 tar.close()
  29. .. seealso::
  30. - https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall
  31. - https://docs.python.org/3/library/tarfile.html#tarfile.TarInfo
  32. .. versionadded:: 1.7.5
  33. """
  34. import ast
  35. import bandit
  36. from bandit.core import issue
  37. from bandit.core import test_properties as test
  38. def exec_issue(level, members=""):
  39. if level == bandit.LOW:
  40. return bandit.Issue(
  41. severity=bandit.LOW,
  42. confidence=bandit.LOW,
  43. cwe=issue.Cwe.PATH_TRAVERSAL,
  44. text="Usage of tarfile.extractall(members=function(tarfile)). "
  45. "Make sure your function properly discards dangerous members "
  46. "{members}).".format(members=members),
  47. )
  48. elif level == bandit.MEDIUM:
  49. return bandit.Issue(
  50. severity=bandit.MEDIUM,
  51. confidence=bandit.MEDIUM,
  52. cwe=issue.Cwe.PATH_TRAVERSAL,
  53. text="Found tarfile.extractall(members=?) but couldn't "
  54. "identify the type of members. "
  55. "Check if the members were properly validated "
  56. "{members}).".format(members=members),
  57. )
  58. else:
  59. return bandit.Issue(
  60. severity=bandit.HIGH,
  61. confidence=bandit.HIGH,
  62. cwe=issue.Cwe.PATH_TRAVERSAL,
  63. text="tarfile.extractall used without any validation. "
  64. "Please check and discard dangerous members.",
  65. )
  66. def get_members_value(context):
  67. for keyword in context.node.keywords:
  68. if keyword.arg == "members":
  69. arg = keyword.value
  70. if isinstance(arg, ast.Call):
  71. return {"Function": arg.func.id}
  72. else:
  73. value = arg.id if isinstance(arg, ast.Name) else arg
  74. return {"Other": value}
  75. @test.test_id("B202")
  76. @test.checks("Call")
  77. def tarfile_unsafe_members(context):
  78. if all(
  79. [
  80. context.is_module_imported_exact("tarfile"),
  81. "extractall" in context.call_function_name,
  82. ]
  83. ):
  84. if "members" in context.call_keywords:
  85. members = get_members_value(context)
  86. if "Function" in members:
  87. return exec_issue(bandit.LOW, members)
  88. else:
  89. return exec_issue(bandit.MEDIUM, members)
  90. return exec_issue(bandit.HIGH)