Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-bandit for openSUSE:Factory checked in at 2025-02-24 15:51:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-bandit (Old) and /work/SRC/openSUSE:Factory/.python-bandit.new.1873 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-bandit" Mon Feb 24 15:51:15 2025 rev:17 rq:1248121 version:1.8.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-bandit/python-bandit.changes 2025-02-03 21:46:13.709213976 +0100 +++ /work/SRC/openSUSE:Factory/.python-bandit.new.1873/python-bandit.changes 2025-02-24 15:51:49.950941967 +0100 @@ -1,0 +2,16 @@ +Mon Feb 24 10:23:19 UTC 2025 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to 1.8.3 + * Bump docker/build-push-action from 6.10.0 to 6.11.0 (#1220) + * Bump docker/build-push-action from 6.11.0 to 6.12.0 (#1221) + * Bump docker/build-push-action from 6.12.0 to 6.13.0 (#1222) + * [pre-commit.ci] pre-commit autoupdate (#1229) + * Update bug template to include latest released versions (#1218) + * Add markupsafe.Markup XSS plugin (#1225) + * Warn not error on an nonexistant test given (#1230) + * Bump sigstore/cosign-installer from 3.7.0 to 3.8.0 (#1233) + * Bump docker/setup-buildx-action from 3.8.0 to 3.9.0 (#1234) + * B107: Skip None values in hardcoded password detection (#1232) + * Pytorch fix (#1231) + +------------------------------------------------------------------- Old: ---- bandit-1.8.2.tar.gz New: ---- bandit-1.8.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-bandit.spec ++++++ --- /var/tmp/diff_new_pack.jYazGX/_old 2025-02-24 15:51:51.635012341 +0100 +++ /var/tmp/diff_new_pack.jYazGX/_new 2025-02-24 15:51:51.655013177 +0100 @@ -29,7 +29,7 @@ %bcond_without builddocs %{?sle15_python_module_pythons} Name: python-bandit -Version: 1.8.2 +Version: 1.8.3 Release: 0 Summary: Security oriented static analyser for Python code License: Apache-2.0 ++++++ bandit-1.8.2.tar.gz -> bandit-1.8.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/.github/ISSUE_TEMPLATE/bug-report.yml new/bandit-1.8.3/.github/ISSUE_TEMPLATE/bug-report.yml --- old/bandit-1.8.2/.github/ISSUE_TEMPLATE/bug-report.yml 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/.github/ISSUE_TEMPLATE/bug-report.yml 2025-02-17 06:24:38.000000000 +0100 @@ -44,7 +44,9 @@ label: Bandit version description: Run "bandit --version" if unsure of version number options: - - 1.8.0 (Default) + - 1.8.2 (Default) + - 1.8.1 + - 1.8.0 - 1.7.10 - 1.7.9 - 1.7.8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/.github/workflows/build-publish-image.yml new/bandit-1.8.3/.github/workflows/build-publish-image.yml --- old/bandit-1.8.2/.github/workflows/build-publish-image.yml 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/.github/workflows/build-publish-image.yml 2025-02-17 06:24:38.000000000 +0100 @@ -31,7 +31,7 @@ ref: ${{ github.event_name == 'release' && github.ref || env.RELEASE_TAG }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3 + uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3 - name: Log in to GitHub Container Registry uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3 @@ -41,7 +41,7 @@ password: ${{ secrets.GITHUB_TOKEN }} - name: Install Cosign - uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 + uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0 with: cosign-release: 'v2.2.2' @@ -51,7 +51,7 @@ - name: Build and push Docker image id: build-and-push - uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6 + uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6 with: context: . file: ./docker/Dockerfile diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/.pre-commit-config.yaml new/bandit-1.8.3/.pre-commit-config.yaml --- old/bandit-1.8.2/.pre-commit-config.yaml 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/.pre-commit-config.yaml 2025-02-17 06:24:38.000000000 +0100 @@ -13,7 +13,7 @@ - id: reorder-python-imports args: [--application-directories, '.:src', --py38-plus] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.10.0 + rev: 25.1.0 hooks: - id: black args: [--line-length=79, --target-version=py38] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/AUTHORS new/bandit-1.8.3/AUTHORS --- old/bandit-1.8.2/AUTHORS 2025-01-13 00:32:28.000000000 +0100 +++ new/bandit-1.8.3/AUTHORS 2025-02-17 06:24:41.000000000 +0100 @@ -37,6 +37,7 @@ Dave McCowan <dmcco...@cisco.com> Dave Walker (Daviey) <em...@daviey.com> David D Lowe <daviddlowe.fl...@gmail.com> +David Salvisberg <d...@daverball.com> David Vo <auscompg...@users.noreply.github.com> David Wyde <dw...@cisco.com> Deepika Gupta <deep...@cisco.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/ChangeLog new/bandit-1.8.3/ChangeLog --- old/bandit-1.8.2/ChangeLog 2025-01-13 00:32:28.000000000 +0100 +++ new/bandit-1.8.3/ChangeLog 2025-02-17 06:24:41.000000000 +0100 @@ -1,6 +1,21 @@ CHANGES ======= +1.8.3 +----- + +* Pytorch fix (#1231) +* B107: Skip None values in hardcoded password detection (#1232) +* Bump docker/setup-buildx-action from 3.8.0 to 3.9.0 (#1234) +* Bump sigstore/cosign-installer from 3.7.0 to 3.8.0 (#1233) +* Warn not error on an nonexistant test given (#1230) +* Add markupsafe.Markup XSS plugin (#1225) +* Update bug template to include latest released versions (#1218) +* [pre-commit.ci] pre-commit autoupdate (#1229) +* Bump docker/build-push-action from 6.12.0 to 6.13.0 (#1222) +* Bump docker/build-push-action from 6.11.0 to 6.12.0 (#1221) +* Bump docker/build-push-action from 6.10.0 to 6.11.0 (#1220) + 1.8.2 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/PKG-INFO new/bandit-1.8.3/PKG-INFO --- old/bandit-1.8.2/PKG-INFO 2025-01-13 00:32:28.271676500 +0100 +++ new/bandit-1.8.3/PKG-INFO 2025-02-17 06:24:41.568784500 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: bandit -Version: 1.8.2 +Version: 1.8.3 Summary: Security oriented static analyser for python code. Home-page: https://bandit.readthedocs.io/ Author: PyCQA diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit/core/context.py new/bandit-1.8.3/bandit/core/context.py --- old/bandit-1.8.2/bandit/core/context.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/bandit/core/context.py 2025-02-17 06:24:38.000000000 +0100 @@ -318,3 +318,7 @@ @property def file_data(self): return self._context.get("file_data") + + @property + def import_aliases(self): + return self._context.get("import_aliases") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit/core/extension_loader.py new/bandit-1.8.3/bandit/core/extension_loader.py --- old/bandit-1.8.2/bandit/core/extension_loader.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/bandit/core/extension_loader.py 2025-02-17 06:24:38.000000000 +0100 @@ -1,11 +1,14 @@ # # SPDX-License-Identifier: Apache-2.0 +import logging import sys from stevedore import extension from bandit.core import utils +LOG = logging.getLogger(__name__) + class Manager: # These IDs are for bandit built in tests @@ -84,11 +87,11 @@ """Validate that everything in the configured profiles looks good.""" for inc in profile["include"]: if not self.check_id(inc): - raise ValueError(f"Unknown test found in profile: {inc}") + LOG.warning(f"Unknown test found in profile: {inc}") for exc in profile["exclude"]: if not self.check_id(exc): - raise ValueError(f"Unknown test found in profile: {exc}") + LOG.warning(f"Unknown test found in profile: {exc}") union = set(profile["include"]) & set(profile["exclude"]) if len(union) > 0: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit/plugins/general_hardcoded_password.py new/bandit-1.8.3/bandit/plugins/general_hardcoded_password.py --- old/bandit-1.8.2/bandit/plugins/general_hardcoded_password.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/bandit/plugins/general_hardcoded_password.py 2025-02-17 06:24:38.000000000 +0100 @@ -201,7 +201,9 @@ - "token" - "secrete" - Note: this can be noisy and may generate false positives. + Note: this can be noisy and may generate false positives. We do not + report on None values which can be legitimately used as a default value, + when initializing a function or class. **Config Options:** @@ -242,5 +244,11 @@ # go through all (param, value)s and look for candidates for key, val in zip(context.node.args.args, defs): if isinstance(key, (ast.Name, ast.arg)): + # Skip if the default value is None + if val is None or ( + isinstance(val, (ast.Constant, ast.NameConstant)) + and val.value is None + ): + continue if isinstance(val, ast.Str) and RE_CANDIDATES.search(key.arg): return _report(val.s) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit/plugins/markupsafe_markup_xss.py new/bandit-1.8.3/bandit/plugins/markupsafe_markup_xss.py --- old/bandit-1.8.2/bandit/plugins/markupsafe_markup_xss.py 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/bandit/plugins/markupsafe_markup_xss.py 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,118 @@ +# Copyright (c) 2025 David Salvisberg +# +# SPDX-License-Identifier: Apache-2.0 +r""" +============================================ +B704: Potential XSS on markupsafe.Markup use +============================================ + +``markupsafe.Markup`` does not perform any escaping, so passing dynamic +content, like f-strings, variables or interpolated strings will potentially +lead to XSS vulnerabilities, especially if that data was submitted by users. + +Instead you should interpolate the resulting ``markupsafe.Markup`` object, +which will perform escaping, or use ``markupsafe.escape``. + + +**Config Options:** + +This plugin allows you to specify additional callable that should be treated +like ``markupsafe.Markup``. By default we recognize ``flask.Markup`` as +an alias, but there are other subclasses or similar classes in the wild +that you may wish to treat the same. + +Additionally there is a whitelist for callable names, whose result may +be safely passed into ``markupsafe.Markup``. This is useful for escape +functions like e.g. ``bleach.clean`` which don't themselves return +``markupsafe.Markup``, so they need to be wrapped. Take care when using +this setting, since incorrect use may introduce false negatives. + +These two options can be set in a shared configuration section +`markupsafe_xss`. + + +.. code-block:: yaml + + markupsafe_xss: + # Recognize additional aliases + extend_markup_names: + - webhelpers.html.literal + - my_package.Markup + + # Allow the output of these functions to pass into Markup + allowed_calls: + - bleach.clean + - my_package.sanitize + + +:Example: + +.. code-block:: none + + >> Issue: [B704:markupsafe_markup_xss] Potential XSS with + ``markupsafe.Markup`` detected. Do not use ``Markup`` + on untrusted data. + Severity: Medium Confidence: High + CWE: CWE-79 (https://cwe.mitre.org/data/definitions/79.html) + Location: ./examples/markupsafe_markup_xss.py:5:0 + 4 content = "<script>alert('Hello, world!')</script>" + 5 Markup(f"unsafe {content}") + 6 flask.Markup("unsafe {}".format(content)) + +.. seealso:: + + - https://pypi.org/project/MarkupSafe/ + - https://markupsafe.palletsprojects.com/en/stable/escaping/#markupsafe.Markup + - https://cwe.mitre.org/data/definitions/79.html + +.. versionadded:: 1.8.3 + +""" +import ast + +import bandit +from bandit.core import issue +from bandit.core import test_properties as test +from bandit.core.utils import get_call_name + + +def gen_config(name): + if name == "markupsafe_xss": + return { + "extend_markup_names": [], + "allowed_calls": [], + } + + +@test.takes_config("markupsafe_xss") +@test.checks("Call") +@test.test_id("B704") +def markupsafe_markup_xss(context, config): + + qualname = context.call_function_name_qual + if qualname not in ("markupsafe.Markup", "flask.Markup"): + if qualname not in config.get("extend_markup_names", []): + # not a Markup call + return None + + args = context.node.args + if not args or isinstance(args[0], ast.Constant): + # both no arguments and a constant are fine + return None + + allowed_calls = config.get("allowed_calls", []) + if ( + allowed_calls + and isinstance(args[0], ast.Call) + and get_call_name(args[0], context.import_aliases) in allowed_calls + ): + # the argument contains a whitelisted call + return None + + return bandit.Issue( + severity=bandit.MEDIUM, + confidence=bandit.HIGH, + cwe=issue.Cwe.XSS, + text=f"Potential XSS with ``{qualname}`` detected. Do " + f"not use ``{context.call_function_name}`` on untrusted data.", + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit/plugins/pytorch_load.py new/bandit-1.8.3/bandit/plugins/pytorch_load.py --- old/bandit-1.8.2/bandit/plugins/pytorch_load.py 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/bandit/plugins/pytorch_load.py 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,80 @@ +# Copyright (c) 2024 Stacklok, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +r""" +================================== +B614: Test for unsafe PyTorch load +================================== + +This plugin checks for unsafe use of `torch.load`. Using `torch.load` with +untrusted data can lead to arbitrary code execution. There are two safe +alternatives: +1. Use `torch.load` with `weights_only=True` where only tensor data is + extracted, and no arbitrary Python objects are deserialized +2. Use the `safetensors` library from huggingface, which provides a safe + deserialization mechanism + +With `weights_only=True`, PyTorch enforces a strict type check, ensuring +that only torch.Tensor objects are loaded. + +:Example: + +.. code-block:: none + + >> Issue: Use of unsafe PyTorch load + Severity: Medium Confidence: High + CWE: CWE-94 (https://cwe.mitre.org/data/definitions/94.html) + Location: examples/pytorch_load_save.py:8 + 7 loaded_model.load_state_dict(torch.load('model_weights.pth')) + 8 another_model.load_state_dict(torch.load('model_weights.pth', + map_location='cpu')) + 9 + 10 print("Model loaded successfully!") + +.. seealso:: + + - https://cwe.mitre.org/data/definitions/94.html + - https://pytorch.org/docs/stable/generated/torch.load.html#torch.load + - https://github.com/huggingface/safetensors + +.. versionadded:: 1.7.10 + +""" +import bandit +from bandit.core import issue +from bandit.core import test_properties as test + + +@test.checks("Call") +@test.test_id("B614") +def pytorch_load(context): + """ + This plugin checks for unsafe use of `torch.load`. Using `torch.load` + with untrusted data can lead to arbitrary code execution. The safe + alternative is to use `weights_only=True` or the safetensors library. + """ + imported = context.is_module_imported_exact("torch") + qualname = context.call_function_name_qual + if not imported and isinstance(qualname, str): + return + + qualname_list = qualname.split(".") + func = qualname_list[-1] + if all( + [ + "torch" in qualname_list, + func == "load", + ] + ): + # For torch.load, check if weights_only=True is specified + weights_only = context.get_call_arg_value("weights_only") + if weights_only == "True" or weights_only is True: + return + + return bandit.Issue( + severity=bandit.MEDIUM, + confidence=bandit.HIGH, + text="Use of unsafe PyTorch load", + cwe=issue.Cwe.DESERIALIZATION_OF_UNTRUSTED_DATA, + lineno=context.get_lineno_for_call_arg("load"), + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit/plugins/pytorch_load_save.py new/bandit-1.8.3/bandit/plugins/pytorch_load_save.py --- old/bandit-1.8.2/bandit/plugins/pytorch_load_save.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/bandit/plugins/pytorch_load_save.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,72 +0,0 @@ -# Copyright (c) 2024 Stacklok, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -r""" -========================================== -B614: Test for unsafe PyTorch load or save -========================================== - -This plugin checks for the use of `torch.load` and `torch.save`. Using -`torch.load` with untrusted data can lead to arbitrary code execution, and -improper use of `torch.save` might expose sensitive data or lead to data -corruption. A safe alternative is to use `torch.load` with the `safetensors` -library from hugingface, which provides a safe deserialization mechanism. - -:Example: - -.. code-block:: none - - >> Issue: Use of unsafe PyTorch load or save - Severity: Medium Confidence: High - CWE: CWE-94 (https://cwe.mitre.org/data/definitions/94.html) - Location: examples/pytorch_load_save.py:8 - 7 loaded_model.load_state_dict(torch.load('model_weights.pth')) - 8 another_model.load_state_dict(torch.load('model_weights.pth', - map_location='cpu')) - 9 - 10 print("Model loaded successfully!") - -.. seealso:: - - - https://cwe.mitre.org/data/definitions/94.html - - https://pytorch.org/docs/stable/generated/torch.load.html#torch.load - - https://github.com/huggingface/safetensors - -.. versionadded:: 1.7.10 - -""" -import bandit -from bandit.core import issue -from bandit.core import test_properties as test - - -@test.checks("Call") -@test.test_id("B614") -def pytorch_load_save(context): - """ - This plugin checks for the use of `torch.load` and `torch.save`. Using - `torch.load` with untrusted data can lead to arbitrary code execution, - and improper use of `torch.save` might expose sensitive data or lead - to data corruption. - """ - imported = context.is_module_imported_exact("torch") - qualname = context.call_function_name_qual - if not imported and isinstance(qualname, str): - return - - qualname_list = qualname.split(".") - func = qualname_list[-1] - if all( - [ - "torch" in qualname_list, - func in ["load", "save"], - not context.check_call_arg_value("map_location", "cpu"), - ] - ): - return bandit.Issue( - severity=bandit.MEDIUM, - confidence=bandit.HIGH, - text="Use of unsafe PyTorch load or save", - cwe=issue.Cwe.DESERIALIZATION_OF_UNTRUSTED_DATA, - lineno=context.get_lineno_for_call_arg("load"), - ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit/plugins/trojansource.py new/bandit-1.8.3/bandit/plugins/trojansource.py --- old/bandit-1.8.2/bandit/plugins/trojansource.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/bandit/plugins/trojansource.py 2025-02-17 06:24:38.000000000 +0100 @@ -38,16 +38,16 @@ BIDI_CHARACTERS = ( - "\u202A", - "\u202B", - "\u202C", - "\u202D", - "\u202E", + "\u202a", + "\u202b", + "\u202c", + "\u202d", + "\u202e", "\u2066", "\u2067", "\u2068", "\u2069", - "\u200F", + "\u200f", ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit.egg-info/PKG-INFO new/bandit-1.8.3/bandit.egg-info/PKG-INFO --- old/bandit-1.8.2/bandit.egg-info/PKG-INFO 2025-01-13 00:32:28.000000000 +0100 +++ new/bandit-1.8.3/bandit.egg-info/PKG-INFO 2025-02-17 06:24:41.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: bandit -Version: 1.8.2 +Version: 1.8.3 Summary: Security oriented static analyser for python code. Home-page: https://bandit.readthedocs.io/ Author: PyCQA diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit.egg-info/SOURCES.txt new/bandit-1.8.3/bandit.egg-info/SOURCES.txt --- old/bandit-1.8.2/bandit.egg-info/SOURCES.txt 2025-01-13 00:32:28.000000000 +0100 +++ new/bandit-1.8.3/bandit.egg-info/SOURCES.txt 2025-02-17 06:24:41.000000000 +0100 @@ -93,7 +93,8 @@ bandit/plugins/jinja2_templates.py bandit/plugins/logging_config_insecure_listen.py bandit/plugins/mako_templates.py -bandit/plugins/pytorch_load_save.py +bandit/plugins/markupsafe_markup_xss.py +bandit/plugins/pytorch_load.py bandit/plugins/request_without_timeout.py bandit/plugins/snmp_security_check.py bandit/plugins/ssh_no_host_key_verification.py @@ -161,10 +162,11 @@ doc/source/plugins/b611_django_rawsql_used.rst doc/source/plugins/b612_logging_config_insecure_listen.rst doc/source/plugins/b613_trojansource.rst -doc/source/plugins/b614_pytorch_load_save.rst +doc/source/plugins/b614_pytorch_load.rst doc/source/plugins/b701_jinja2_autoescape_false.rst doc/source/plugins/b702_use_of_mako_templates.rst doc/source/plugins/b703_django_mark_safe.rst +doc/source/plugins/b704_markupsafe_markup_xss.rst doc/source/plugins/index.rst docker/Dockerfile examples/__init__.py @@ -199,6 +201,9 @@ examples/mark_safe.py examples/mark_safe_insecure.py examples/mark_safe_secure.py +examples/markupsafe_markup_xss.py +examples/markupsafe_markup_xss_allowed_calls.py +examples/markupsafe_markup_xss_extend_markup_names.py examples/marshal_deserialize.py examples/mktemp.py examples/multiline_statement.py @@ -225,7 +230,7 @@ examples/pycrypto.py examples/pycryptodome.py examples/pyghmi.py -examples/pytorch_load_save.py +examples/pytorch_load.py examples/random_module.py examples/requests-missing-timeout.py examples/requests-ssl-verify-disabled.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit.egg-info/entry_points.txt new/bandit-1.8.3/bandit.egg-info/entry_points.txt --- old/bandit-1.8.2/bandit.egg-info/entry_points.txt 2025-01-13 00:32:28.000000000 +0100 +++ new/bandit-1.8.3/bandit.egg-info/entry_points.txt 2025-02-17 06:24:41.000000000 +0100 @@ -31,8 +31,9 @@ jinja2_autoescape_false = bandit.plugins.jinja2_templates:jinja2_autoescape_false linux_commands_wildcard_injection = bandit.plugins.injection_wildcard:linux_commands_wildcard_injection logging_config_insecure_listen = bandit.plugins.logging_config_insecure_listen:logging_config_insecure_listen +markupsafe_markup_xss = bandit.plugins.markupsafe_markup_xss:markupsafe_markup_xss paramiko_calls = bandit.plugins.injection_paramiko:paramiko_calls -pytorch_load_save = bandit.plugins.pytorch_load_save:pytorch_load_save +pytorch_load = bandit.plugins.pytorch_load:pytorch_load request_with_no_cert_validation = bandit.plugins.crypto_request_no_cert_validation:request_with_no_cert_validation request_without_timeout = bandit.plugins.request_without_timeout:request_without_timeout set_bad_file_permissions = bandit.plugins.general_bad_file_permissions:set_bad_file_permissions diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/bandit.egg-info/pbr.json new/bandit-1.8.3/bandit.egg-info/pbr.json --- old/bandit-1.8.2/bandit.egg-info/pbr.json 2025-01-13 00:32:28.000000000 +0100 +++ new/bandit-1.8.3/bandit.egg-info/pbr.json 2025-02-17 06:24:41.000000000 +0100 @@ -1 +1 @@ -{"git_version": "c2c336d", "is_release": false} \ No newline at end of file +{"git_version": "8ff25e0", "is_release": false} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/doc/source/plugins/b614_pytorch_load.rst new/bandit-1.8.3/doc/source/plugins/b614_pytorch_load.rst --- old/bandit-1.8.2/doc/source/plugins/b614_pytorch_load.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/doc/source/plugins/b614_pytorch_load.rst 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,5 @@ +------------------ +B614: pytorch_load +------------------ + +.. automodule:: bandit.plugins.pytorch_load diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/doc/source/plugins/b614_pytorch_load_save.rst new/bandit-1.8.3/doc/source/plugins/b614_pytorch_load_save.rst --- old/bandit-1.8.2/doc/source/plugins/b614_pytorch_load_save.rst 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/doc/source/plugins/b614_pytorch_load_save.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1,5 +0,0 @@ ------------------------ -B614: pytorch_load_save ------------------------ - -.. automodule:: bandit.plugins.pytorch_load_save diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/doc/source/plugins/b704_markupsafe_markup_xss.rst new/bandit-1.8.3/doc/source/plugins/b704_markupsafe_markup_xss.rst --- old/bandit-1.8.2/doc/source/plugins/b704_markupsafe_markup_xss.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/doc/source/plugins/b704_markupsafe_markup_xss.rst 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,5 @@ +--------------------------- +B704: markupsafe_markup_xss +--------------------------- + +.. automodule:: bandit.plugins.markupsafe_markup_xss diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/examples/hardcoded-passwords.py new/bandit-1.8.3/examples/hardcoded-passwords.py --- old/bandit-1.8.2/examples/hardcoded-passwords.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/examples/hardcoded-passwords.py 2025-02-17 06:24:38.000000000 +0100 @@ -51,7 +51,7 @@ # Possible hardcoded password: 'blerg' # Severity: Low Confidence: Medium -d["password"] = "blerg" +password["password"] = "blerg" # Possible hardcoded password: 'secret' # Severity: Low Confidence: Medium @@ -68,3 +68,13 @@ # Possible hardcoded password: '1234' # Severity: Low Confidence: Medium passphrase='1234' + +# Possible hardcoded password: None +# Severity: High Confidence: High +def __init__(self, auth_scheme, auth_token=None, auth_username=None, auth_password=None, auth_link=None, **kwargs): + self.auth_scheme = auth_scheme + self.auth_token = auth_token + self.auth_username = auth_username + self.auth_password = auth_password + self.auth_link = auth_link + self.kwargs = kwargs diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/examples/markupsafe_markup_xss.py new/bandit-1.8.3/examples/markupsafe_markup_xss.py --- old/bandit-1.8.2/examples/markupsafe_markup_xss.py 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/examples/markupsafe_markup_xss.py 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,13 @@ +import flask +from markupsafe import Markup, escape + +content = "<script>alert('Hello, world!')</script>" +Markup(f"unsafe {content}") # B704 +flask.Markup("unsafe {}".format(content)) # B704 +Markup("safe {}").format(content) +flask.Markup(b"safe {}", encoding='utf-8').format(content) +escape(content) +Markup(content) # B704 +flask.Markup("unsafe %s" % content) # B704 +Markup(object="safe") +Markup(object="unsafe {}".format(content)) # Not currently detected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/examples/markupsafe_markup_xss_allowed_calls.py new/bandit-1.8.3/examples/markupsafe_markup_xss_allowed_calls.py --- old/bandit-1.8.2/examples/markupsafe_markup_xss_allowed_calls.py 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/examples/markupsafe_markup_xss_allowed_calls.py 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,9 @@ +from bleach import clean +from markupsafe import Markup + +content = "<script>alert('Hello, world!')</script>" +Markup(clean(content)) + +# indirect assignments are currently not supported +cleaned = clean(content) +Markup(cleaned) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/examples/markupsafe_markup_xss_extend_markup_names.py new/bandit-1.8.3/examples/markupsafe_markup_xss_extend_markup_names.py --- old/bandit-1.8.2/examples/markupsafe_markup_xss_extend_markup_names.py 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/examples/markupsafe_markup_xss_extend_markup_names.py 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,6 @@ +from markupsafe import Markup +from webhelpers.html import literal + +content = "<script>alert('Hello, world!')</script>" +Markup(f"unsafe {content}") +literal(f"unsafe {content}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/examples/pytorch_load.py new/bandit-1.8.3/examples/pytorch_load.py --- old/bandit-1.8.2/examples/pytorch_load.py 1970-01-01 01:00:00.000000000 +0100 +++ new/bandit-1.8.3/examples/pytorch_load.py 2025-02-17 06:24:38.000000000 +0100 @@ -0,0 +1,26 @@ +import torch +import torchvision.models as models + +# Example of saving a model +model = models.resnet18(pretrained=True) +torch.save(model.state_dict(), 'model_weights.pth') + +# Example of loading the model weights in an insecure way (should trigger B614) +loaded_model = models.resnet18() +loaded_model.load_state_dict(torch.load('model_weights.pth')) + +# Example of loading with weights_only=True (should NOT trigger B614) +safe_model = models.resnet18() +safe_model.load_state_dict(torch.load('model_weights.pth', weights_only=True)) + +# Example of loading with weights_only=False (should trigger B614) +unsafe_model = models.resnet18() +unsafe_model.load_state_dict(torch.load('model_weights.pth', weights_only=False)) + +# Example of loading with map_location but no weights_only (should trigger B614) +cpu_model = models.resnet18() +cpu_model.load_state_dict(torch.load('model_weights.pth', map_location='cpu')) + +# Example of loading with both map_location and weights_only=True (should NOT trigger B614) +safe_cpu_model = models.resnet18() +safe_cpu_model.load_state_dict(torch.load('model_weights.pth', map_location='cpu', weights_only=True)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/examples/pytorch_load_save.py new/bandit-1.8.3/examples/pytorch_load_save.py --- old/bandit-1.8.2/examples/pytorch_load_save.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/examples/pytorch_load_save.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,21 +0,0 @@ -import torch -import torchvision.models as models - -# Example of saving a model -model = models.resnet18(pretrained=True) -torch.save(model.state_dict(), 'model_weights.pth') - -# Example of loading the model weights in an insecure way -loaded_model = models.resnet18() -loaded_model.load_state_dict(torch.load('model_weights.pth')) - -# Save the model -torch.save(loaded_model.state_dict(), 'model_weights.pth') - -# Another example using torch.load with more parameters -another_model = models.resnet18() -another_model.load_state_dict(torch.load('model_weights.pth', map_location='cpu')) - -# Save the model -torch.save(another_model.state_dict(), 'model_weights.pth') - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/setup.cfg new/bandit-1.8.3/setup.cfg --- old/bandit-1.8.2/setup.cfg 2025-01-13 00:32:28.272676700 +0100 +++ new/bandit-1.8.3/setup.cfg 2025-02-17 06:24:41.569784400 +0100 @@ -128,9 +128,11 @@ tarfile_unsafe_members = bandit.plugins.tarfile_unsafe_members:tarfile_unsafe_members - pytorch_load_save = bandit.plugins.pytorch_load_save:pytorch_load_save + pytorch_load = bandit.plugins.pytorch_load:pytorch_load trojansource = bandit.plugins.trojansource:trojansource + + markupsafe_markup_xss = bandit.plugins.markupsafe_markup_xss:markupsafe_markup_xss [build_sphinx] all_files = 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/tests/functional/test_functional.py new/bandit-1.8.3/tests/functional/test_functional.py --- old/bandit-1.8.2/tests/functional/test_functional.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/tests/functional/test_functional.py 2025-02-17 06:24:38.000000000 +0100 @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: Apache-2.0 import os +from contextlib import contextmanager import testtools @@ -33,6 +34,18 @@ self.b_mgr.b_conf._settings["plugins_dir"] = path self.b_mgr.b_ts = b_test_set.BanditTestSet(config=b_conf) + @contextmanager + def with_test_set(self, ts): + """A helper context manager to change the test set without + side-effects for any follow-up tests. + """ + orig_ts = self.b_mgr.b_ts + self.b_mgr.b_ts = ts + try: + yield + finally: + self.b_mgr.b_ts = orig_ts + def run_example(self, example_script, ignore_nosec=False): """A helper method to run the specified test @@ -526,10 +539,12 @@ "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 0}, "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 0}, } - self.b_mgr.b_ts = b_test_set.BanditTestSet( - config=self.b_mgr.b_conf, profile={"exclude": ["B308"]} - ) - self.check_example("mark_safe_secure.py", expect) + with self.with_test_set( + b_test_set.BanditTestSet( + config=self.b_mgr.b_conf, profile={"exclude": ["B308"]} + ) + ): + self.check_example("mark_safe_secure.py", expect) def test_django_xss_insecure(self): """Test for Django XSS via django.utils.safestring""" @@ -537,10 +552,12 @@ "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 29, "HIGH": 0}, "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 29}, } - self.b_mgr.b_ts = b_test_set.BanditTestSet( - config=self.b_mgr.b_conf, profile={"exclude": ["B308"]} - ) - self.check_example("mark_safe_insecure.py", expect) + with self.with_test_set( + b_test_set.BanditTestSet( + config=self.b_mgr.b_conf, profile={"exclude": ["B308"]} + ) + ): + self.check_example("mark_safe_insecure.py", expect) def test_xml(self): """Test xml vulnerabilities.""" @@ -855,13 +872,13 @@ } self.check_example("tarfile_extractall.py", expect) - def test_pytorch_load_save(self): - """Test insecure usage of torch.load and torch.save.""" + def test_pytorch_load(self): + """Test insecure usage of torch.load.""" expect = { - "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 4, "HIGH": 0}, - "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 4}, + "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 3, "HIGH": 0}, + "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 3}, } - self.check_example("pytorch_load_save.py", expect) + self.check_example("pytorch_load.py", expect) def test_trojansource(self): expect = { @@ -876,3 +893,36 @@ "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 0}, } self.check_example("trojansource_latin1.py", expect) + + def test_markupsafe_markup_xss(self): + expect = { + "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 4, "HIGH": 0}, + "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 4}, + } + self.check_example("markupsafe_markup_xss.py", expect) + + def test_markupsafe_markup_xss_extend_markup_names(self): + expect = { + "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 2, "HIGH": 0}, + "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 2}, + } + b_conf = b_config.BanditConfig() + b_conf.config["markupsafe_xss"] = { + "extend_markup_names": ["webhelpers.html.literal"] + } + with self.with_test_set(b_test_set.BanditTestSet(config=b_conf)): + self.check_example( + "markupsafe_markup_xss_extend_markup_names.py", expect + ) + + def test_markupsafe_markup_xss_allowed_calls(self): + expect = { + "SEVERITY": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 1, "HIGH": 0}, + "CONFIDENCE": {"UNDEFINED": 0, "LOW": 0, "MEDIUM": 0, "HIGH": 1}, + } + b_conf = b_config.BanditConfig() + b_conf.config["markupsafe_xss"] = {"allowed_calls": ["bleach.clean"]} + with self.with_test_set(b_test_set.BanditTestSet(config=b_conf)): + self.check_example( + "markupsafe_markup_xss_allowed_calls.py", expect + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bandit-1.8.2/tests/unit/cli/test_main.py new/bandit-1.8.3/tests/unit/cli/test_main.py --- old/bandit-1.8.2/tests/unit/cli/test_main.py 2025-01-13 00:32:25.000000000 +0100 +++ new/bandit-1.8.3/tests/unit/cli/test_main.py 2025-02-17 06:24:38.000000000 +0100 @@ -215,34 +215,10 @@ self.assertRaisesRegex(SystemExit, "2", bandit.main) self.assertEqual( str(err_mock.call_args[0][0]), - "Unknown test found in profile: some_test", + "No tests would be run, please check the profile.", ) @mock.patch( - "sys.argv", ["bandit", "-c", "bandit.yaml", "-t", "badID", "test"] - ) - def test_main_unknown_tests(self): - # Test that bandit exits when an invalid test ID is provided - temp_directory = self.useFixture(fixtures.TempDir()).path - os.chdir(temp_directory) - with open("bandit.yaml", "w") as fd: - fd.write(bandit_config_content) - # assert a SystemExit with code 2 - self.assertRaisesRegex(SystemExit, "2", bandit.main) - - @mock.patch( - "sys.argv", ["bandit", "-c", "bandit.yaml", "-s", "badID", "test"] - ) - def test_main_unknown_skip_tests(self): - # Test that bandit exits when an invalid test ID is provided to skip - temp_directory = self.useFixture(fixtures.TempDir()).path - os.chdir(temp_directory) - with open("bandit.yaml", "w") as fd: - fd.write(bandit_config_content) - # assert a SystemExit with code 2 - self.assertRaisesRegex(SystemExit, "2", bandit.main) - - @mock.patch( "sys.argv", ["bandit", "-c", "bandit.yaml", "-p", "bad", "test"] ) def test_main_profile_not_found(self):