From 7e0278079361cd7da9f1a9b0ba3743aa449bf001 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 19:32:37 +0000 Subject: [PATCH 1/3] Initial plan From 0213319775b92a4403add44cacdd1d435f9d2e28 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 19:44:28 +0000 Subject: [PATCH 2/3] Add BareExcept query for Python to detect overly broad exception handling - Detects bare 'except:' clauses that catch all exceptions - Helps identify code quality issues where specific exceptions should be caught - Includes comprehensive test cases with both compliant and non-compliant examples - Query metadata: @id py/bare-except, @problem.severity warning, @precision high - All tests passing (6 bare except clauses detected in test cases) --- .../custom/src/BareExcept/BareExcept.qhelp | 47 ++++++ .../custom/src/BareExcept/BareExcept.ql | 17 ++ .../custom/src/BareExcept/BareExceptBad.py | 12 ++ .../custom/src/BareExcept/BareExceptGood.py | 21 +++ .../test/BareExcept/BareExcept.expected | 6 + .../custom/test/BareExcept/BareExcept.qlref | 1 + .../python/custom/test/BareExcept/test.py | 151 ++++++++++++++++++ 7 files changed, 255 insertions(+) create mode 100644 languages/python/custom/src/BareExcept/BareExcept.qhelp create mode 100644 languages/python/custom/src/BareExcept/BareExcept.ql create mode 100644 languages/python/custom/src/BareExcept/BareExceptBad.py create mode 100644 languages/python/custom/src/BareExcept/BareExceptGood.py create mode 100644 languages/python/custom/test/BareExcept/BareExcept.expected create mode 100644 languages/python/custom/test/BareExcept/BareExcept.qlref create mode 100644 languages/python/custom/test/BareExcept/test.py diff --git a/languages/python/custom/src/BareExcept/BareExcept.qhelp b/languages/python/custom/src/BareExcept/BareExcept.qhelp new file mode 100644 index 0000000..f2fa7e0 --- /dev/null +++ b/languages/python/custom/src/BareExcept/BareExcept.qhelp @@ -0,0 +1,47 @@ + + + + +

+Using a bare except: clause without specifying an exception type is considered bad practice +because it catches all exceptions, including system exits (SystemExit), keyboard interrupts +(KeyboardInterrupt), and other critical exceptions that should typically propagate. +

+ +

+This makes debugging difficult, can hide real bugs, and may lead to incorrect program behavior by +catching exceptions that were not intended to be handled. +

+
+ + +

+Always specify the exception types you expect to handle. If you need to catch multiple exception types, +use a tuple of exception types. If you must catch most exceptions, catch Exception explicitly, +which still allows system exits and keyboard interrupts to propagate. +

+
+ + +

+The following example shows a bare except: clause that catches all exceptions: +

+ + + +

+The following example shows the corrected code that catches only the specific exception type expected: +

