Skip to content

Semgrep python rules


pyramid_jinja2_reflected_xss

Summary:

Improper neutralization of user input rendered in HTML ('XSS')

Severity: High

CWE: CWE-79

Description:

Untrusted user input is passed to Pyramid's render() function without proper sanitization, creating a reflected XSS vulnerability. Even though Jinja2 templates typically auto-escape variables, this protection can be bypassed through template features that disable auto-escaping (such as safe filters or raw blocks).

Remediation:

Consider sanitizing user input before passing it to templates using functions like escape_html() from pyramid.escape, escape() from markupsafe, html.escape(), or bleach.clean(). Recommended to pass user data through context dictionaries rather than embedding directly. Be especially careful with template features that disable auto-escaping when working with user-controlled data.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

pyramid_unsafe_user_input

Summary:

Improper neutralization of user input rendered in HTML ('XSS')

Severity: High

CWE: CWE-79

Description:

Untrusted user input from request objects (params, GET, POST, json_body, matchdict) is directly embedded in a Pyramid Response() without proper sanitization, creating a reflected XSS vulnerability. This allows attackers to inject malicious scripts that execute in users' browsers.

Remediation:

Consider sanitizing user input before including it in HTML responses using escape_html() from pyramid.escape, escape() from markupsafe, html.escape(), or bleach.clean(). Recommended to use Pyramid's template engines which automatically escape variables by default. Note that HTML escaping is not sufficient for JavaScript, CSS, or URL contexts - use context-specific sanitization for these cases.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_deserialization_rule-cpickle

Summary:

Deserialization of untrusted data

Severity: High

CWE: CWE-502

Description:

