Skip to content

fix: detect unsafe tarfile.extract() in B202#1414

Open
dashitongzhi wants to merge 1 commit into
PyCQA:mainfrom
dashitongzhi:fix/b202-tarfile-extract
Open

fix: detect unsafe tarfile.extract() in B202#1414
dashitongzhi wants to merge 1 commit into
PyCQA:mainfrom
dashitongzhi:fix/b202-tarfile-extract

Conversation

@dashitongzhi
Copy link
Copy Markdown

Summary

B202 (tarfile_unsafe_members) previously only detected unsafe tarfile.extractall() calls, missing the equally dangerous tarfile.extract() usage pattern (reported in #1392).

Problem

The condition "extractall" in context.call_function_name uses substring matching, which correctly matches "extractall" but does not match bare "extract". An attacker exploiting a vulnerable tarfile.extract() loop with malicious member names (e.g., path traversal via ../) would go undetected.

Changes

  • Match both extract and extractall by changing the condition to an exact-set check: context.call_function_name in ("extract", "extractall")
  • Guard the members keyword check to only apply for extractall (since extract() does not accept a members parameter)
  • Update docstring title and description to reflect coverage of both methods
  • Update severity message to be generic ("Unsafe tarfile extraction") rather than specifically referencing extractall
  • Add example unsafe_extract_handler() in examples/tarfile_extractall.py

Test plan

Reproduce the issue from #1392 and verify B202 now fires for tarfile.extract():

cat > /tmp/repro.py <<'PY'
import tarfile, tempfile
tar = tarfile.open("test.tar.gz")
for member in tar.getmembers():
    tar.extract(member, path=tempfile.mkdtemp())
tar.close()
PY
bandit -t B202 /tmp/repro.py

Closes #1392

B202 previously only checked for tarfile.extractall() calls, missing
the equally dangerous tarfile.extract() which can also be exploited
for path traversal attacks (CWE-22).

Changes:
- Match both 'extract' and 'extractall' in the call function name check
- Only check 'members' keyword for extractall (extract doesn't accept it)
- Update docstring and example to document extract() coverage
- Update severity message to be generic for both patterns

Closes PyCQA#1392
Copilot AI review requested due to automatic review settings May 12, 2026 01:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands Bandit’s B202 (tarfile_unsafe_members) plugin to also flag unsafe tarfile.extract() usage (in addition to extractall()), addressing the false negative reported in #1392.

Changes:

  • Update B202 detection to match both extract and extractall, and scope the members keyword handling to extractall only.
  • Generalize the HIGH-severity issue text to cover unsafe tar extraction broadly.
  • Add an unsafe_extract_handler() example to examples/tarfile_extractall.py.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
bandit/plugins/tarfile_unsafe_members.py Extends B202 detection to include extract() and updates messaging/docs.
examples/tarfile_extractall.py Adds an extract()-based unsafe example intended to trigger B202.
Comments suppressed due to low confidence (1)

bandit/plugins/tarfile_unsafe_members.py:16

  • The docstring severity breakdown still only describes extractall()/members=... cases. Since the plugin now also flags extract(), please update this section to document how extract() is classified (likely always HIGH because there is no members/filter mitigation path in this plugin for extract()).
Severity are set as follows:

* ``tarfile.extractall(members=function(tarfile))`` - LOW
* ``tarfile.extractall(members=?)`` - member is not a function - MEDIUM
* ``tarfile.extractall()`` - members from the archive is trusted - HIGH

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 108 to 112
if all(
[
context.is_module_imported_exact("tarfile"),
"extractall" in context.call_function_name,
context.call_function_name in ("extract", "extractall"),
]

def unsafe_extract_handler(filename):
tar = tarfile.open(filename)
for member in tar.getmembers():
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

False negative: B202 unsafe tarfile.extract() not detected

2 participants