+ + +
+ + +
  • Python Documentation: Handling Exceptions
  • +
  • PEP 8: Programming Recommendations
  • +
  • CWE-396: Declaration of Catch for Generic Exception
  • +
    + +
    diff --git a/languages/python/custom/src/BareExcept/BareExcept.ql b/languages/python/custom/src/BareExcept/BareExcept.ql new file mode 100644 index 0000000..a1bd06c --- /dev/null +++ b/languages/python/custom/src/BareExcept/BareExcept.ql @@ -0,0 +1,17 @@ +/** + * @name Bare except clause + * @description Using a bare 'except:' clause catches all exceptions including system exits and keyboard interrupts, making debugging difficult and potentially hiding real bugs. + * @kind problem + * @problem.severity warning + * @precision high + * @id py/bare-except + * @tags maintainability + * code-quality + * external/cwe/cwe-396 + */ + +import python + +from ExceptStmt except +where not exists(except.getType()) +select except, "Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors." diff --git a/languages/python/custom/src/BareExcept/BareExceptBad.py b/languages/python/custom/src/BareExcept/BareExceptBad.py new file mode 100644 index 0000000..129a4ad --- /dev/null +++ b/languages/python/custom/src/BareExcept/BareExceptBad.py @@ -0,0 +1,12 @@ +def parse_int(s: str) -> int: + try: + return int(s) + except: # BAD: Catches all exceptions including system exits + return 0 + +def read_config(filename): + try: + with open(filename) as f: + return f.read() + except: # BAD: Catches all exceptions, even KeyboardInterrupt + return None diff --git a/languages/python/custom/src/BareExcept/BareExceptGood.py b/languages/python/custom/src/BareExcept/BareExceptGood.py new file mode 100644 index 0000000..3f48313 --- /dev/null +++ b/languages/python/custom/src/BareExcept/BareExceptGood.py @@ -0,0 +1,21 @@ +def parse_int(s: str) -> int: + try: + return int(s) + except ValueError: # GOOD: Catches only ValueError + return 0 + +def read_config(filename): + try: + with open(filename) as f: + return f.read() + except (IOError, OSError) as e: # GOOD: Catches specific file-related exceptions + print(f"Error reading file: {e}") + return None + +# If you really need to catch most exceptions, use Exception explicitly +def process_with_logging(data): + try: + return process(data) + except Exception as e: # ACCEPTABLE: Explicitly catches Exception, not bare except + log_error(e) + return None diff --git a/languages/python/custom/test/BareExcept/BareExcept.expected b/languages/python/custom/test/BareExcept/BareExcept.expected new file mode 100644 index 0000000..e3298ec --- /dev/null +++ b/languages/python/custom/test/BareExcept/BareExcept.expected @@ -0,0 +1,6 @@ +| test.py:10:5:10:11 | ExceptStmt | Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors. | +| test.py:26:5:26:11 | ExceptStmt | Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors. | +| test.py:43:5:43:11 | ExceptStmt | Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors. | +| test.py:72:9:72:15 | ExceptStmt | Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors. | +| test.py:95:9:95:15 | ExceptStmt | Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors. | +| test.py:115:5:115:11 | ExceptStmt | Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors. | diff --git a/languages/python/custom/test/BareExcept/BareExcept.qlref b/languages/python/custom/test/BareExcept/BareExcept.qlref new file mode 100644 index 0000000..9046482 --- /dev/null +++ b/languages/python/custom/test/BareExcept/BareExcept.qlref @@ -0,0 +1 @@ +BareExcept/BareExcept.ql diff --git a/languages/python/custom/test/BareExcept/test.py b/languages/python/custom/test/BareExcept/test.py new file mode 100644 index 0000000..54f9e8d --- /dev/null +++ b/languages/python/custom/test/BareExcept/test.py @@ -0,0 +1,151 @@ +""" +Test cases for BareExcept query. +This file contains both compliant and non-compliant examples. +""" + +# NON_COMPLIANT: Bare except clause +def parse_int_bare_except(s: str) -> int: + try: + return int(s) + except: # DETECT: Bare except clause + return 0 + + +# COMPLIANT: Specific exception type +def parse_int_specific(s: str) -> int: + try: + return int(s) + except ValueError: + return 0 + + +# NON_COMPLIANT: Bare except with pass +def process_data_bare_except(): + try: + risky_operation() + except: # DETECT: Bare except clause + pass + + +# COMPLIANT: Specific exception with pass +def process_data_specific(): + try: + risky_operation() + except IOError: + pass + + +# NON_COMPLIANT: Bare except that logs +def read_file_bare_except(filename): + try: + with open(filename) as f: + return f.read() + except: # DETECT: Bare except clause + print("Error reading file") + return None + + +# COMPLIANT: Multiple specific exceptions +def read_file_specific(filename): + try: + with open(filename) as f: + return f.read() + except (IOError, OSError) as e: + print(f"Error reading file: {e}") + return None + + +# COMPLIANT: Catch Exception (not bare) +def process_with_exception_base(data): + try: + return process(data) + except Exception as e: + log_error(e) + return None + + +# NON_COMPLIANT: Nested bare except +def nested_bare_except(): + try: + try: + dangerous_operation() + except: # DETECT: Bare except clause + cleanup() + except ValueError: + pass + + +# COMPLIANT: Nested with specific exceptions +def nested_specific(): + try: + try: + dangerous_operation() + except KeyError: + cleanup() + except ValueError: + pass + + +# NON_COMPLIANT: Bare except in loop +def process_items_bare_except(items): + results = [] + for item in items: + try: + results.append(process(item)) + except: # DETECT: Bare except clause + continue + return results + + +# COMPLIANT: Specific exception in loop +def process_items_specific(items): + results = [] + for item in items: + try: + results.append(process(item)) + except (ValueError, TypeError): + continue + return results + + +# NON_COMPLIANT: Bare except with finally +def operation_with_finally_bare(): + try: + perform_operation() + except: # DETECT: Bare except clause + handle_error() + finally: + cleanup() + + +# COMPLIANT: Specific exception with finally +def operation_with_finally_specific(): + try: + perform_operation() + except RuntimeError: + handle_error() + finally: + cleanup() + + +# Helper functions (not real implementations, just for test structure) +def risky_operation(): + pass + +def process(data): + return data + +def log_error(e): + pass + +def dangerous_operation(): + pass + +def cleanup(): + pass + +def perform_operation(): + pass + +def handle_error(): + pass From fff6d4fa87a4b40cfe11349cfee36c40e20b8420 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 19:45:54 +0000 Subject: [PATCH 3/3] Format BareExcept.ql query with codeql query format --- languages/python/custom/src/BareExcept/BareExcept.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/languages/python/custom/src/BareExcept/BareExcept.ql b/languages/python/custom/src/BareExcept/BareExcept.ql index a1bd06c..4e2f176 100644 --- a/languages/python/custom/src/BareExcept/BareExcept.ql +++ b/languages/python/custom/src/BareExcept/BareExcept.ql @@ -14,4 +14,5 @@ import python from ExceptStmt except where not exists(except.getType()) -select except, "Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors." +select except, + "Avoid using bare 'except:' clauses. Specify exception types to catch only expected errors."