The application uses the cPickle module for deserialization, which allows arbitrary code execution when processing untrusted data. The cPickle module (Python 2's C-based implementation of pickle) can execute arbitrary Python code during the deserialization process through specially crafted payloads containing __reduce__ methods or other magic methods. When an attacker controls the serialized data being deserialized, they can inject malicious objects that execute commands, read sensitive files, or establish reverse shells during object reconstruction. Object injection attacks through cPickle can also exploit mass assignment vulnerabilities by including unexpected fields that modify application state or bypass security controls.

Remediation:

Consider migrating to safer serialization formats such as JSON with the built-in json module, which only supports basic data types and cannot execute arbitrary code. For complex object serialization, consider using MessagePack (msgpack-python) or Protocol Buffers (protobuf), both of which provide type-safe serialization without code execution risks. If pickle-based serialization must be used with untrusted data, implement HMAC signatures using hmac.new() to verify data integrity before deserialization, though this only protects against tampering and not malicious internal sources. To protect against mass assignment, deserialize into intermediary objects and use schema validation with the jsonschema library to explicitly whitelist allowed fields before copying data to production objects. Note that cPickle is Python 2 only and applications should migrate to Python 3, which uses the pickle module exclusively. For more information, see OWASP's Deserialization Cheat Sheet at https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html

OWASP:

  • A8:2017-Insecure Deserialization
  • A08:2021-Software and Data Integrity Failures

python_deserialization_rule-dill

Summary:

Deserialization of untrusted data

Severity: High

CWE: CWE-502

Description:

The application uses the dill library for deserialization, which extends pickle's capabilities but inherits all of pickle's security vulnerabilities. The dill.load(), dill.loads(), and related functions can execute arbitrary Python code when processing untrusted data through malicious payloads containing __reduce__ methods, lambda functions, or other executable constructs. Dill is particularly dangerous because it can serialize and deserialize a wider range of Python objects than standard pickle, including lambda functions, nested functions, and interpreter session state, which expands the attack surface for remote code execution. When attackers control serialized dill data, they can inject objects that execute system commands, exfiltrate data, or establish persistent backdoors during the deserialization process.

Remediation:

Consider replacing dill with safer serialization formats that do not execute code during deserialization. For basic data structures, use the json module which only handles primitive types and cannot execute arbitrary code. For more complex object graphs that require preserving type information, consider MessagePack (msgpack-python) or Protocol Buffers (protobuf), both of which provide type-safe serialization without code execution capabilities. If dill must be used for legitimate purposes like serializing function closures for distributed computing, ensure it only processes data from trusted internal sources and never deserializes user-supplied or network-received data. Implement HMAC signatures using hmac.new() with a secret key to verify data authenticity before deserialization, though this only protects against external tampering. To protect against mass assignment attacks, deserialize into intermediary objects and validate with jsonschema to whitelist allowed fields before copying to production objects. For more information, see OWASP's Deserialization Cheat Sheet at https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html

OWASP:

  • A8:2017-Insecure Deserialization
  • A08:2021-Software and Data Integrity Failures

python_deserialization_rule-marshal

Summary:

Deserialization of untrusted data

Severity: High

CWE: CWE-502

Description:

The application uses the marshal module for deserialization through functions like marshal.load() or marshal.loads(), which can lead to security vulnerabilities when processing untrusted data. The marshal module is designed for Python's internal use to serialize compiled bytecode (.pyc files) and is explicitly documented as unsafe for untrusted data. Maliciously crafted marshal data can cause crashes, memory corruption, or potentially arbitrary code execution by deserializing invalid bytecode objects or exploiting implementation bugs in the marshal format parser. While marshal does not inherently execute __reduce__ methods like pickle, its complexity and lack of validation make it unsuitable for security-sensitive applications, and Python's documentation explicitly warns against using marshal with untrusted data.

Remediation:

Consider replacing marshal with safer serialization formats designed for untrusted data. Use the json module for serializing basic data structures, which provides built-in safety by only supporting primitive types and cannot execute code or deserialize complex objects. For applications requiring binary serialization with type safety, consider MessagePack (msgpack-python) or Protocol Buffers (protobuf), both of which include proper validation and schema enforcement. The marshal module should only be used for its intended purpose of serializing Python bytecode for .pyc files, never for application data or anything that could be influenced by external input. If you must exchange complex Python objects, use the pickle module with HMAC signatures for data integrity verification, though even this approach should be restricted to trusted internal communication only. Note that marshal's format is version-specific and can change between Python releases, making it unsuitable for long-term data storage or cross-version compatibility. For more information, see Python's documentation at https://docs.python.org/3/library/marshal.html which explicitly warns about security risks.

OWASP:

  • A8:2017-Insecure Deserialization
  • A08:2021-Software and Data Integrity Failures

python_deserialization_rule-pickle

Summary:

Deserialization of untrusted data

Severity: High

CWE: CWE-502

Description:

The application uses the pickle module for deserialization through functions like pickle.load(), pickle.loads(), or pickle.Unpickler(), which allows arbitrary code execution when processing untrusted data. Python's pickle module can execute arbitrary code during deserialization through specially crafted payloads that include __reduce__, __setstate__, or other magic methods that are automatically invoked during object reconstruction. When an attacker controls the serialized pickle data, they can create malicious objects that execute system commands, read sensitive files, establish reverse shells, or manipulate application state during the unpickling process. Python's official documentation explicitly warns that pickle is unsafe for untrusted data and should never be used to deserialize data from untrusted or unauthenticated sources.

Remediation:

Consider migrating to safer serialization formats that do not execute code during deserialization. For basic data structures, use the json module which only supports primitive types (strings, numbers, lists, dictionaries) and cannot execute arbitrary code. For more complex serialization needs requiring binary formats or better performance, consider MessagePack (msgpack-python) or Protocol Buffers (protobuf), both of which provide type-safe serialization without code execution risks. If pickle must be used for legitimate internal purposes like caching or inter-process communication, ensure it only processes data from trusted sources and implement HMAC signatures using hmac.new() with a secret key to verify data integrity before unpickling. To protect against mass assignment attacks, deserialize into intermediary objects first and validate with the jsonschema library to explicitly whitelist allowed fields before copying data to production objects. Consider running deserialization operations in sandboxed environments with limited privileges following the principle of least privilege. For more information, see OWASP's Deserialization Cheat Sheet at https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html

OWASP:

  • A8:2017-Insecure Deserialization
  • A08:2021-Software and Data Integrity Failures

python_deserialization_rule-shelve

Summary:

Deserialization of untrusted data

Severity: High

CWE: CWE-502

Description:

The application uses the shelve module for persistent storage, which uses pickle internally for serialization and inherits all of pickle's security vulnerabilities. The shelve.open() function creates a persistent dictionary-like object that automatically pickles and unpickles Python objects when storing and retrieving data, making it vulnerable to arbitrary code execution if the shelf file is tampered with or replaced by an attacker. When reading from a shelf file, maliciously crafted pickled objects can execute arbitrary Python code through __reduce__ methods or other magic methods during the unpickling process. Since shelf files are typically stored on disk with predictable locations, attackers with filesystem access can replace legitimate shelf files with malicious versions containing exploit payloads that execute when the application reads data from the shelf.

Remediation:

Consider replacing shelve with database solutions that do not deserialize executable code. For simple key-value persistence, use SQLite through Python's sqlite3 module with JSON serialization for data values, which provides atomic transactions and concurrent access without deserialization risks. For applications requiring more complex data structures, consider embedded databases like TinyDB or external databases like PostgreSQL or MongoDB. If shelve must be used, store shelf files in directories with restrictive permissions (chmod 600) that only allow access by the application user, and implement file integrity monitoring to detect unauthorized modifications. Consider using HMAC signatures to verify shelf file integrity before opening, though this only protects against external tampering. For caching use cases, consider alternatives like Redis which use safe serialization formats, or python-diskcache which provides similar functionality with better security options. Always validate and sanitize data after retrieval from persistent storage before using it in security-sensitive operations. For more information, see OWASP's Deserialization Cheat Sheet at https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html

OWASP:

  • A8:2017-Insecure Deserialization
  • A08:2021-Software and Data Integrity Failures

python_deserialization_rule-yaml-load

Summary:

Deserialization of untrusted data

Severity: High

CWE: CWE-502

Description:

The application uses unsafe YAML deserialization through yaml.load(), yaml.unsafe_load(), or yaml.load() with unsafe loaders like Loader, UnsafeLoader, CLoader, or FullLoader. These functions can instantiate arbitrary Python objects during deserialization, allowing attackers to execute arbitrary code when processing malicious YAML input. The PyYAML library supports special YAML tags like !!python/object/apply that can invoke arbitrary Python functions or constructors, enabling remote code execution through carefully crafted YAML documents. Even the FullLoader, which was introduced as a safer alternative, has known vulnerabilities and should not be used with untrusted data. Attackers can exploit this by providing YAML input that constructs malicious objects, executes system commands, or manipulates application state during the loading process.

Remediation:

Replace unsafe YAML loading functions with yaml.safe_load() or explicitly specify yaml.load(data, Loader=yaml.SafeLoader), which only deserialize standard YAML tags and cannot instantiate arbitrary Python objects. The SafeLoader is designed to handle untrusted data and restricts deserialization to basic data types like strings, numbers, lists, and dictionaries. For applications using the newer ruamel.yaml library, use YAML(typ='safe') for safe deserialization. After safe deserialization, validate the loaded data structure against a schema using libraries like pydantic or jsonschema to ensure it matches expected formats and contains no unexpected fields that could exploit mass assignment vulnerabilities. If you need to load YAML with custom Python objects for internal configuration files, ensure those files are stored with restrictive permissions and cannot be modified by untrusted users. Consider switching to JSON for configuration data when possible, as it has a simpler security model and no support for executable constructs. For more information, see OWASP's Deserialization Cheat Sheet at https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html

OWASP:

  • A8:2017-Insecure Deserialization
  • A08:2021-Software and Data Integrity Failures

python_django_rule-django-extra-used

Summary:

Improper neutralization of special elements used in an SQL Command ('SQL Injection')

Severity: High

CWE: CWE-89

Description:

The QuerySet.extra() method is deprecated due to SQL Injection risks. This method allows dynamically generated SQL queries where user input may influence query logic, potentially allowing adversaries to access unauthorized data or execute arbitrary database operations. Callers must manually escape parameters from user-supplied information, which is error-prone and insecure.

Remediation:

Consider replacing QuerySet.extra() with other QuerySet methods like annotate(), filter(), or aggregate() to avoid SQL injection risks. If custom SQL is absolutely necessary, use RawSQL() as a safer alternative, ensuring all user-supplied arguments are passed only through the params=[] parameter which handles proper escaping. For more information, see:

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_django_rule_reflected_xss_csp

Summary:

Unsafe Content Security Policy (CSP) settings ('XSS')

Severity: High

CWE: CWE-79

Description:

The application is configuring an insecure Content Security Policy (CSP) in Python code, potentially for Django applications. The CSP configuration uses unsafe directives including 'unsafe-inline' which permits inline scripts and styles, 'unsafe-eval' which allows eval() and similar dynamic code execution, 'unsafe-hashes' which can weaken hash-based protections, or overly permissive source lists using '*' wildcards. These weak CSP directives significantly reduce the policy's effectiveness as an XSS mitigation, as they allow exactly the types of code execution that CSP is designed to prevent. The rule detects CSP-related configuration variables (matching CSP|Content-Security-Policy|Security|Policy patterns) with dangerous values.

Remediation:

Consider removing 'unsafe-inline', 'unsafe-eval', and 'unsafe-hashes' from your CSP directives and replacing '*' wildcards with explicit allowlists or 'self'. For Django applications using django-csp middleware, configure restrictive policies like CSP_SCRIPT_SRC = ("'self'",) and use nonce-based or hash-based CSP for inline scripts when necessary. Move inline JavaScript to external files to avoid needing 'unsafe-inline'. Replace eval(), Function(), and inline event handlers to eliminate the need for 'unsafe-eval'. For third-party scripts, explicitly allowlist their domains rather than using wildcards. Use report-uri or report-to directives to monitor CSP violations in production. Consider starting with a report-only policy (Content-Security-Policy-Report-Only) to test restrictions before enforcing them. See Mozilla's CSP documentation at https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP and django-csp documentation at https://django-csp.readthedocs.io/ for implementation guidance.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_django_rule_reflected_xss_global

Summary:

Improper neutralization of user input rendered in HTML ('XSS') in Django

Severity: High

CWE: CWE-79

Description:

The Django application has insecure global XSS protection settings in settings.py or code. This includes: (1) SECURE_BROWSER_XSS_FILTER = False which disables browser XSS filtering, (2) SECURE_CONTENT_TYPE_NOSNIFF = False which allows MIME-type sniffing attacks, (3) ALLOWED_HOSTS = ['*'] which permits host header injection, (4) template engine configuration with 'autoescape': False which globally disables Django's HTML escaping, or (5) using the @html_safe decorator on classes that may process untrusted data. The @html_safe decorator marks all string representations of a class as safe HTML, bypassing Django's automatic escaping when instances are rendered in templates. These global misconfigurations remove critical XSS defenses and affect the entire application rather than specific views or templates.

Remediation:

Consider setting SECURE_BROWSER_XSS_FILTER = True and SECURE_CONTENT_TYPE_NOSNIFF = True in Django settings to enable browser-level XSS protections. Configure ALLOWED_HOSTS with a specific list of valid hostnames instead of using ['*'] to prevent host header injection attacks. Keep template auto-escaping enabled by ensuring 'autoescape': True in template ENGINE options (this is the default). Avoid using the @html_safe decorator on classes that process user input - reserve it only for classes that generate trusted HTML. For Django 4.0+, consider using the SECURE_CROSS_ORIGIN_OPENER_POLICY setting for additional isolation. Implement Content Security Policy (CSP) headers using django-csp middleware to provide defense-in-depth protection. See Django security documentation at https://docs.djangoproject.com/en/stable/topics/security/ for comprehensive hardening guidance.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_django_rule_reflected_xss_httpresponse

Summary:

Improper neutralization of user input rendered in HTML ('XSS') in Django

Severity: High

CWE: CWE-79

Description:

The Django application is passing user-supplied data from request.GET.get() or request.POST.get() directly to HttpResponse() without HTML escaping. Django's HttpResponse() constructor bypasses the template engine's automatic HTML escaping, rendering content exactly as provided. This creates a reflected Cross-Site Scripting (XSS) vulnerability where attackers can inject malicious JavaScript through request parameters that will execute in victims' browsers. The rule detects taint flow from Django request parameter accessors to HttpResponse constructors using taint mode analysis. While Django templates automatically escape variables, using HttpResponse() directly circumvents this protection and requires manual escaping of all user input.

Remediation:

Consider using Django's render() function with templates instead of HttpResponse() for HTML responses, as templates provide automatic context-aware escaping. If you must use HttpResponse(), manually escape user input with django.utils.html.escape() or django.utils.html.format_html() before constructing the response. When using format_html(), pass user input as arguments (e.g., format_html("<b>{}</b>", user_input)) rather than embedding it in f-strings which would bypass escaping. For plain text responses, set the content type to text/plain with HttpResponse(content, content_type='text/plain') to prevent browsers from interpreting the content as HTML. For JavaScript or CSS contexts, use django.utils.html.escapejs() in addition to HTML escaping. Use whitelist-based sanitizers like bleach or nh3 for rich user-generated content that requires HTML formatting.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_django_rule_reflected_xss_render

Summary:

Improper neutralization of user input rendered in HTML ('XSS')

Severity: High

CWE: CWE-79

Description:

The Django application is marking user-supplied data from request.GET.get() or request.POST.get() as safe HTML using mark_safe() or SafeString() before passing it to the render() function or template context. These functions explicitly tell Django's template engine to skip automatic HTML escaping for the marked strings, creating a Cross-Site Scripting (XSS) vulnerability. The rule also detects cases where user input is marked safe and then passed to render_to_string() combined with HttpResponse(), or when templates are dynamically rendered with unsafe user data using template loaders. Even though Django templates have auto-escaping enabled by default, using mark_safe() or SafeString() on user input bypasses this protection entirely, allowing malicious JavaScript to execute in the rendered page.

Remediation:

Consider removing mark_safe() and SafeString() calls on user-supplied data and rely on Django's automatic template escaping instead. Never mark user input as safe - reserve these functions only for HTML generated by your application code. If you need to escape user input manually before rendering, use django.utils.html.escape() or django.utils.html.format_html() with proper argument passing like format_html("<b>{}</b>", user_input) rather than f-strings. For rich user-generated content that requires HTML formatting, use a whitelist-based sanitizer like bleach or nh3 to clean the HTML before passing it to templates. For JavaScript or CSS contexts within templates, use django.utils.html.escapejs() in addition to Django's auto-escaping. Consider using Django's Sanitizer class for more complex HTML sanitization scenarios. Implement Content Security Policy (CSP) headers as defense-in-depth protection.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_eval_rule-eval

Summary:

Improper neutralization of directives in dynamically evaluated code ('Eval Injection')

Severity: High

CWE: CWE-95

Description:

The application calls eval() with non-literal data, which allows arbitrary Python code execution. If the input contains any user-controlled data (directly or indirectly), an attacker can execute malicious code to compromise the entire system, access sensitive data, or perform unauthorized operations. The eval() function is inherently unsafe with untrusted input.

Remediation:

Remove all calls to eval() and use safer alternatives. If converting strings to data structures, use json.loads() for JSON data. Avoid ast.literal_eval() as it can still cause denial-of-service issues. Consider redesigning the logic to avoid dynamic code execution entirely. There is no safe way to call eval() with any user-influenced input, even with sanitization attempts. Refactor to use explicit conditionals, lookup tables, or predefined function mappings instead.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-exec-used

Summary:

Improper neutralization of special elements used in an OS command ('OS Command Injection')

Severity: High

CWE: CWE-78

Description:

The application uses Python's exec() function with a non-literal variable, which allows execution of arbitrary Python code at runtime. If the variable passed to exec() contains any user-supplied input, an adversary could achieve complete system compromise by executing malicious Python code with the application's privileges. This vulnerability is particularly dangerous because exec() has access to the full Python runtime environment and can modify program state, access files, make network connections, or execute system commands.

Remediation:

Remove all calls to exec() and redesign the application logic to avoid dynamic code execution. Consider using json.loads() if the goal is to convert strings into Python data structures, as this safely parses JSON without executing code. If evaluating literal expressions is required, ast.literal_eval() can safely parse Python literals like strings, numbers, lists, and dictionaries, though it should be used cautiously as it can still cause denial-of-service through resource exhaustion. For configuration or plugin systems, consider using declarative formats like YAML or TOML with schema validation, or implement a restricted domain-specific language. There is no safe method of calling exec() with any form of user-influenced input.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-linux-command-wildcard-injection

Summary:

Improper neutralization of wildcards or matching symbols

Severity: High

CWE: CWE-155

Description:

The application uses wildcard characters (* or ?) in calls to os.system(), os.popen(), or subprocess.Popen() with shell=True, which allows shell expansion of the wildcards. This creates a command injection vulnerability because adversaries can create files with names that begin with dashes (like -e sh malicious.sh) which will be expanded by the shell and interpreted as command-line flags rather than filenames. This technique, known as wildcard injection or argument injection, can lead to arbitrary command execution when the expanded filenames are processed by the target command.

Remediation:

Use the glob module to expand wildcards programmatically before passing the results to subprocess functions, and always use list-style arguments without shell=True. For example, replace subprocess.Popen("rm *.txt", shell=True) with subprocess.run(["rm"] + glob.glob("*.txt")). This ensures that expanded filenames are treated as data rather than being subject to shell interpretation. If the set of files is predictable, consider hardcoding the file list or using more specific path matching. When working with user-specified patterns, validate them strictly and never allow patterns to be directly interpolated into shell commands.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-os-path

Summary:

Improper neutralization of special elements used in an OS Command ('OS Command Injection')

Severity: High

CWE: CWE-78

Description:

The application uses deprecated Python functions like os.system(), os.popen(), os.popen2(), os.popen3(), os.popen4(), commands.getoutput(), or commands.getstatusoutput() with string literals. While the current implementation appears to use static strings, these functions are inherently dangerous because they invoke shell interpreters, making the code fragile and susceptible to command injection if the code is modified later to include variables or user input.

Remediation:

Migrate to subprocess.run() or subprocess.Popen() with list-style arguments and shell=False (the default). For example, replace os.system("ls -la") with subprocess.run(["ls", "-la"], capture_output=True). This approach avoids shell invocation entirely, eliminating shell injection risks even if the code is later modified to include variables. The subprocess module provides better control over process execution, including proper handling of arguments, environment variables, and output capture. Note that the commands module was removed in Python 3, and the os.popen family of functions is deprecated.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-os-popen2

Summary:

Improper neutralization of special elements used in an OS Command ('OS Command Injection')

Severity: High

CWE: CWE-78

Description:

The application uses deprecated Python process execution functions including os.system(), os.popen(), os.popen2(), os.popen3(), os.popen4(), popen2.popen2(), popen2.popen3(), popen2.popen4(), popen2.Popen3(), popen2.Popen4(), commands.getoutput(), or commands.getstatusoutput(). These functions spawn processes through a shell interpreter, which introduces command injection vulnerabilities if the code is ever modified to accept dynamic input. Even with static arguments, these APIs are deprecated and should be replaced with modern alternatives.

Remediation:

Replace all usage with subprocess.run() or subprocess.Popen() using list-style arguments without shell=True. For example, convert os.popen("grep pattern file.txt") to subprocess.run(["grep", "pattern", "file.txt"], capture_output=True, text=True). The subprocess module provides better security, error handling, and control over process execution. The popen2 module was removed in Python 3.0, and the commands module was also removed in Python 3. Using modern subprocess APIs prevents shell injection vulnerabilities and makes the code more maintainable and portable across platforms.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-start-process-with-no-shell

Summary:

Improper neutralization of special elements used in an OS Command ('OS Command Injection')

Severity: High

CWE: CWE-78

Description:

The application uses Python's os.exec*() family of functions (including os.execl(), os.execle(), os.execlp(), os.execlpe(), os.execv(), os.execve(), os.execvp(), os.execvpe()) or os.spawn*() family (including os.spawnl(), os.spawnle(), os.spawnlp(), os.spawnlpe(), os.spawnv(), os.spawnve(), os.spawnvp(), os.spawnvpe()) or os.startfile() with dynamic arguments that are not string literals. While these functions don't invoke a shell by default, they can still enable command injection if external data influences the command path or arguments, as attackers can execute arbitrary programs or manipulate command behavior.

Remediation:

Ensure that the command path and all arguments are either hardcoded string literals or strictly validated against an allowlist of safe values. If user input must influence which command runs, use a mapping structure to translate user choices into safe, predefined commands rather than allowing direct path specification. For the os.spawn*() family, consider using subprocess.run() or subprocess.Popen() instead, as they provide better control and are the recommended modern approach. Never allow user input to control the executable path, and validate all arguments to ensure they cannot break out of intended usage patterns (e.g., by containing path traversal sequences or unexpected command-line flags).

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-subprocess-call

Summary:

Improper neutralization of special elements used in an OS Command ('OS Command Injection')

Severity: High

CWE: CWE-78

Description:

The application uses subprocess module functions (like subprocess.run(), subprocess.Popen(), subprocess.call(), or subprocess.check_output()) without shell=True, which is the secure default behavior. While this approach avoids shell injection vulnerabilities, the application still needs to validate that user-supplied data does not influence the command path or arguments in dangerous ways. For example, passing user input as the executable path could allow execution of arbitrary programs, and user-controlled arguments could enable flag injection attacks if the target command has dangerous options.

Remediation:

Ensure the executable path is always a hardcoded literal or selected from a strict allowlist of permitted commands. Validate all arguments that come from user input, especially ensuring they do not begin with dashes (which could be interpreted as command-line flags). Consider using libraries that provide higher-level abstractions for common tasks rather than spawning subprocesses directly. For example, use the shutil module for file operations instead of calling cp or mv commands. When user input must be passed as arguments, implement strict input validation, consider sandboxing, and use the -- separator if the command supports it to mark the end of options and prevent flag injection.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-subprocess-popen-shell-true

Summary:

Improper neutralization of special elements used in an OS Command ('OS Command Injection')

Severity: High

CWE: CWE-78

Description:

The application uses subprocess module functions like subprocess.run(), subprocess.Popen(), subprocess.call(), or subprocess.check_output() with shell=True, which spawns commands through a shell interpreter (like /bin/sh or cmd.exe). This is extremely dangerous because it enables shell injection attacks if any part of the command string contains user-supplied data. Shell interpreters treat special characters (like ;, |, &, $, backticks, etc.) as control operators, allowing attackers to chain commands, redirect output, or execute arbitrary code. Additionally, shell=True inherits the current environment and shell configuration, which can introduce unexpected behavior and security vulnerabilities.

Remediation:

Replace shell=True with shell=False (the default) and pass the command as a list of arguments instead of a string. For example, replace subprocess.run("grep pattern file.txt", shell=True) with subprocess.run(["grep", "pattern", "file.txt"]). This ensures that each argument is passed directly to the program without shell interpretation, completely eliminating shell injection vulnerabilities. If you need shell features like pipes or redirection, implement them using subprocess features: use stdout=subprocess.PIPE and connect multiple processes, or use Python's built-in file handling. Never concatenate or interpolate user input into command strings, even when they appear in argument lists.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_exec_rule-subprocess-shell-TRUE

Summary:

Improper neutralization of special elements used in an OS Command ('OS Command Injection')

Severity: High

CWE: CWE-78

Description:

The application uses process spawning functions with shell=True in a context that appears to be a subprocess-like call but may not be from the standard subprocess module. This pattern detects potential command injection vulnerabilities in custom subprocess wrappers or third-party libraries that accept shell=True parameters. Using shell=True enables shell interpretation of the command string, which allows attackers to inject shell metacharacters (like ;, |, &, $(), etc.) if any user input influences the command, leading to arbitrary command execution.

Remediation:

Review the identified function to understand whether it spawns processes and accepts shell commands. If it's a custom wrapper around subprocess functionality, modify it to remove shell=True and accept command arguments as lists instead of strings. If it's a third-party library, consult the documentation for secure alternatives that don't require shell invocation. When refactoring, ensure that commands are passed as lists (e.g., ["command", "arg1", "arg2"]) rather than strings, and never concatenate or interpolate user input into command strings. Consider creating higher-level abstractions that eliminate the need for direct process spawning.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_flask_rule_reflected_xss_make_response

Summary:

Improper neutralization of user input rendered in HTML (XSS)

Severity: High

CWE: CWE-79

Description:

Untrusted user input from request objects is directly inserted into an HTML response created with make_response() without proper sanitization, creating a reflected XSS vulnerability. Always sanitize user input before including it in HTML responses using Flask's escape function, MarkupSafe's escape, html.escape(), or bleach.clean(). Use Flask's render_template() with Jinja2 templates instead of manually constructing HTML with make_response(), as templates automatically escape variables. Remember that HTML escaping is not sufficient for JavaScript contexts, CSS contexts, or URL attributes - use context-specific sanitization for these cases.

Remediation:

Consider using Flask's render_template() function with Jinja2 templates instead of make_response() with manual HTML construction, as templates provide automatic HTML escaping by default. If you must use make_response(), escape user input with markupsafe.escape(), flask.escape(), html.escape(), or bleach.clean() before constructing the response. For plain text responses, set the content type explicitly with response.mimetype = 'text/plain' to prevent browsers from interpreting the content as HTML. For JSON responses, use Flask's jsonify() function which handles escaping automatically. Implement Content Security Policy (CSP) headers using Flask-CSP or Flask-Talisman extensions to provide defense-in-depth protection. For JavaScript or CSS contexts, use context-specific escaping beyond HTML escaping.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_flask_rule_reflected_xss_render

Summary:

Improper neutralization of user input rendered in HTML (XSS)

Severity: High

CWE: CWE-79

Description:

Untrusted user input is directly inserted into an HTML template string passed to render_template_string(), creating a reflected XSS vulnerability. While Jinja2 templates automatically escape variables, this protection is bypassed when user input is embedded in the template string itself or when the |safe filter is used. Never construct template strings dynamically with user input - always pass user data as context variables to the template instead. If you must include user data in dynamic templates, sanitize it first with Flask's escape function, MarkupSafe's escape, or html.escape(). Never use the |safe filter with untrusted data, and consider using render_template() with static template files instead of render_template_string().

Remediation:

Consider using render_template() with static template files instead of render_template_string() to avoid template injection vulnerabilities. Never embed user input directly in template strings - always pass user data as template context variables which Jinja2 will automatically escape. If you must use dynamic templates, escape user input with markupsafe.escape() or flask.escape() before embedding it in the template string. Never use the | safe filter on untrusted data in templates. For cases where you need to construct dynamic content, consider using template inheritance or includes with static base templates. Implement Content Security Policy (CSP) headers using Flask-Talisman to provide defense-in-depth protection. Use bleach.clean() for rich user-generated content that requires HTML formatting.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_flask_rule_reflected_xss_user_input

Summary:

Improper neutralization of user input rendered in HTML (XSS)

Severity: High

CWE: CWE-79

Description:

User input from request objects (args, form, values, json) is directly used in HTML output without proper sanitization, creating a reflected XSS vulnerability. Always sanitize user input before including it in HTML responses using Flask's escape function, MarkupSafe's escape, html.escape(), or bleach.clean(). Use Flask templates (Jinja2) which automatically escape variables by default instead of manually constructing HTML. For JavaScript contexts or URL attributes, use additional context-specific sanitization as HTML escaping alone is insufficient.

Remediation:

Consider using Flask's render_template() function with Jinja2 templates instead of returning manually constructed HTML strings, as templates provide automatic HTML escaping by default. If you must return HTML strings directly, escape user input with markupsafe.escape(), flask.escape(), html.escape(), or bleach.clean() before including it in the response. For plain text responses, use Response(content, mimetype='text/plain') to prevent browsers from interpreting the content as HTML. For JSON responses, use Flask's jsonify() function which handles escaping automatically. Implement Content Security Policy (CSP) headers using Flask-Talisman or Flask-CSP extensions to provide defense-in-depth protection against XSS attacks. For JavaScript or CSS contexts, use context-specific escaping beyond standard HTML escaping.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_log_rule-logging-config-insecure-listen

Summary:

Improper control of generation of code ('Code Injection')

Severity: High

CWE: CWE-94

Description:

The application calls logging.config.listen(), which creates a socket server to receive logging configuration from external sources. This function internally calls eval() on received configuration data, enabling arbitrary code execution by local users or remote attackers exploiting SSRF vulnerabilities to send malicious logging configurations.

Remediation:

Consider removing the call to logging.config.listen() entirely and use static configuration files loaded at startup instead. Recommended to use logging.config.fileConfig() or logging.config.dictConfig() with configuration files that are read-only and owned by trusted users. If dynamic logging configuration is required, implement a custom configuration loader with strict input validation that does not use eval() or other code execution mechanisms.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_rule_sql_injection

Summary:

Unsafe SQL query with non parameterized parameters

Severity: High

CWE: CWE-89

Description:

SQL injection vulnerability detected: user-controlled input is embedded in a SQL query using Python string formatting (% operator), concatenation (+), f-strings, or .format(). This allows attackers to manipulate the query logic and potentially access, modify, or delete database data.

Remediation:

Consider using parameterized queries with placeholders instead of string concatenation. Use parameter binding like cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,)) or named parameters like session.exec("SELECT :col", {"col": value}). Avoid quoted placeholders like '%s'. Recommended to use ORM query builders (Django ORM, SQLAlchemy, SQLModel, Peewee) which handle parameterization automatically and provide additional SQL injection protection.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_rule_sql_injection_queries

