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