diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/README.md b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/README.md new file mode 100644 index 00000000..67ac009d --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/README.md @@ -0,0 +1,233 @@ +# CWE-532: Insertion of Sensitive Information into Log File + +Do not log any sensitive information such as passwords or credit card numbers. Encrypt or anonymize personal information such as user names, and date of birth in plain text. + +Logging is crucial for tasks like debugging, forensic analysis, and the general management of various incidents, however, it poses significant challenges when it comes to personal information and sensitive information. + +National authorities have fines for data protection violations such as: + +* California Consumer Privacy Act (CCPA) USA [CCPA DIVISION 3. OBLIGATIONS [1427 - 3273.16]](https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=CIV§ionNum=1798.150) +* General Data Protection Regulation (GDPR) [Fines / Penalties - General Data Protection Regulation (GDPR) (gdpr-info.eu)](https://gdpr-info.eu/issues/fines-penalties/) + +Cross-border data transfer regulations limit what type of data can be transferred across borders even within a single company or organization such as the [Rules on international data transfers - European Commission (europa.eu)](https://commission.europa.eu/law/law-topic/data-protection/international-dimension-data-protection/rules-international-data-transfers_en) + +Software applications often offer different levels of data protection. Certain data, such as access times, can be logged without concern. Other data can be logged but should be accessible only to specific administrators. Sensitive information, such as credit card numbers, should be logged only in encrypted form, while passwords should never be logged. [[SEI CERT 2021 FIO13-J. Do not log sensitive information outside a trust boundary]](https://wiki.sei.cmu.edu/confluence/display/java/FIO13-J.+Do+not+log+sensitive+information+outside+a+trust+boundary) + +## Noncompliant Code Example (Logging) + +In the `noncompliant01.py` code example the user is asked to input sensitive information during login, and the entered information is logged. + +In a real-world scenario, the logging data printed by the `noncompliant01.py` would have to be forwarded to a central logging system. + +Storing or displaying a password typically exposes it to a wider audience and must be avoided. + +*[noncompliant01.py](noncompliant01.py):* + +```py +""" Non-compliant Code Example """ + +import logging + + +def login_user(username, password, security_question): + """Function to login user with username password, and security question""" + logging.info( + "User %s login attempt: password=%s, security answer=%s", + username, password, security_question + ) + + # Continue to other login functionality + + +def main(): + """Main function showing login functionality""" + logger = logging.getLogger() + logger.setLevel(logging.INFO) + username = input("Enter your username: ") + password = input("Enter your password: ") + security_question = input("What is the name of your favorite pet?: ") + login_user(username, password, security_question) + + +main() +``` + +## Example Solution + +The `example01.py` solution uses a custom filter in Python's logging module to automatically mask sensitive data in the logs. While this is a good solution for central handling in large software project it does require that all modules use the same string such as `password=`, variations such as `pass=` or pass: won't work and continue to print the plain text password. + +*[example01.py](example01.py):* + +```py +""" Code Example """ + +import logging +import re + + +class RedactingFilter(logging.Filter): + """Function to redact any sensitive information from getting logged""" + def filter(self, record): + message = record.getMessage() + + # Perform redactions on copy of message + message = re.sub(r"password=\S+", "password=REDACTED", message) + message = re.sub(r"security_question_answer=\S+", + "security_question_answer=REDACTED", message) + + record.msg = message + record.args = () # Clear args to prevent further formatting attempts + + return True + + +def login_user(username, password, security_question): + """Function to login user with username password, and security question""" + logging.info( + "User %s login attempt: password=%s, security_question_answer=%s", + username, + password, + security_question, + ) + + # Continue to other login functionality + + +def main(): + """Main function showing login functionality""" + logger = logging.getLogger() + logger.setLevel(logging.INFO) + + # Add the custom filter to the logger + redacting_filter = RedactingFilter() + logger.addFilter(redacting_filter) + username = input("Enter your username: ") + password = input("Enter your password: ") + security_question = input("What is the name of your favorite pet?: ") + + login_user(username, password, security_question) + + +main() +``` + +## Compliant Solution (Logging) + +The `compliant01.py` solution doesn't log any sensitive information in the first place, which is a more ideal solution and position to be in. Instead of trying to conceal logged strings at a later stage, control over "classification" is decided during the collection/creation of the data. + +*[compliant01.py](compliant01.py):* + +```py +""" Compliant Code Example """ + +import logging + + +def login_user(username, password, security_question): + """Function to login user with username password, and security question""" + logging.info("User %s login attempt", username) + + # Continue to other login functionality + + +def main(): + """Main function showing login functionality""" + logger = logging.getLogger() + logger.setLevel(logging.INFO) + username = input("Enter your username: ") + password = input("Enter your password: ") + security_question = input("What is the name of your favorite pet?: ") + login_user(username, password, security_question) + + +main() +``` + +## Non-Compliant Code Example (Debugging) + +For security purposes, sensitive information should never be printed to the console in log messages (for instance, a passenger's age). In Python's logging module, there are five logging levels: + +* `DEBUG` +* `INFO` +* `WARNING` (default) +* `ERROR` +* `CRITICAL` + +If we set the level to `DEBUG` or `INFO` we will see the info and debug logs being printed to the console. +The `noncompliant02.py` code has the log level set to DEBUG is causing the customer's address to appear in the console. + +*[noncompliant02.py](noncompliant02.py):* + +```py +""" Non-compliant Code Example """ + +import logging + + +def process_order(address): + """Function for processing some online order""" + logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', + level=logging.DEBUG) + logger = logging.getLogger(__name__) + logger.info("Initial logging level: %s", + logging.getLevelName(logger.getEffectiveLevel())) + logger.debug("Processing order for address: %s", address) + + # Continue to process the order. + + +process_order("10 Grafton Street") +``` + +## Compliant Solution (Debugging) + +In the `compliant02.py` solution we set the log level to INFO , this ensures that only Info logs will get outputted to the console. The log level should only be set to DEBUG when the code is not on a live deployment. This configuration should be managed at the service or deployment level, not within individual code files. + +*[compliant02.py](compliant02.py):* + +```py +""" Compliant Code Example """ + +import logging + + +def process_order(address): + logging.basicConfig( + format="%(asctime)s %(levelname)s:%(message)s", level=logging.INFO + ) + logger = logging.getLogger(__name__) + + logger.info("Initial logging level: %s", logger.getEffectiveLevel()) + + logger.debug("Processing order for address: %s", address) + + # Continue to process the order. + + +process_order("10 Grafton Street") +``` + +## Related Guidelines + +||| +|:---|:---| +|[SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java?src=breadcrumbs)|[FIO13-J. Do not log sensitive information outside a trust boundary - SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/FIO13-J.+Do+not+log+sensitive+information+outside+a+trust+boundary)| +|[MITRE CWE Base](http://cwe.mitre.org/)|[CWE-359](http://cwe.mitre.org/data/definitions/359.html), Privacy Violation| +|[MITRE CWE Base](http://cwe.mitre.org/)|[CWE-532](http://cwe.mitre.org/data/definitions/532.html), Information Exposure through Log Files| +|[MITRE CWE Pillar](http://cwe.mitre.org/)| [CWE-664](https://cwe.mitre.org/data/definitions/664.html), Improper Control of a Resource Through its Lifetime| +|[RFC](https://www.rfc-editor.org/)| [RFC 5424: The Syslog Protocol](https://www.rfc-editor.org/rfc/rfc5424.html)| + +## Automated Detection + +|Tool|Version|Checker|Description| +|:----|:----|:----|:----| +|[Pylint](https://pylint.pycqa.org/)|2023.10.1|[W1203:logging-fstring-interpolation](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/logging-fstring-interpolation.html)|Use lazy % formatting in logging functions| + +## Biblography + +||| +|:---|:---| +|(Python Software Foundation 2023)|[logging - Logging facilty for Python](https://docs.python.org/3/library/logging.html) [accessed 11 May 2023]| +|California Consumer Privacy Act (CCPA) USA|[CCPA DIVISION 3. OBLIGATIONS [1427 - 3273.16]](https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?lawCode=CIV§ionNum=1798.150) [accessed 16 October 2024]| +|General Data Protection Regulation (GDPR)|[Fines / Penalties - General Data Protection Regulation (GDPR) (gdpr-info.eu)](https://gdpr-info.eu/issues/fines-penalties/) [accessed 16 October 2024]| +|European Commission International Data Protection|[Rules on international data transfers](https://commission.europa.eu/law/law-topic/data-protection/international-dimension-data-protection/rules-international-data-transfers_en) [accessed 16 October 2024]| diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant01.py new file mode 100644 index 00000000..4f1fe55d --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant01.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Compliant Code Example """ + +import logging + + +def login_user(username, password, security_question): + """Function to login user with username password, and security question""" + logging.info("User %s login attempt", username) + + # Continue to other login functionality + + +def main(): + """Main function showing login functionality""" + logger = logging.getLogger() + logger.setLevel(logging.INFO) + username = input("Enter your username: ") + password = input("Enter your password: ") + security_question = input("What is the name of your favorite pet?: ") + login_user(username, password, security_question) + + +main() diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant02.py b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant02.py new file mode 100644 index 00000000..1dc85679 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/compliant02.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Compliant Code Example """ + +import logging + + +def process_order(address): + """Function for processing some online order""" + logging.basicConfig( + format="%(asctime)s %(levelname)s:%(message)s", level=logging.INFO + ) + logger = logging.getLogger(__name__) + + logger.info("Initial logging level: %s", logger.getEffectiveLevel()) + + logger.debug("Processing order for address: %s", address) + + # Continue to process the order. + + +process_order("10 Grafton Street") diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/example01.py b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/example01.py new file mode 100644 index 00000000..7e18e797 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/example01.py @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Code Example """ + +import logging +import re + + +class RedactingFilter(logging.Filter): + """Function to redact any sensitive information from getting logged""" + def filter(self, record): + message = record.getMessage() + + # Perform redactions on copy of message + message = re.sub(r"password=\S+", "password=REDACTED", message) + message = re.sub(r"security_question_answer=\S+", + "security_question_answer=REDACTED", message) + + record.msg = message + record.args = () # Clear args to prevent further formatting attempts + + return True + + +def login_user(username, password, security_question): + """Function to login user with username password, and security question""" + logging.info( + "User %s login attempt: password=%s, security_question_answer=%s", + username, + password, + security_question, + ) + + # Continue to other login functionality + + +def main(): + """Main function showing login functionality""" + logger = logging.getLogger() + logger.setLevel(logging.INFO) + + # Add the custom filter to the logger + redacting_filter = RedactingFilter() + logger.addFilter(redacting_filter) + username = input("Enter your username: ") + password = input("Enter your password: ") + security_question = input("What is the name of your favorite pet?: ") + + login_user(username, password, security_question) + + +main() diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant01.py new file mode 100644 index 00000000..27c59c09 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant01.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Non-compliant Code Example """ + +import logging + + +def login_user(username, password, security_question): + """Function to login user with username password, and security question""" + logging.info( + "User %s login attempt: password=%s, security answer=%s", + username, password, security_question + ) + + # Continue to other login functionality + + +def main(): + """Main function showing login functionality""" + logger = logging.getLogger() + logger.setLevel(logging.INFO) + username = input("Enter your username: ") + password = input("Enter your password: ") + security_question = input("What is the name of your favorite pet?: ") + login_user(username, password, security_question) + + +main() diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant02.py b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant02.py new file mode 100644 index 00000000..2dbbc9c0 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-664/CWE-532/noncompliant02.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Non-compliant Code Example """ + +import logging + + +def process_order(address): + """Function for processing some online order""" + logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', + level=logging.DEBUG) + logger = logging.getLogger(__name__) + logger.info("Initial logging level: %s", + logging.getLevelName(logger.getEffectiveLevel())) + logger.debug("Processing order for address: %s", address) + + # Continue to process the order. + + +process_order("10 Grafton Street") diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/README.md b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/README.md new file mode 100644 index 00000000..3e7f4761 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/README.md @@ -0,0 +1,194 @@ +# CWE-755: Improper Handling of Exceptional Conditions + +There are two built-in Python modules that allow for file manipulation. The original module is called `os`. It provides the ability to perform various functions related to the operating system, among which are creating, updating, and deleting files [[Python docs - os]](https://docs.python.org/3/library/os.html). Python 3.4 introduced the `pathlib` module, which represents file paths as objects as opposed to string variables [[Python docs - pathlib]](https://docs.python.org/3/library/pathlib.html). + +Both modules use the same OS exceptions for file-related errors. Here are some of the common file-related exceptions: + +|Exception name|Description| +|:----|:----| +|`OSError`|Base exception for all OS-related error.| +|`FileExistsError`|Raised when trying to create a file or directory which already exists.| +|`FileNotFoundError`| Raised when a file or directory is requested but doesn’t exist.| +|`IsADirectoryError`|Raised when a file operation is requested on a directory.| +|`NotADirectoryError`|Raised when a directory operation is requested on something which is not a directory.| +|`PermissionError`|Raised when trying to run an operation without adequate access rights - for example, filesystem permissions.| + +The full list of OS exceptions can be found in the Python documentation [[Python docs - OS Exceptions](https://docs.python.org/3/library/exceptions.html#os-exceptions)]. + +It is important to handle those exceptions when performing file I/O operations. + +## Non-Compliant Code Example (`os.remove()`/`os.unlink()`) + +This code example demonstrates an attempt to read a non-existent file using the `os` module. The `read_file()` function opens a file and reads its content using `os.open()` and `os.read()`. If the file does not exist, an `OSError` or `FileNotFoundError` will be raised when trying to access the randomly generated file name. + +*[noncompliant01.py](noncompliant01.py):* + +```py +""" Non-compliant Code Example """ + +import os +import uuid + + +def read_file(file): + """Function for opening a file and reading it's content.""" + fd = os.open(file, os.O_RDONLY) + content = os.read(fd) + return content.decode() + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") +``` + +## Compliant Solution (`try/except` blocks) + +The file opening and reading should be surrounded by the `try/except` block. This way, we can catch the generic `OSError` and handle the error differently depending on its cause (such as the file not existing or it being a directory instead). + +*[compliant01.py](compliant01.py):* + +```py +""" Compliant Code Example """ + +import os +import uuid + + +def read_file(file): + """Function for opening a file and reading its content.""" + try: + fd = os.open(file, os.O_RDONLY) + try: + content = os.read(fd, 1024) + finally: + os.close(fd) + return content.decode() + except OSError as e: + if not os.path.exists(file): + print(f"File not found: {file}") + elif os.path.isdir(file): + print(f"Is a directory: {file}") + else: + print(f"An error occurred: {e}") + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") +``` + +## Non-Compliant Code Example (`pathlib.Path.unlink()`) + +The `pathlib` module also provides functions for opening and reading files. The `Path.read_text()` method attempts to read the content of the file represented by the `Path` object. If the file does not exist, it will raise a `FileNotFoundError`. In this code example, this exception is expected when attempting to read a randomly generated non-existent file. + +*[noncompliant02.py](noncompliant02.py):* + +```py +""" Non-compliant Code Example """ + +import uuid +from pathlib import Path + + +def read_file(file): + """Function for opening a file and reading its content.""" + path = Path(file) + content = path.read_text(encoding="utf-8") + return content + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") +``` + +The `pathlib.Path.unlink()` function has an optional parameter `missing_ok` that will suppress the `FileNotFoundError` on file deletion, if the parameter's value is `True` . However, without proper handling, using this parameter will cause the script to fail silently. + +*[noncompliant03.py](noncompliant03.py):* + +```py +""" Non-compliant Code Example """ + +import pathlib +import uuid + + +def delete_temporary_file(file): + """Function for deleting a temporary file from a certain location""" + resource_path = pathlib.Path(file) + resource_path.unlink(missing_ok=True) + + +##################### +# exploiting above code example +##################### +# Attempting to remove a random non-existent file +delete_temporary_file(f"{uuid.uuid4()}.txt") +``` + +## Compliant Solution (`pathlib` module) + +Since the `pathlib` module uses the same exceptions as the `os` module, error handling can be implemented in the same way. + +*[compliant02.py](compliant02.py):* + +```py +""" Non-compliant Code Example """ + +import uuid +from pathlib import Path + + +def read_file(file): + """Function for opening a file and reading its content.""" + path = Path(file) + try: + content = path.read_text(encoding="utf-8") + return content + except OSError as e: + if path.is_dir(): + print(f"Is a directory: {file}") + elif not path.exists(): + print(f"File not found: {file}") + else: + print(f"An error occurred: {e}") + return None + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") +``` + +## Automated Detection + +||||| +|:---|:---|:---|:---| +|Tool|Version|Checker|Description| +|no detection|||| + +## Related Guidelines + +||| +|:---|:---| +|[SEI CERT C++ Coding Standard](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682)|[VOID FIO04-CPP. Detect and handle input and output errors](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046775)| +|[SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/SEI+CERT+Oracle+Coding+Standard+for+Java)|[FIO02-J. Detect and handle file-related errors - SEI CERT Oracle Coding Standard for Java](https://wiki.sei.cmu.edu/confluence/display/java/FIO02-J.+Detect+and+handle+file-related+errors)| +|[CWE MITRE Pillar](https://cwe.mitre.org/)|[CWE-703](https://cwe.mitre.org/data/definitions/703.html), Improper Check or Handling of Exceptional Conditions| +|[CWE MITRE Class](https://cwe.mitre.org/)|[CWE-755](https://cwe.mitre.org/data/definitions/755.html), Improper Handling of Exceptional Conditions| + +## Biblography + +||| +|:---|:---| +|[Python-docs - os](https://docs.python.org/3/library/os.html)|[Python Software Foundation. (2023). os - Miscellaneous operating system interfaces [online]](https://docs.python.org/3/library/os.html) [accessed 27 July 2023].| +|[Python docs - pathlib](https://docs.python.org/3/library/pathlib.html)|[Python Software Foundation. (2023). pathlib - Object-oriented filesystem paths [online]](https://docs.python.org/3/library/pathlib.html) [accessed 27 July 2023]| +|[Python docs - OS Exceptions](https://docs.python.org/3/library/exceptions.html#os-exceptions)|[Python Software Foundation. (2023). Built-in Exceptions - OS Exceptions [online]](https://docs.python.org/3/library/exceptions.html#os-exceptions) [accessed 27 July 2023]| diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/compliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/compliant01.py new file mode 100644 index 00000000..0487ec8a --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/compliant01.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Non-compliant Code Example """ + +import os +import uuid + + +def read_file(file): + """Function for opening a file and reading its content.""" + try: + fd = os.open(file, os.O_RDONLY) + try: + content = os.read(fd, 1024) + finally: + os.close(fd) + return content.decode() + except OSError as e: + if not os.path.exists(file): + print(f"File not found: {file}") + elif os.path.isdir(file): + print(f"Is a directory: {file}") + else: + print(f"An error occurred: {e}") + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/compliant02.py b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/compliant02.py new file mode 100644 index 00000000..a58946f4 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/compliant02.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Non-compliant Code Example """ + +import uuid +from pathlib import Path + + +def read_file(file): + """Function for opening a file and reading its content.""" + path = Path(file) + try: + content = path.read_text(encoding="utf-8") + return content + except OSError as e: + if path.is_dir(): + print(f"Is a directory: {file}") + elif not path.exists(): + print(f"File not found: {file}") + else: + print(f"An error occurred: {e}") + return None + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant01.py new file mode 100644 index 00000000..cf57b8c5 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant01.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Non-compliant Code Example """ + +import os +import uuid + + +def read_file(file): + """Function for opening a file and reading it's content.""" + fd = os.open(file, os.O_RDONLY) + content = os.read(fd) + return content.decode() + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant02.py b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant02.py new file mode 100644 index 00000000..2c2518bb --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant02.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Non-compliant Code Example """ + +import uuid +from pathlib import Path + + +def read_file(file): + """Function for opening a file and reading its content.""" + path = Path(file) + content = path.read_text(encoding="utf-8") + return content + + +##################### +# exploiting above code example +##################### +# Attempting to read a random non-existent file +read_file(f"{uuid.uuid4()}.txt") diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant03.py b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant03.py new file mode 100644 index 00000000..842a77e8 --- /dev/null +++ b/docs/Secure-Coding-Guide-for-Python/CWE-703/CWE-755/noncompliant03.py @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: OpenSSF project contributors +# SPDX-License-Identifier: MIT +""" Non-compliant Code Example """ + +import pathlib +import uuid + + +def delete_temporary_file(file): + """Function for deleting a temporary file from a certain location""" + resource_path = pathlib.Path(file) + resource_path.unlink(missing_ok=True) + + +##################### +# exploiting above code example +##################### +# Attempting to remove a random non-existent file +delete_temporary_file(f"{uuid.uuid4()}.txt") diff --git a/docs/Secure-Coding-Guide-for-Python/readme.md b/docs/Secure-Coding-Guide-for-Python/readme.md index 35225f0b..1efa7118 100644 --- a/docs/Secure-Coding-Guide-for-Python/readme.md +++ b/docs/Secure-Coding-Guide-for-Python/readme.md @@ -49,6 +49,7 @@ It is **not production code** and requires code-style or python best practices t |[CWE-426: Untrusted Search Path](CWE-664/CWE-426/README.md)|[CVE-2015-1326](https://www.cvedetails.com/cve/CVE-2015-1326),
CVSSv3.0: **8.8**,
EPSS: **00.20** (23.11.2023)| |[CWE-501: Trust Boundary Violation)](CWE-664/CWE-501/README.md)|| |[CWE-502: Deserialization of Untrusted Data)](CWE-664/CWE-502/.)|| +|[CWE-532: Insertion of Sensitive Information into Log File](CWE-664/CWE-532/.)|| |[CWE-665: Improper Initialization](CWE-664/CWE-665/README.md)|| |[CWE-681: Incorrect Conversion between Numeric Types](CWE-664/CWE-681/README.md)|| |[CWE-833: Deadlock](CWE-664/CWE-833/README.md)|| @@ -81,6 +82,7 @@ It is **not production code** and requires code-style or python best practices t |[CWE-390: Detection of Error Condition without Action](CWE-703/CWE-390/)|| |[CWE-392: Missing Report of Error Condition](CWE-703/CWE-392/README.md)|| |[CWE-754: Improper Check for Unusual or Exceptional Conditions](CWE-703/CWE-754/.)|| +|[CWE-755: Improper Handling of Exceptional Conditions](CWE-703/CWE-755/.)|| |[CWE-707: Improper Neutralization](https://cwe.mitre.org/data/definitions/707.html)|Prominent CVE| |:----------------------------------------------------------------|:----|