Summary:

Unsafe SQL query with non parameterized parameters

Severity: High

CWE: CWE-89

Description:

SQL injection vulnerability detected: SQL query uses unsafe dynamic parameter insertion through quoted placeholders ('%s'), .format(), string concatenation, f-strings, or += operators. This allows attackers to escape the query context and execute arbitrary SQL commands.

Remediation:

Consider using properly parameterized queries with separate parameter lists or tuples. Use patterns like cursor.execute("SELECT %s FROM table", (input,)) or execute("SELECT :name", {"name": value}) instead of string formatting or concatenation. Never quote placeholders like '%s'. Recommended to use ORM frameworks (Django ORM, SQLAlchemy, SQLModel) when possible, as they provide built-in SQL injection protection. Only construct raw SQL when ORMs cannot fulfill the requirement.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_rule_ssrf

Summary:

Request to a user controllable URL leading to SSRF

Severity: High

CWE: CWE-918

Description:

This rule detected user-controlled input being used to construct URLs for Python HTTP client libraries including requests.get(), requests.post(), urllib.request.urlopen(), http.client.HTTPConnection(), socket.connect(), tornado.httpclient.fetch(), aiohttp.ClientSession.get(), pyramid.request.Request.blank(), xmlrpc.client.ServerProxy(), zeep.Client(), suds.client.Client(), pycurl.Curl.setopt(), and subprocess calls to curl or wget. The taint analysis tracks user input from sources like Flask request parameters, command-line arguments, standard input, and WebSocket messages to these network request sinks. When user input controls URLs without validation, Server-Side Request Forgery (SSRF) vulnerabilities arise that allow attackers to force the server to access internal services (localhost:8080/admin), cloud metadata endpoints (169.254.169.254), or arbitrary external systems, potentially exposing sensitive data or enabling network reconnaissance that bypasses firewall protections.

Remediation:

Consider implementing a strict URL allowlist that validates user input against approved domains using Python's urllib.parse.urlparse() to extract and validate the scheme, hostname, and port components before making requests. Restrict allowed protocols to http:// and https:// only, explicitly rejecting file://, gopher://, ftp://, and other dangerous schemes. Implement DNS rebinding protection by resolving hostnames using socket.gethostbyname() and blocking connections to private IP ranges (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and cloud metadata addresses (169.254.169.254) using libraries like ipaddress.ip_address() and is_private. For applications using the requests library, configure custom transport adapters with requests.adapters.HTTPAdapter to enforce connection restrictions. Disable HTTP redirects or implement strict redirect validation to prevent redirect-based SSRF bypasses. Consider routing all outbound requests through a monitored egress proxy with request filtering, or use network-level controls like iptables rules to restrict the application's network access. Use a server-side mapping approach where user input provides keys that map to pre-configured safe URLs rather than accepting arbitrary URLs.

OWASP:

  • A10:2021-Server-Side Request Forgery (SSRF)

python_tornado_rule_reflected_xss

Summary:

Improper neutralization of user input rendered in Tornado ('XSS')

Severity: High

CWE: CWE-79

Description:

User controlled input given to Tornado self.write() or self.redirect() methods can lead to XSS attacks as they do not escape the variable. Prefer using tornado.web.RequestHandler render() methods which auto escapes variables rendered in the Template. If you need to use self.write() or self.redirect(), make sure to sanitize them using tornado.escape.xhtml_escape(...) or tornado.escape.url_escape(...) if it is a URL.

Remediation:

Consider using Tornado's self.render() method instead of self.write() for HTML responses, as self.render() uses templates with automatic HTML escaping enabled by default. If you must use self.write(), manually escape user input with tornado.escape.xhtml_escape() before writing it to the response. For URL redirects with user input, use tornado.escape.url_escape() to properly encode the data. For JSON responses, use tornado.escape.json_encode() which handles escaping automatically. Avoid constructing HTML strings manually with user input - prefer template rendering which provides context-aware escaping. For file uploads accessed through self.request.files, ensure filenames and content are validated and escaped before display. Implement Content Security Policy (CSP) headers using self.set_header() to provide defense-in-depth protection against XSS attacks.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_tornado_rule_reflected_xss_csp

Summary:

Improper neutralization of user input rendered in HTML ('XSS')

Severity: High

CWE: CWE-79

Description:

The application configures an insecure Content Security Policy (CSP) in Tornado using self.set_header(). The policy contains dangerous directives such as unsafe-inline, unsafe-eval, unsafe-hashes, or wildcard (*) sources, or explicitly disables XSS protection with X-XSS-Protection: 0. These configurations bypass browser XSS protections and allow execution of inline scripts, enabling attackers to inject and execute malicious JavaScript.

Remediation:

Remove unsafe-inline, unsafe-eval, and unsafe-hashes from your CSP directives. Consider implementing nonce-based or hash-based CSP for inline scripts using nonce- or sha256- directives. Replace wildcard (*) sources with specific domain allowlists or use 'self' to restrict resources to same-origin only. Ensure X-XSS-Protection is set to 1 or omitted entirely (modern browsers use CSP instead). For Tornado applications, set secure headers in a base handler's set_default_headers() method.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_tornado_rule_reflected_xss_global

Summary:

Improper neutralization of user input rendered in HTML ('XSS')

Severity: High

CWE: CWE-79

Description:

The Tornado application is globally disabling HTML auto-escaping by setting autoescape=None in the tornado.web.Application() constructor, Application subclass initialization, or tornado.template.Loader() configuration. This removes Tornado's default XSS protection for all templates in the application, creating widespread Cross-Site Scripting vulnerabilities wherever user-supplied data is rendered. Unlike template-level escaping controls, this global configuration affects every template rendered by the application, including third-party templates and includes. Setting autoescape=None means that all template variables {{ variable }} will be rendered without HTML encoding, allowing malicious JavaScript in user input to execute in victims' browsers.

Remediation:

Consider keeping Tornado's default auto-escaping enabled by removing autoescape=None from Application and Loader configurations or using autoescape="xhtml_escape" explicitly. Tornado's default behavior automatically escapes HTML in template variables, protecting against XSS attacks. If you need to render trusted HTML in specific templates, use the {% raw %} directive or {{! }} syntax selectively rather than disabling escaping globally. For user-generated content that requires HTML formatting, use a whitelist-based sanitizer like bleach or nh3 in Python before passing data to templates. Use Tornado's escaping functions when constructing responses manually: tornado.escape.xhtml_escape() for HTML, tornado.escape.url_escape() for URLs, and tornado.escape.json_encode() for JSON. Implement Content Security Policy (CSP) headers with self.set_header() to provide defense-in-depth protection.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_crypto_rule-cipher-modes

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses cryptography.hazmat.primitives.ciphers.modes.ECB() to instantiate ECB (Electronic Codebook) cipher mode, which is cryptographically dangerous because it lacks message integrity verification. Without message integrity, an adversary can tamper with the ciphertext in ways that may compromise the encryption key or alter the decrypted plaintext in predictable ways. ECB mode also reveals patterns in the plaintext since identical plaintext blocks produce identical ciphertext blocks, making it particularly vulnerable to analysis attacks. Modern cryptographic best practices require authenticated encryption that combines confidentiality and integrity protection.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides built-in authenticated encryption and is faster and easier to use correctly than manually configured cipher modes. For applications requiring AES compatibility, AES-256-GCM can be used, but be aware that nonce reuse with GCM leads to catastrophic security failures - nonces must be generated using os.urandom(12) and never reused with the same key. ChaCha20Poly1305 is generally recommended for new Python applications as it avoids the cipher mode configuration complexity and nonce-misuse catastrophes associated with AES-GCM. Both algorithms are available in the cryptography package at https://cryptography.io/en/latest/hazmat/primitives/aead/. Example implementations: ChaCha20Poly1305.generate_key() creates a secure key, and encrypt(nonce, plaintext, aad) provides authenticated encryption in a single operation.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-cipher-blowfish

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Cipher.Blowfish.new() or Cryptodome.Cipher.Blowfish.new() to instantiate Blowfish ciphers. The Blowfish cipher has a 64-bit block size which makes it vulnerable to birthday attacks after processing approximately 4GB of data with the same key. This practical limitation means Blowfish should not be used for bulk encryption in modern applications, particularly for high-throughput scenarios like file encryption or network protocols. Although Blowfish was designed in 1993 as a DES replacement and no major cryptanalytic breaks are known, its small block size represents a fundamental weakness that cannot be mitigated through configuration changes.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides authenticated encryption with a modern stream cipher design that avoids block size limitations entirely. For applications requiring AES compatibility, AES-256-GCM can be used instead, though be aware it requires careful nonce management to avoid catastrophic failures from nonce reuse. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - the cryptography package at https://cryptography.io/ provides better security defaults and is more actively maintained. When migrating from Blowfish, ensure that authenticated encryption modes like ChaCha20Poly1305 or AES-GCM are used rather than switching to another unauthenticated cipher mode, as authenticated encryption provides both confidentiality and integrity protection.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-cipher-des

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Cipher.DES.new() or Cryptodome.Cipher.DES.new() to instantiate DES ciphers. DES (Data Encryption Standard) is a broken cryptographic algorithm that uses an insufficient 56-bit key size, making it vulnerable to brute-force attacks with modern computing power. DES was officially deprecated by NIST in 2005 and should never be used for encrypting sensitive data. The use of DES in the Crypto or Cryptodome packages indicates reliance on outdated cryptographic libraries that lack modern security features like authenticated encryption and proper key derivation.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides authenticated encryption that is both faster and more secure than DES. ChaCha20Poly1305 is recommended over AES-256-GCM for most Python applications because it's easier to use correctly and doesn't have the catastrophic nonce-reuse vulnerabilities that plague GCM modes. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ which provides better security defaults, active maintenance, and modern authenticated encryption. When replacing DES, ensure you use authenticated encryption modes (ChaCha20Poly1305 or AES-GCM) rather than unauthenticated block ciphers, as modern security standards require both confidentiality and integrity protection. Note that any data encrypted with DES should be re-encrypted with a modern algorithm as soon as possible.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-cipher-rc2

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Cipher.ARC2.new() or Cryptodome.Cipher.ARC2.new() to instantiate RC2 ciphers. RC2 (Rivest Cipher 2) is a broken cryptographic algorithm with known weaknesses including vulnerability to related-key attacks and insufficient key scheduling. RC2 uses variable key sizes but even with maximum key length remains cryptographically weak by modern standards. Designed in 1987 and later reverse-engineered, RC2 lacks the cryptanalytic scrutiny and security properties required for modern encryption, particularly the absence of authenticated encryption that allows tampering with ciphertext.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides authenticated encryption that is both faster and more secure than RC2. ChaCha20Poly1305 is recommended over AES-256-GCM for most Python applications because it's easier to use correctly and avoids the catastrophic nonce-reuse vulnerabilities present in GCM modes. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ which provides modern authenticated encryption primitives and active security maintenance. When replacing RC2, ensure authenticated encryption modes (ChaCha20Poly1305 or AES-GCM) are used rather than switching to another unauthenticated cipher, as modern security standards require both confidentiality and integrity protection.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-cipher-rc4

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Cipher.ARC4.new() or Cryptodome.Cipher.ARC4.new() to instantiate RC4 ciphers. RC4 (Rivest Cipher 4 or ARC4) is a comprehensively broken stream cipher with multiple practical attacks including biases in the keystream, related-key attacks, and plaintext recovery attacks. RC4 was officially prohibited for use in TLS by RFC 7465 in 2015 and should never be used in any security-sensitive context. The cipher's weaknesses allow attackers to recover plaintext from ciphertext in realistic scenarios, particularly in protocols like WEP and early TLS versions where RC4 was historically deployed.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides authenticated encryption using a modern, secure stream cipher design. ChaCha20Poly1305 is recommended over AES-256-GCM for most Python applications as it's faster in software implementations and easier to use correctly without the catastrophic nonce-reuse vulnerabilities that plague GCM modes. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ which provides modern authenticated encryption primitives with better security defaults. When replacing RC4, ensure authenticated encryption modes (ChaCha20Poly1305 or AES-GCM) are used, as modern security standards require both confidentiality and integrity protection. Any data encrypted with RC4 should be considered potentially compromised and should be re-encrypted with a secure algorithm immediately.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-cipher-xor

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Cipher.XOR.new() or Cryptodome.Cipher.XOR.new() to instantiate XOR ciphers. XOR cipher is not a secure encryption algorithm and provides only trivial obfuscation that can be easily broken. XOR encryption with a repeating key is vulnerable to frequency analysis, known-plaintext attacks, and can often be broken with automated tools in seconds. Using XOR as an encryption primitive in the Crypto or Cryptodome packages represents a fundamental misunderstanding of cryptographic security, as XOR alone lacks key derivation, authentication, and the cryptographic properties necessary for confidentiality.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides real authenticated encryption instead of simple obfuscation. ChaCha20Poly1305 is recommended over AES-256-GCM for most Python applications as it's easier to use correctly and provides both confidentiality and integrity protection in a single operation. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ which provides modern authenticated encryption primitives with proper security guarantees. When replacing XOR encryption, ensure that authenticated encryption modes (ChaCha20Poly1305 or AES-GCM) are used, as modern security standards require cryptographically secure algorithms with key derivation, proper mode of operation, and message authentication. Note that any data "encrypted" with XOR should be considered exposed and must be re-encrypted with a proper cryptographic algorithm immediately.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-encrypt-dsa-rsa

Summary:

Inadequate encryption strength

Severity: Medium

CWE: CWE-326

Description:

The application uses Crypto.PublicKey.RSA.generate(), Cryptodome.PublicKey.RSA.generate(), Crypto.PublicKey.DSA.generate(), Cryptodome.PublicKey.DSA.generate(), or cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key() / cryptography.hazmat.primitives.asymmetric.dsa.generate_private_key() with a key size of less than 2048 bits, which provides inadequate security against modern factorization attacks. NIST deprecated 1024-bit RSA keys in December 2010, and while they haven't been publicly factored yet, advances in computing power and algorithmic improvements make factorization increasingly feasible. RSA and DSA keys below 2048 bits are considered cryptographically weak and unsuitable for protecting sensitive data, particularly for long-term security requirements like certificate signing or key agreement protocols.

Remediation:

Consider using the modern X25519 or Ed25519 elliptic curve algorithms from the cryptography package, which provide stronger security with smaller key sizes and better performance than RSA or DSA. For key exchange, X25519PrivateKey.generate() handles key generation with secure defaults, while Ed25519PrivateKey.generate() provides secure digital signatures. If RSA or DSA must be used for compatibility reasons, use a minimum key size of 2048 bits, though 3072 or 4096 bits are recommended for long-term security. When generating RSA keys with cryptography.hazmat.primitives.asymmetric.rsa.generate_private_key(), always use public_exponent=65537 and key_size=4096 for new applications. Note that the Crypto and Cryptodome packages detected in this finding are no longer recommended - migrate to the cryptography package at https://cryptography.io/en/latest/ for better security defaults and active maintenance.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-encrypt-ec

Summary:

Inadequate encryption strength

Severity: Medium

CWE: CWE-326

Description:

The application uses cryptography.hazmat.primitives.asymmetric.ec.generate_private_key() with weak elliptic curve parameters - specifically ec.SECP192R1() (192-bit), ec.SECT163K1() (163-bit), or ec.SECT163R2() (163-bit) curves. These curves provide inadequate security margins against modern cryptanalytic attacks and do not meet NIST's minimum recommendation of 224-bit security strength. Using weak elliptic curves in the cryptography package can lead to compromised key exchanges or digital signatures, particularly as computational power increases and cryptanalytic techniques improve.

Remediation:

Consider upgrading to SECP384R1 or SECP256R1 curves when using NIST P-curves, which provide 384-bit and 256-bit security levels respectively. For new applications, the modern Ed25519 or X25519 curves are recommended over NIST P-curves as they provide better security properties, are easier to implement correctly, and offer better performance. Use Ed25519PrivateKey.generate() for digital signatures or X25519PrivateKey.generate() for key exchange from cryptography.hazmat.primitives.asymmetric.ed25519 and x25519 modules. If NIST P-curves are required for compatibility, use ec.SECP384R1() or ec.SECP256R1() with ec.generate_private_key() - avoid curves below 224-bit security strength. More information on elliptic curve cryptography is available at https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ec/.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-hash-md5

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Hash.MD5.new() or Cryptodome.Hash.MD5.new() to instantiate MD5 hash objects. MD5 is a cryptographically broken hash algorithm vulnerable to collision attacks, where attackers can generate different inputs that produce the same hash output. Collision attacks against MD5 are practical and have been demonstrated since 2004, making MD5 unsuitable for any security-critical applications including digital signatures, certificate validation, or integrity verification. The use of MD5 in the Crypto or Cryptodome packages indicates reliance on outdated cryptographic libraries for an already-broken hash function.

Remediation:

Consider migrating to SHA-256 or SHA-384 from the cryptography package for general-purpose hashing and integrity verification. If this MD5 usage is for password hashing, migrate to a dedicated password hashing algorithm like Argon2id, bcrypt, or PBKDF2 instead of any general-purpose hash function. Use hashes.Hash(hashes.SHA256()) from cryptography.hazmat.primitives for creating secure message digests. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ for better security defaults. Note that MD5 should never be used for security purposes even in legacy protocol implementations, though it may be acceptable for non-security use cases like checksums for detecting accidental data corruption. For password storage guidance, see the OWASP Password Storage Cheat Sheet at https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-hash-sha1

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Hash.SHA.new() or Cryptodome.Hash.SHA.new() to instantiate SHA-1 hash objects. SHA-1 is a cryptographically broken hash algorithm vulnerable to collision attacks, where attackers can generate different inputs that produce the same hash output. Practical collision attacks against SHA-1 were demonstrated in 2017 with the SHAttered attack, and SHA-1 has been deprecated for most security uses by major standards bodies and browser vendors. Using SHA-1 in the Crypto or Cryptodome packages indicates reliance on outdated cryptographic libraries for an already-broken hash function that should not be used for digital signatures, certificate validation, or integrity verification.

Remediation:

Consider migrating to SHA-256 or SHA-384 from the cryptography package for general-purpose hashing and integrity verification. If this SHA-1 usage is for password hashing, migrate to a dedicated password hashing algorithm like Argon2id, bcrypt, or PBKDF2 instead of any general-purpose hash function. Use hashes.Hash(hashes.SHA256()) or hashes.Hash(hashes.SHA384()) from cryptography.hazmat.primitives for creating secure message digests. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ for better security defaults. Note that SHA-1 may still be required for compatibility with legacy systems like Git or older protocols, but should never be used in new security-critical contexts or where collision resistance is required. For password storage guidance, see the OWASP Password Storage Cheat Sheet at https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-hazmat-cipher-arc4

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses cryptography.hazmat.primitives.ciphers.algorithms.ARC4() to instantiate RC4 ciphers. RC4 (also known as ARC4 or Rivest Cipher 4) is a comprehensively broken stream cipher with multiple practical attacks including biases in the keystream, related-key attacks, and plaintext recovery attacks. RC4 was officially prohibited for use in TLS by RFC 7465 in 2015 and should never be used in any security-sensitive context. The cipher's weaknesses allow attackers to recover plaintext from ciphertext in realistic scenarios, particularly in protocols like WEP and early TLS versions where RC4 was historically deployed.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides authenticated encryption using a modern, secure stream cipher design. ChaCha20Poly1305 is recommended over AES-256-GCM for most applications as it's faster in software implementations and easier to use correctly without the catastrophic nonce-reuse vulnerabilities that plague GCM modes. Example implementation: use ChaCha20Poly1305.generate_key() to create a secure key, then encrypt with chacha.encrypt(nonce, plaintext, aad) where nonce must be generated using os.urandom(12) and never reused. For applications requiring AES compatibility, AES-256-GCM can be used with AESGCM.generate_key(bit_length=256), but requires careful nonce management to avoid catastrophic failures. Full examples available at https://cryptography.io/en/latest/hazmat/primitives/aead/.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-hazmat-cipher-blowfish

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses cryptography.hazmat.primitives.ciphers.algorithms.Blowfish() to instantiate Blowfish ciphers. The Blowfish cipher has a 64-bit block size which makes it vulnerable to birthday attacks after processing approximately 4GB of data with the same key. This practical limitation means Blowfish should not be used for bulk encryption in modern applications, particularly for high-throughput scenarios like file encryption or network protocols. Although Blowfish was designed in 1993 as a DES replacement and no major cryptanalytic breaks are known, its small block size represents a fundamental weakness that cannot be mitigated through configuration changes.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides authenticated encryption with a modern stream cipher design that avoids block size limitations entirely. ChaCha20Poly1305 is generally recommended for new applications as it's faster than AES-GCM and easier to use correctly. Example: use ChaCha20Poly1305.generate_key() to create a key, then chacha.encrypt(nonce, plaintext, aad) where nonce = os.urandom(12). For applications requiring AES compatibility, AES-256-GCM can be used with AESGCM.generate_key(bit_length=256), but be aware it requires careful nonce management to avoid catastrophic failures from nonce reuse. When migrating from Blowfish, ensure authenticated encryption modes are used rather than switching to another unauthenticated cipher, as modern standards require both confidentiality and integrity protection. Full code examples at https://cryptography.io/en/latest/hazmat/primitives/aead/.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto-hazmat-cipher-idea

Summary:

Use of a Broken or Risky Cryptographic Algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses cryptography.hazmat.primitives.ciphers.algorithms.IDEA() to instantiate IDEA ciphers. The IDEA (International Data Encryption Algorithm) cipher was designed in 1991 as a DES replacement but has since been found to have multiple cryptographic weaknesses. Vulnerabilities including weak-key classes and related-key attacks have been identified, making IDEA unsuitable for modern cryptographic applications. While IDEA uses a 128-bit key size, its design flaws and lack of authenticated encryption mean it cannot provide the security guarantees required by contemporary standards.

Remediation:

Consider migrating to ChaCha20Poly1305 from the cryptography package, which provides authenticated encryption that combines confidentiality and integrity protection in a single operation. ChaCha20Poly1305 is recommended for most applications as it's faster and easier to use correctly than AES-GCM. Example: use ChaCha20Poly1305.generate_key() to create a key, then chacha.encrypt(nonce, plaintext, aad) where nonce = os.urandom(12) and must never be reused. For applications requiring AES compatibility, AES-256-GCM can be used with AESGCM.generate_key(bit_length=256), but requires careful nonce management to avoid catastrophic security failures. Code examples and full documentation available at https://cryptography.io/en/latest/hazmat/primitives/aead/.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto.hazmat-hash-md5

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses cryptography.hazmat.primitives.hashes.MD5() to instantiate MD5 hash objects. MD5 is a cryptographically broken hash algorithm vulnerable to collision attacks, where attackers can generate different inputs that produce the same hash output. Collision attacks against MD5 are practical and have been demonstrated since 2004, making MD5 unsuitable for any security-critical applications including digital signatures, certificate validation, or integrity verification. The use of MD5 via the cryptography.hazmat API indicates direct use of a broken hash function that should be replaced with secure alternatives.

Remediation:

Consider migrating to SHA-256, SHA-384, or SHA-512 from the cryptography package for general-purpose hashing and integrity verification. Use hashes.Hash(hashes.SHA256()) for creating secure message digests. For password hashing, migrate to dedicated password hashing algorithms like Argon2id (via the argon2-cffi package) or PBKDF2, which include proper salting and key stretching mechanisms. Example with SHA-256: digest = hashes.Hash(hashes.SHA256()); digest.update(b"data"); result = digest.finalize(). Note that MD5 should never be used for security purposes even in legacy protocol implementations, though it may be acceptable for non-security use cases like checksums for detecting accidental data corruption. For password storage guidance, see https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-crypto.hazmat-hash-sha1

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses cryptography.hazmat.primitives.hashes.SHA1() to instantiate SHA-1 hash objects. SHA-1 is a cryptographically broken hash algorithm vulnerable to collision attacks, where attackers can generate different inputs that produce the same hash output. Practical collision attacks against SHA-1 were demonstrated in 2017 with the SHAttered attack, and SHA-1 has been deprecated for most security uses by major standards bodies and browser vendors. Using SHA-1 via the cryptography.hazmat API indicates direct use of a broken hash function that should not be used for digital signatures, certificate validation, or integrity verification in security-sensitive contexts.

Remediation:

Consider migrating to SHA-256, SHA-384, or SHA-512 from the cryptography package for general-purpose hashing and integrity verification. Use hashes.Hash(hashes.SHA256()) or hashes.Hash(hashes.SHA384()) for creating secure message digests. For password hashing, migrate to dedicated password hashing algorithms like Argon2id (via the argon2-cffi package) or PBKDF2, which include proper salting and key stretching mechanisms. Example with SHA-256: digest = hashes.Hash(hashes.SHA256()); digest.update(b"data"); result = digest.finalize(). Note that SHA-1 may still be required for compatibility with legacy systems like Git or older protocols, but should never be used in new security-critical contexts or where collision resistance is required. For password storage guidance, see https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-hash-md2

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Hash.MD2.new() or Cryptodome.Hash.MD2.new() to instantiate MD2 hash objects. MD2 is a severely broken cryptographic hash algorithm with fundamental design flaws that make it completely unsuitable for any cryptographic purpose. MD2 is vulnerable to collision attacks and has been deprecated since the early 2000s due to multiple practical attacks against its security. The use of MD2 in the Crypto or Cryptodome packages indicates reliance on outdated cryptographic libraries for an algorithm that should never be used in any security context.

Remediation:

Consider migrating to SHA-256, SHA-384, or SHA-512 from the cryptography package for general-purpose hashing and integrity verification. Use hashes.Hash(hashes.SHA256()) from cryptography.hazmat.primitives for creating secure message digests. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ for better security defaults. For password hashing, migrate to dedicated password hashing algorithms like Argon2id (via the argon2-cffi package) or PBKDF2, which include proper salting and key stretching mechanisms. Example with SHA-384: digest = hashes.Hash(hashes.SHA384()); digest.update(b"data"); result = digest.finalize(). For password storage guidance, see https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-hash-md4

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses Crypto.Hash.MD4.new() or Cryptodome.Hash.MD4.new() to instantiate MD4 hash objects. MD4 is a critically broken cryptographic hash algorithm with severe vulnerabilities that make it completely unsuitable for any security purpose. MD4 is vulnerable to collision attacks that can be executed in seconds on modern hardware, and it has been deprecated for decades due to fundamental cryptographic weaknesses. The use of MD4 in the Crypto or Cryptodome packages indicates reliance on outdated cryptographic libraries for an algorithm with no legitimate modern security use cases.

Remediation:

Consider migrating to SHA-256, SHA-384, or SHA-512 from the cryptography package for general-purpose hashing and integrity verification. Use hashes.Hash(hashes.SHA256()) from cryptography.hazmat.primitives for creating secure message digests. The Crypto and Cryptodome packages detected in this finding are no longer recommended for new Python applications - migrate to the cryptography package at https://cryptography.io/ for better security defaults. For password hashing, migrate to dedicated password hashing algorithms like Argon2id (via the argon2-cffi package) or PBKDF2, which include proper salting and key stretching mechanisms. Example with SHA-384: digest = hashes.Hash(hashes.SHA384()); digest.update(b"data"); result = digest.finalize(). For password storage guidance, see https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-hash-md5

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses hashlib.md5() to instantiate MD5 hash objects. MD5 is a cryptographically broken hash algorithm vulnerable to collision attacks, where attackers can generate different inputs that produce the same hash output. Collision attacks against MD5 are practical and have been demonstrated since 2004, making MD5 unsuitable for any security-critical applications including digital signatures, certificate validation, or integrity verification. The use of hashlib.md5() indicates direct use of a broken hash function that should be replaced with secure alternatives.

Remediation:

Consider replacing hashlib.md5() with hashlib.sha256(), hashlib.sha384(), or hashlib.sha512() for data integrity verification and general-purpose hashing. Example with SHA-256: digest = hashlib.sha256(); digest.update(b"data"); result = digest.digest(). For password hashing, migrate to dedicated password hashing algorithms like Argon2id (via the argon2-cffi package) or PBKDF2 from the cryptography package, which include proper salting and key stretching mechanisms. Note that MD5 should never be used for security purposes even in legacy protocol implementations, though it may be acceptable for non-security use cases like checksums for detecting accidental data corruption. For password storage guidance, see https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-hash-sha1

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses hashlib.sha1() to instantiate SHA-1 hash objects. SHA-1 is a cryptographically broken hash algorithm vulnerable to collision attacks, where attackers can generate different inputs that produce the same hash output. Practical collision attacks against SHA-1 were demonstrated in 2017 with the SHAttered attack, and SHA-1 has been deprecated for most security uses by major standards bodies and browser vendors. The use of hashlib.sha1() indicates direct use of a broken hash function that should not be used for digital signatures, certificate validation, or integrity verification in security-sensitive contexts.

Remediation:

Consider replacing hashlib.sha1() with hashlib.sha256(), hashlib.sha384(), or hashlib.sha512() for data integrity verification and general-purpose hashing. Example with SHA-256: digest = hashlib.sha256(); digest.update(b"data"); result = digest.digest(). For password hashing, migrate to dedicated password hashing algorithms like Argon2id (via the argon2-cffi package) or PBKDF2 from the cryptography package, which include proper salting and key stretching mechanisms. Note that SHA-1 may still be required for compatibility with legacy systems like Git or older protocols, but should never be used in new security-critical contexts or where collision resistance is required. For password storage guidance, see https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-hashlib-new-insecure-functions

Summary:

Use of a broken or risky cryptographic algorithm

Severity: Medium

CWE: CWE-327

Description:

The application uses hashlib.new() with an insecure hash algorithm name parameter (MD2, MD4, MD5, SHA, or SHA-1) that is vulnerable to collision attacks. These hash algorithms have been found to be cryptographically broken, where attackers can generate different inputs that produce the same hash output. Using insecure hash algorithms through hashlib.new() makes the code less obvious and harder to audit, while still providing no security benefits due to the fundamental weaknesses of these algorithms.

Remediation:

Consider replacing hashlib.new() calls with direct function calls using secure algorithms: hashlib.sha256(), hashlib.sha384(), or hashlib.sha512() for data integrity verification and general-purpose hashing. Direct function calls like hashlib.sha256() are preferred over hashlib.new('sha256') for improved code clarity and easier security auditing. Example with SHA-384: digest = hashlib.sha384(); digest.update(b"data"); result = digest.digest(). For password hashing, migrate to dedicated password hashing algorithms like Argon2id (via the argon2-cffi package) or PBKDF2 from the cryptography package, which include proper salting and key stretching mechanisms to resist brute-force attacks. Avoid implementing custom hash algorithms as this is prone to errors and security vulnerabilities.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_crypto_rule-import-pycrypto

Summary:

Use of unmaintained third party components

Severity: Medium

CWE: CWE-1104

Description:

The application imports from the pycrypto package using import Crypto.Cipher, import Crypto.Hash, or other Crypto.* module imports. The pycrypto package has been abandoned since 2013 and contains known security vulnerabilities that will never be patched. Using an unmaintained cryptographic library poses serious security risks, as newly discovered vulnerabilities will remain unpatched and exploitable. The pycrypto package lacks modern cryptographic primitives and security features that are standard in contemporary libraries.

Remediation:

Consider migrating to the actively maintained cryptography package at https://cryptography.io/, which provides modern, secure implementations of cryptographic primitives with regular security updates. The cryptography package offers comprehensive support for authenticated encryption (ChaCha20Poly1305, AES-GCM), secure hashing (SHA-256, SHA-384, SHA-512), and password hashing (PBKDF2), along with strong community support and active maintenance. For authenticated encryption, use ChaCha20Poly1305.generate_key() and chacha.encrypt(nonce, plaintext, aad). For hashing, use hashes.Hash(hashes.SHA256()) from cryptography.hazmat.primitives. The migration typically involves replacing Crypto.Cipher imports with cryptography.hazmat.primitives.ciphers.aead for modern authenticated encryption modes.

OWASP:

  • A9:2017-Using Components with Known Vulnerabilities
  • A02:2021-Cryptographic Failures

python_escaping_rule-jinja2-autoescape-false

Summary:

Improper encoding or escaping of output

Severity: Medium

CWE: CWE-116

Description:

The application uses jinja2.Environment() without enabling autoescaping. When rendering HTML templates with user-supplied input, this allows malicious content to be rendered as executable JavaScript or HTML, leading to Cross-Site Scripting (XSS) attacks that can compromise user sessions and data.

Remediation:

Consider enabling autoescaping by passing autoescape=True or autoescape=select_autoescape() when creating the Jinja2 Environment. Note that Jinja2 autoescaping only provides HTML context escaping and is insufficient for other contexts (JavaScript, CSS, URLs, etc.). For complex applications, implement custom filters using @pass_eval_context decorators to handle context-specific escaping. Recommended to never output user input directly in JavaScript blocks, and validate/sanitize all user input before rendering.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_escaping_rule-use-of-mako-templates

Summary:

Improper neutralization of input during web page generation ('Cross-site Scripting')

Severity: Medium

CWE: CWE-79

Description:

The application uses mako.template.Template() or mako.lookup.TemplateLookup() without specifying default_filters. When rendering HTML templates with user-supplied input, this allows malicious content to be rendered as executable JavaScript or HTML, leading to Cross-Site Scripting (XSS) attacks that can compromise user sessions and data.

Remediation:

Consider adding default_filters=['h'] to Template or TemplateLookup constructors to enable HTML escaping by default. The 'h' filter HTML-escapes variables in templates automatically. Note that this only protects HTML contexts and is insufficient for JavaScript, CSS, or URL contexts. For complex applications, implement custom filters for context-specific escaping and import them via the imports parameter. Recommended to never output user input directly in JavaScript blocks, and validate/sanitize all user input before rendering.

OWASP:

  • A7:2017-Cross-Site Scripting (XSS)
  • A03:2021-Injection

python_file-permissions_rule-general-bad-permission

Summary:

Incorrect permission assignment for critical resource

Severity: Medium

CWE: CWE-732

Description:

The application uses os.chmod() to set overly permissive file permissions, allowing world-writable or world-executable access. This creates a security risk where unauthorized users or processes could modify or execute sensitive files, potentially leading to privilege escalation, data tampering, or arbitrary code execution.

Remediation:

Consider restricting file permissions to the minimum necessary for the application. Recommended to use octal values like 0o600 (read/write for owner only) or 0o400 (read-only for owner) when the application user is the only process that needs access. Avoid permissions that grant write (0o2) or execute (0o1) access to group or others. For example, use os.chmod('file.txt', 0o600) instead of world-writable modes.

OWASP:

  • A5:2017-Broken Access Control
  • A01:2021-Broken Access Control

python_files_rule-tarfile-unsafe-members

Summary:

Improper limitation of a pathname to a restricted directory ('Path Traversal')

Severity: Medium

CWE: CWE-22

Description:

The application uses tarfile.extractall() without proper path validation, making it vulnerable to path traversal attacks (Zip Slip). Malicious archive files can contain entries with path traversal sequences like ../../etc/passwd that escape the intended extraction directory, allowing attackers to overwrite critical system files or plant malicious code in arbitrary locations.

Remediation:

Consider validating each archive member before extraction using tar.getmembers() and checking that paths don't escape the target directory. Recommended to verify member.isfile() to skip symlinks and directories, sanitize filenames using os.path.basename(), and validate the resolved path starts with your intended directory. For Python 3.12+, use the filter='data' parameter in extractall() for automatic protection against path traversal and other archive-based attacks.

OWASP:

  • A5:2017-Broken Access Control
  • A01:2021-Broken Access Control

python_flask_rule-app-debug

Summary:

Active debug code

Severity: Medium

CWE: CWE-489

Description:

The Flask application uses app.run(debug=True) which enables the interactive debugger in production. This exposes sensitive information including source code, environment variables, and stack traces through HTTP responses when exceptions occur. The debugger also provides an interactive console accessible via web browser, allowing attackers to execute arbitrary Python code on the server.

Remediation:

Consider disabling debug mode in production by setting debug=False or omitting the parameter entirely. Recommended to use environment variables like app.config.from_envvar() to control debug settings based on deployment environment. For production deployments, use a production-grade WSGI server such as Gunicorn or Waitress instead of Flask's built-in development server (app.run()).

OWASP:

  • A6:2017-Security Misconfiguration
  • A05:2021-Security Misconfiguration

python_ftp_rule-ftplib

Summary:

Cleartext transmission of sensitive information

Severity: Medium

CWE: CWE-319

Description:

The application uses the ftplib module for file transfer protocol operations. FTP transmits all data, including credentials and file contents, in cleartext without encryption, allowing attackers to intercept sensitive information through network sniffing or man-in-the-middle attacks.

Remediation:

Consider migrating to secure file transfer protocols that provide encryption. Recommended to use SFTP via the paramiko library with scp module (e.g., paramiko.SSHClient() with scp.SCPClient()) for SSH-based secure file transfers. For compatibility with FTP servers that support encryption, use ftplib.FTP_TLS() instead, though SFTP is preferred. Ensure proper host key verification when using SSH-based approaches to prevent MITM attacks.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_requests_rule-request-without-timeout

Summary:

Allocation of resources without limits or throttling

Severity: Medium

CWE: CWE-770

Description:

The application calls requests module methods (get(), post(), put(), etc.) without specifying a timeout parameter. This allows network connections to hang indefinitely, leading to uncontrolled resource consumption and socket exhaustion, effectively causing a Denial of Service (DoS) condition.

Remediation:

Consider adding a timeout parameter to all requests method calls to prevent indefinite blocking. The timeout value should be set based on expected network conditions and application requirements, typically between 5-30 seconds. For example, use requests.get('https://example.com', timeout=10) to set a 10-second timeout. Recommended to apply timeouts consistently across all HTTP operations including get(), post(), put(), delete(), patch(), head(), and options(). Avoid setting timeout=None or timeout=0 as these disable the timeout protection.

OWASP:

  • A6:2017-Security Misconfiguration
  • A05:2021-Security Misconfiguration

python_snmp_rule-insecure-snmp-version

Summary:

Cleartext transmission of sensitive information

Severity: Medium

CWE: CWE-319

Description:

The CommunityData() API with mpModel=0 (SNMPv1) or mpModel=1 (SNMPv2c) transmits credentials and data in cleartext without encryption or strong authentication. This exposes sensitive device information and community strings to network eavesdropping and man-in-the-middle attacks.

Remediation:

Consider migrating to SNMPv3 with UsmUserData() instead of CommunityData(). Recommended to use SHA-based authentication (authProtocol=usmHMACSHAAuthProtocol) with a strong authKey, and AES encryption (privProtocol=usmAesCfb128Protocol) with a strong privKey. For example: UsmUserData('username', 'authKey', 'privKey', authProtocol=usmHMACSHAAuthProtocol, privProtocol=usmAesCfb128Protocol).

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_snmp_rule-snmp-weak-cryptography

Summary:

Cleartext transmission of sensitive information

Severity: Medium

CWE: CWE-319

Description:

The UsmUserData() API is configured without authentication or encryption. Using usmNoAuthProtocol, usmNoPrivProtocol, missing/null authKey, or missing/null privKey exposes SNMP communications to eavesdropping and tampering. Without authentication, attackers can impersonate devices; without encryption, sensitive device data and credentials are transmitted in cleartext.

Remediation:

Consider enabling both authentication and privacy in UsmUserData(). Recommended to set authProtocol=usmHMACSHAAuthProtocol with a strong authKey for message authentication, and privProtocol=usmAesCfb128Protocol with a strong privKey for encryption. Avoid usmNoAuthProtocol and usmNoPrivProtocol. Always provide non-null values for both authKey and privKey to ensure secure SNMPv3 communications.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_ssh_rule-ssh-nohost-key-verification

Summary:

Key exchange without entity authentication

Severity: Medium

CWE: CWE-322

Description:

The application uses SSHClient.set_missing_host_key_policy() with AutoAddPolicy or WarningPolicy, which disables host key verification. This allows connections to untrusted hosts and enables man-in-the-middle attacks, as the client cannot validate the server's identity through host key authentication.

Remediation:

Consider removing the set_missing_host_key_policy() call entirely to use paramiko's default RejectPolicy, which rejects connections to unknown hosts. Recommended to load known host keys using ssh.load_system_host_keys() or ssh.load_host_keys('/path/to/known_hosts') before connecting. For production environments, maintain a known_hosts file with verified server fingerprints. If you must connect to new hosts, manually verify the host key fingerprint out-of-band before adding it to your known_hosts file. Avoid using AutoAddPolicy or WarningPolicy as they accept any host key without verification.

OWASP:

  • A5:2017-Broken Access Control
  • A07:2021-Identification and Authentication Failures

python_ssl_rule-req-no-certvalid

Summary:

Improper certificate validation

Severity: Medium

CWE: CWE-295

Description:

The application uses requests.get(), requests.post(), or other requests module functions with the verify=False argument, which disables SSL/TLS certificate validation. This prevents the requests library from verifying the server's identity, making the connection vulnerable to man-in-the-middle attacks. An adversary positioned between the application and the target server could intercept sensitive data, inject malicious responses, or impersonate legitimate servers without detection.

Remediation:

Consider removing the verify=False argument entirely from all requests function calls, as certificate verification is enabled by default in the requests library. If explicit verification is required, set verify=True or provide a path to a custom CA bundle file using verify='/path/to/ca-bundle.crt'. For development environments with self-signed certificates, recommended to add the certificate to the system trust store rather than disabling verification globally. When working with corporate proxies or internal services, consider using the REQUESTS_CA_BUNDLE environment variable to specify certificate paths system-wide. Always combine certificate verification with appropriate timeout values (e.g., timeout=10) to prevent hanging connections. For more information, see https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification

OWASP:

  • A2:2017-Broken Authentication
  • A07:2021-Identification and Authentication Failures

python_ssl_rule-ssl-no-version

Summary:

Inadequate encryption strength

Severity: Medium

CWE: CWE-326

Description:

The application calls ssl.wrap_socket() without specifying a TLS protocol version, which can result in negotiating weak or outdated protocol versions. Additionally, ssl.wrap_socket() has been deprecated since Python 3.7 and lacks the security features and proper defaults provided by the modern SSLContext API. Using this deprecated function without explicit protocol configuration leaves the application vulnerable to protocol downgrade attacks and may inadvertently allow insecure SSL/TLS versions.

Remediation:

Consider migrating from ssl.wrap_socket() to the SSLContext API by creating a context with ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) for client connections or ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_SERVER) for server connections. The PROTOCOL_TLS_CLIENT and PROTOCOL_TLS_SERVER constants automatically select the highest available TLS version (1.3 on Python 3.7+, 1.2 as fallback) while preventing downgrade to vulnerable protocols. After creating the context, use context.wrap_socket(sock, server_hostname="example.org") instead of the deprecated function. For client connections, always specify the server_hostname parameter to enable Server Name Indication (SNI) and proper certificate validation. The SSLContext approach provides better control over cipher suites, certificate verification options, and protocol versions. For more information, see https://docs.python.org/3/library/ssl.html#ssl.SSLContext

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_ssl_rule-ssl-with-bad-version

Summary:

Inadequate Encryption Strength

Severity: Medium

CWE: CWE-326

Description:

The application explicitly specifies vulnerable SSL/TLS protocol versions such as ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, or their pyOpenSSL equivalents like pyOpenSSL.SSL.SSLv3_METHOD and pyOpenSSL.SSL.TLSv1_METHOD. These protocols have known cryptographic weaknesses including vulnerability to POODLE, BEAST, and other attacks that allow adversaries to decrypt traffic or downgrade connection security. SSLv2 and SSLv3 are completely broken, while TLS 1.0 and 1.1 were deprecated by major browsers and standards organizations in 2020 due to insufficient cryptographic strength against modern attack techniques.

Remediation:

Consider replacing vulnerable protocol constants with ssl.PROTOCOL_TLS_CLIENT for client applications or ssl.PROTOCOL_TLS_SERVER for server applications when creating an SSLContext. These constants automatically negotiate the highest available TLS version (1.3 on Python 3.7+, with fallback to 1.2) while explicitly preventing downgrade to vulnerable protocols. If using pyOpenSSL, recommended to migrate to the standard library ssl module or the pyca/cryptography package, as pyOpenSSL has been deprecated by the Python Cryptographic Authority. For applications requiring backward compatibility with TLS 1.2, use ssl.PROTOCOL_TLS and configure context.minimum_version = ssl.TLSVersion.TLSv1_2 to set an explicit floor. Avoid using PROTOCOL_SSLv23 despite its confusing name suggesting flexibility, as it requires additional configuration to prevent protocol downgrade. For more information, see https://docs.python.org/3/library/ssl.html#ssl-security and https://cryptography.io/en/latest/

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_ssl_rule-unverified-context

Summary:

Improper certificate validation

Severity: Medium

CWE: CWE-295

Description:

The application creates an SSL context using ssl._create_unverified_context(), which completely disables server certificate validation. This private API function bypasses all certificate verification checks including hostname validation, certificate authority trust chain verification, and expiration checks. Using an unverified context makes the application vulnerable to man-in-the-middle attacks where an adversary can intercept encrypted traffic, impersonate legitimate servers, and steal or manipulate sensitive data without detection.

Remediation:

Consider replacing ssl._create_unverified_context() with ssl.create_default_context(), which provides secure defaults including certificate verification, hostname checking, and modern TLS protocol selection. The default context automatically loads system CA certificates and enforces proper validation. For client connections, use ssl.create_default_context( purpose=ssl.Purpose.SERVER_AUTH) and for server connections use ssl.Purpose.CLIENT_AUTH. If working with self-signed certificates in development environments, recommended to add the certificate to the context using context.load_verify_locations('cert.pem') rather than disabling verification entirely. For corporate environments with custom CA certificates, configure the SSL_CERT_FILE or SSL_CERT_DIR environment variables to specify trusted certificate locations. Never use the underscore-prefixed _create_unverified_context() in production code as it's an internal API meant only for debugging purposes. For more information, see https://docs.python.org/3/library/ssl.html#ssl.create_default_context

OWASP:

  • A2:2017-Broken Authentication
  • A07:2021-Identification and Authentication Failures

python_telnet_rule-import-telnib

Summary:

Cleartext transmission of sensitive information

Severity: Medium

CWE: CWE-319

Description:

The application imports the telnetlib module, which transmits all data including credentials and sensitive information in cleartext over the network. This exposes communications to eavesdropping, interception, and man-in-the-middle attacks.

Remediation:

Consider replacing telnetlib with the paramiko library to use SSH for encrypted remote access. SSH provides strong encryption for both authentication and data transmission. Use paramiko.SSHClient() with load_system_host_keys() or load_host_keys() to establish verified connections. For command execution, use ssh.exec_command() instead of telnet's read_until() and write() methods. If telnet protocol is absolutely required for legacy system compatibility, consider tunneling it through an encrypted VPN or SSH port forwarding rather than transmitting cleartext over the network.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_tmpdir_rule-hardcodedtmp

Summary:

Insecure temporary file

Severity: Medium

CWE: CWE-377

Description:

The application creates files directly in shared system temporary directories (/tmp or /var/tmp) using standard file operations instead of secure Python tempfile module functions. This allows attackers to exploit time-of-check to time-of-use (TOCTOU) race conditions by creating symlinks to sensitive files, potentially leading to unauthorized file creation, overwriting, or information disclosure.

Remediation:

Consider using Python's tempfile module for secure temporary file operations. Recommended functions include tempfile.TemporaryFile() for automatic cleanup, tempfile.NamedTemporaryFile() when a filesystem name is needed, or tempfile.mkstemp() for low-level control with secure file descriptor creation. These functions use secure random naming and appropriate file permissions to prevent race conditions. Use context managers (with statements) to ensure automatic cleanup when possible.

OWASP:

  • A5:2017-Broken Access Control
  • A01:2021-Broken Access Control

python_tmpdir_rule-mktemp-q

Summary:

Insecure temporary file

Severity: Medium

CWE: CWE-377

Description:

The application uses tempfile.mktemp(), which is deprecated and vulnerable to race conditions. This function only generates a filename without creating the file atomically, allowing attackers to create symlinks or files at that path between name generation and file creation, potentially leading to unauthorized access, file overwriting, or information disclosure.

Remediation:

Replace tempfile.mktemp() with secure alternatives that create files atomically. Consider using tempfile.NamedTemporaryFile() for high-level operations with automatic cleanup, or tempfile.mkstemp() which returns both a file descriptor and filename created securely. If you need a temporary directory, use tempfile.TemporaryDirectory() or tempfile.mkdtemp(). Always use context managers (with statements) when possible to ensure proper cleanup and resource management.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A01:2021-Broken Access Control

python_urlopen_rule-urllib-urlopen

Summary:

Improper authorization in handler for custom URL scheme

Severity: Medium

CWE: CWE-939

Description:

The application passes a non-literal value to urllib.urlopen(), urllib.urlretrieve(), or URLopener methods. These APIs support the file:// scheme, which allows an attacker who controls the URL to read arbitrary files from the file system, leading to sensitive information disclosure.

Remediation:

Consider migrating to the requests library, which does not support the file:// scheme by default and provides better security. If urllib must be used, validate that URLs do not use the file:// scheme by checking the URL prefix before passing to urllib methods. Recommended to maintain an allowlist of permitted URL schemes (e.g., https:// only) and reject any URLs that do not match. Alternatively, hardcode all URLs to avoid user-controlled input.

OWASP:

  • A1:2017-Injection
  • A03:2021-Injection

python_xml_rule-celement

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses xml.etree.cElementTree.parse(), xml.etree.cElementTree.fromstring(), xml.etree.cElementTree.iterparse(), or xml.etree.cElementTree.XMLParser() to process XML data without proper entity restrictions. Python's built-in XML parsers are vulnerable to XML External Entity (XXE) attacks in older Python versions and entity expansion attacks in all versions. The cElementTree module is particularly concerning because it suffers from billion laughs attacks (exponential entity expansion) and quadratic blowup entity expansion, which can allow attackers to cause Denial of Service by submitting crafted XML documents that consume excessive CPU and memory during parsing. These vulnerabilities affect applications processing untrusted XML from external sources such as API requests, file uploads, or configuration files.

Remediation:

Consider migrating to the defusedxml library which provides drop-in replacements for Python's standard XML parsers with secure defaults that prevent XXE and entity expansion attacks. The defusedxml.ElementTree module can replace xml.etree.cElementTree with minimal code changes. For example, replace from xml.etree.cElementTree import parse with from defusedxml.ElementTree import parse to use the hardened parser. The defusedxml library disables external entity processing, DTD processing, and entity expansion by default, protecting against both XXE injection and DoS attacks. For applications that cannot use defusedxml, you can manually configure the XMLParser to disable dangerous features, but this approach is more error-prone and not recommended for security-critical applications. More information is available at https://docs.python.org/3/library/xml.html#xml-vulnerabilities and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_xml_rule-element

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses xml.etree.ElementTree.parse(), xml.etree.ElementTree.fromstring(), xml.etree.ElementTree.iterparse(), or xml.etree.ElementTree.XMLParser() to process XML data without proper entity restrictions. Python's built-in XML parsers are vulnerable to XML External Entity (XXE) attacks in older Python versions and entity expansion attacks in all versions. The ElementTree module suffers from billion laughs attacks (exponential entity expansion) and quadratic blowup entity expansion, which allow attackers to cause Denial of Service by submitting crafted XML documents that consume excessive CPU and memory during parsing. While Python 3.7.1+ disabled external entities by default in ElementTree, entity expansion attacks remain exploitable. These vulnerabilities affect applications processing untrusted XML from external sources such as API requests, file uploads, or configuration files.

Remediation:

Consider migrating to the defusedxml library which provides drop-in replacements for Python's standard XML parsers with secure defaults that prevent XXE and entity expansion attacks. The defusedxml.ElementTree module can replace xml.etree.ElementTree with minimal code changes. For example, replace from xml.etree.ElementTree import parse with from defusedxml.ElementTree import parse to use the hardened parser. The defusedxml library disables external entity processing, DTD processing, and entity expansion by default, protecting against both XXE injection and DoS attacks. For applications that cannot use defusedxml, you can manually configure the XMLParser to disable dangerous features, but this approach is more error-prone and not recommended for security-critical applications. More information is available at https://docs.python.org/3/library/xml.html#xml-vulnerabilities and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_xml_rule-etree

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses lxml.etree.parse(), lxml.etree.fromstring(), lxml.etree.RestrictedElement(), lxml.etree.GlobalParserTLS(), lxml.etree.getDefaultParser(), or lxml.etree.check_docinfo() to process XML data potentially without proper entity restrictions. The lxml library is more powerful than Python's standard library XML parsers but requires explicit configuration to disable dangerous features. By default, lxml parsers may allow external entity resolution, DTD processing, and entity expansion which can lead to XML External Entity (XXE) attacks, Server-Side Request Forgery (SSRF), arbitrary file disclosure, and Denial of Service through billion laughs or quadratic blowup attacks. When using lxml's default parsers with untrusted XML input from sources like API requests, file uploads, or external feeds, applications become vulnerable to these attack vectors unless parsers are explicitly configured with secure settings.

Remediation:

Consider using the defusedxml library which provides secure wrappers for lxml parsers, or manually configure lxml parsers with secure settings. If using lxml directly, create a parser with lxml.etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False, load_dtd=False) and pass it to parsing functions. The resolve_entities=False parameter is critical as it prevents external entity expansion attacks, while no_network=True prevents SSRF attacks. For applications that can switch libraries, defusedxml provides drop-in replacements that apply these secure defaults automatically. Be aware that lxml's security configuration must be applied to every parser instance, as default parsers are not secure. Additionally, avoid using lxml.etree.RestrictedElement as it does not provide adequate security boundaries for untrusted XML. More information is available at https://lxml.de/FAQ.html#how-do-i-use-lxml-safely-as-a-web-service-endpoint and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_xml_rule-expatbuilder

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses xml.dom.expatbuilder.parse() or xml.dom.expatbuilder.parseString() to process XML data, which internally uses the xml.dom.minidom package without proper entity restrictions. Python's built-in DOM XML parsers are vulnerable to XML External Entity (XXE) attacks in older Python versions and entity expansion attacks in all versions. The expatbuilder module, which builds DOM trees using the Expat parser, suffers from billion laughs attacks (exponential entity expansion) and quadratic blowup entity expansion vulnerabilities. These attacks allow adversaries to cause severe Denial of Service conditions by submitting crafted XML documents with deeply nested or extensively repeated entity definitions that consume excessive CPU and memory during parsing. Applications using expatbuilder to process untrusted XML from sources like API requests, file uploads, or configuration files are particularly at risk.

Remediation:

Consider migrating to the defusedxml library which provides secure alternatives to Python's DOM parsing functionality with protection against XXE and entity expansion attacks. While defusedxml does not provide a direct expatbuilder replacement, you can use defusedxml.minidom.parseString() as a drop-in secure alternative for most DOM parsing use cases. The defusedxml library disables external entity processing, DTD processing, and entity expansion by default, protecting against both XXE injection and DoS attacks. If you require the specific functionality of expatbuilder and cannot use defusedxml, be aware that manually hardening expatbuilder is complex and error-prone. For most applications, switching to defusedxml or reconsidering whether DOM parsing is necessary (ElementTree is often more efficient) is recommended. More information is available at https://docs.python.org/3/library/xml.html#xml-vulnerabilities and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_xml_rule-expatreader

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses xml.dom.expatreader.parse(), xml.dom.expatreader.parseString(), or xml.dom.expatreader.create_parser() to process XML data, which uses the SAX-based Expat parser without proper entity restrictions. Python's built-in SAX XML parsers are vulnerable to XML External Entity (XXE) attacks in older Python versions and entity expansion attacks in all versions. The expatreader module, which provides a SAX interface to the Expat parser, suffers from billion laughs attacks (exponential entity expansion) and quadratic blowup entity expansion vulnerabilities. These attacks enable adversaries to cause severe Denial of Service conditions by submitting crafted XML documents with deeply nested or extensively repeated entity definitions that consume excessive CPU and memory during event-driven parsing. Applications using expatreader to process untrusted XML from sources like API requests, streaming feeds, or file uploads are particularly vulnerable.

Remediation:

Consider using the defusedxml library which provides secure SAX parsing alternatives that prevent XXE and entity expansion attacks. The defusedxml.sax module offers drop-in replacements for expatreader functions with hardened defaults. For example, use defusedxml.sax.parse() instead of xml.dom.expatreader.parse() to leverage secure parser configuration automatically. The defusedxml library disables external entity processing, DTD processing, and entity expansion by default, protecting against both XXE injection and DoS attacks while maintaining SAX's event-driven parsing model for memory-efficient processing of large XML documents. If you cannot use defusedxml, you can manually configure SAX parsers by setting features on the parser instance, but this approach is complex and error-prone compared to using defusedxml's secure defaults. More information is available at https://docs.python.org/3/library/xml.html#xml-vulnerabilities and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_xml_rule-minidom

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses xml.dom.minidom.parse() or xml.dom.minidom.parseString() to process XML data and build a Document Object Model tree without proper entity restrictions. Python's built-in minidom parser is vulnerable to XML External Entity (XXE) attacks in older Python versions and entity expansion attacks in all versions. The xml.dom.minidom module provides a lightweight DOM implementation that suffers from billion laughs attacks (exponential entity expansion) and quadratic blowup entity expansion vulnerabilities, enabling attackers to cause severe Denial of Service conditions by submitting crafted XML documents with deeply nested or extensively repeated entity definitions. Unlike streaming parsers, minidom loads the entire XML document into memory as a DOM tree, which makes it particularly susceptible to memory-exhaustion attacks. Applications using minidom to process untrusted XML from sources like API requests, file uploads, or configuration files are at significant risk.

Remediation:

Consider migrating to the defusedxml library which provides secure DOM parsing alternatives with protection against XXE and entity expansion attacks. Use defusedxml.minidom.parse() or defusedxml.minidom.parseString() as drop-in replacements for the standard minidom functions. The defusedxml library applies secure defaults that disable external entity processing, DTD processing, and entity expansion, protecting against both XXE injection and DoS attacks while maintaining the DOM interface. For applications with large XML documents, consider whether DOM parsing is necessary, as streaming parsers like SAX or iterative parsers like ElementTree's iterparse are more memory-efficient and can be secured with defusedxml as well. Be aware that minidom's in-memory DOM tree can consume significant memory even without malicious entity expansion, making it unsuitable for processing large or untrusted XML documents regardless of security hardening. More information is available at https://docs.python.org/3/library/xml.html#xml-vulnerabilities and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_xml_rule-pulldom

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses xml.dom.pulldom.parse() or xml.dom.pulldom.parseString() to process XML data using a hybrid pull/event-driven parsing model without proper entity restrictions. Python's built-in pulldom parser is vulnerable to XML External Entity (XXE) attacks in older Python versions and entity expansion attacks in all versions. The xml.dom.pulldom module provides an event-driven interface that can build DOM subtrees on demand, but it suffers from billion laughs attacks (exponential entity expansion) and quadratic blowup entity expansion vulnerabilities. These attacks enable adversaries to cause severe Denial of Service conditions by submitting crafted XML documents with deeply nested or extensively repeated entity definitions. While pulldom's incremental parsing approach can be more memory-efficient than full DOM parsing, it remains vulnerable to entity expansion attacks that can exhaust CPU and memory resources. Applications using pulldom to process untrusted XML from sources like API requests, streaming feeds, or file uploads are at risk.

Remediation:

Consider migrating to the defusedxml library which provides secure alternatives to pulldom with protection against XXE and entity expansion attacks. While defusedxml does not provide a direct pulldom replacement, you can use defusedxml.ElementTree.iterparse() for similar incremental parsing functionality with secure defaults. The iterparse approach provides event-driven parsing like pulldom while automatically disabling external entity processing, DTD processing, and entity expansion. For applications that specifically require pulldom's DOM subtree building capability, consider whether the full ElementTree API with defusedxml protection would meet your needs, as it provides similar functionality with better security. If you must use pulldom, be aware that manually hardening it is complex and error-prone. The defusedxml library's iterparse is generally a better choice for processing large or untrusted XML documents incrementally. More information is available at https://docs.python.org/3/library/xml.html#xml-vulnerabilities and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_xml_rule-sax

Summary:

Improper restriction of XML external entity reference

Severity: Medium

CWE: CWE-611

Description:

The application uses xml.sax.parse(), xml.sax.parseString(), or xml.sax.make_parser() to process XML data using SAX (Simple API for XML) event-driven parsing without proper entity restrictions. Python's built-in SAX parsers are vulnerable to XML External Entity (XXE) attacks in older Python versions and entity expansion attacks in all versions. The xml.sax module provides a streaming, event-driven interface for parsing XML that suffers from billion laughs attacks (exponential entity expansion) and quadratic blowup entity expansion vulnerabilities. These attacks enable adversaries to cause severe Denial of Service conditions by submitting crafted XML documents with deeply nested or extensively repeated entity definitions that consume excessive CPU and memory during event processing. While SAX parsing is memory-efficient for large documents, it remains vulnerable to entity-based attacks that can exhaust system resources. Applications using xml.sax to process untrusted XML from sources like API requests, streaming feeds, or file uploads are at significant risk.

Remediation:

Consider migrating to the defusedxml library which provides secure SAX parsing functions with protection against XXE and entity expansion attacks. Use defusedxml.sax.parse(), defusedxml.sax.parseString(), or defusedxml.sax.make_parser() as drop-in replacements for the standard xml.sax functions. The defusedxml library automatically configures SAX parsers with secure defaults that disable external entity processing, DTD processing, and entity expansion, protecting against both XXE injection and DoS attacks while maintaining SAX's event-driven parsing model. This allows you to continue using SAX's memory-efficient streaming approach for large XML documents without security risks. If you cannot use defusedxml, you can manually configure SAX parser features by calling parser.setFeature() to disable dangerous capabilities, but this approach is complex and error-prone compared to using defusedxml's hardened defaults. More information is available at https://docs.python.org/3/library/xml.html#xml-vulnerabilities and https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#python

OWASP:

  • A4:2017-XML External Entities (XXE)
  • A03:2021-Injection

python_bind-all-interfaces_rule-general-bindall-interfaces

Summary:

Binding to an unrestricted IP address

Severity: Low

CWE: CWE-1327

Description:

The application calls socket.bind() with "0.0.0.0", "::", or an empty string, which binds the socket to all network interfaces. This is dangerous because it exposes the service to traffic on all network interfaces, including unintended or insecure interfaces that may not be properly documented, firewalled, or intended for external access.

Remediation:

Bind to a specific network interface instead of all interfaces. Consider using "127.0.0.1" or "localhost" for local-only services, or bind to a specific internal interface address for controlled network access. Recommended to obtain the IP address from an environment variable (e.g., os.getenv("BIND_ADDRESS", "127.0.0.1")) or configuration file to allow flexible deployment while maintaining security.

OWASP:

  • A6:2017-Security Misconfiguration
  • A05:2021-Security Misconfiguration

python_prompt_injection

Summary:

Prompt injection in LLM API calls

Severity: Low

CWE: CWE-1427

Description:

User-controlled input is passed directly to LLM APIs (chat.completions.create(), generate_content()) from OpenAI, Gemini, or Azure AI without proper validation or sanitization. Prompt injection attacks can manipulate AI models to ignore their instructions, leak sensitive information, or perform unintended actions.

Remediation:

Consider validating and sanitizing all user inputs before sending to LLM APIs. Recommended to implement prompt templates that clearly separate user data from system instructions using structured formats. Use input filtering to remove or escape potentially malicious prompts. Consider using structured inputs rather than free-form text when possible, and apply the principle of least privilege to LLM API calls.


python_random_rule-random

Summary:

Use of cryptographically weak pseudo-random number generator (PRNG)

Severity: Low

CWE: CWE-338

Description:

The application uses the random module to generate random values. The random module implements a Mersenne Twister PRNG which is not cryptographically secure and produces predictable values that can be exploited when used for tokens, session identifiers, cryptographic keys, nonces, or other security-sensitive contexts.

Remediation:

Consider using the secrets module instead when generating values for security-sensitive operations. Recommended to use secrets.token_bytes() for raw bytes, secrets.token_hex() for hexadecimal strings, or secrets.token_urlsafe() for URL-safe base64-encoded strings. For choosing random elements from a sequence, use secrets.choice(). The random module is appropriate only for non-security purposes like simulations, games, or testing where predictability is acceptable.

OWASP:

  • A3:2017-Sensitive Data Exposure
  • A02:2021-Cryptographic Failures

python_assert_rule-assert-used

Summary:

Improper check for unusual or exceptional conditions

Severity: Info

CWE: CWE-754

Description:

The application uses assert in non-test code, which is dangerous because assert statements are removed when Python is compiled with optimization flags (-O or -OO). This can lead to security checks being bypassed in production, potentially causing undefined behavior or vulnerabilities when critical validation logic is silently stripped away.

Remediation:

Remove all assert statements from production code and replace them with proper error handling. Consider using if conditions that raise appropriate exceptions (e.g., ValueError, AuthError) or use try/except blocks for validation logic. For example, replace assert user.is_authenticated() with an explicit check like if not user.is_authenticated(): raise AuthError(). This ensures validation logic remains active in optimized production builds.

OWASP:

  • A6:2017-Security Misconfiguration
  • A05:2021-Security Misconfiguration