PEP 578 Python Runtime Audit Hooks | peps.python.org
Python provides access to a wide range of low-level functionality on many common operating systems. While this is incredibly useful for write-once, run-anywhere scripting, it also makes monitoring of software written in Python difficult. Because Python uses native system APIs directly, existing monitoring tools either suffer from limited context or auditing bypass.
Limited context occurs when system monitoring can report that an action occurred, but cannot explain the sequence of events leading to it. For example, network monitoring at the OS level may be able to report listening started on port 5678, but may not be able to provide the process ID, command line, parent process, or the local state in the program at the point that triggered the action. Firewall controls to prevent such an action are similarly limited, typically to process names or some global state such as the current user, and in any case rarely provide a useful log file correlated with other application messages.
Auditing bypass can occur when the typical system tool used for an action would ordinarily report its use, but accessing the APIs via Python do not trigger this. For example, invoking curl to make HTTP requests may be specifically monitored in an audited system, but Pythons urlretrieve function is not.
Within a long-running Python application, particularly one that processes user-provided information such as a web app, there is a risk of unexpected behavior. This may be due to bugs in the code or deliberately induced by a malicious user. In both cases, normal application logging may be bypassed resulting in no indication that anything out of the ordinary has occurred.
Additionally, and somewhat unique to Python, it is very easy to affect the code that is run in an application by manipulating either the import systems search path or placing files earlier on the path than intended. This is often seen when developers create a script with the same name as the module they intend to use for example, a random.py file that attempts to import the standard library random module.
This proposal goals to enable both application developers and system administrators to integrate Python into their existing monitoring systems without dictating how those systems look or behave. The goal is to provide an API for auditing hooks and verified open hooks, which will allow embedders and CPython implementors to send and receive audit hook messages.
The proposal suggests adding a new module called “audit” that would separate the API and implementation from the sys module. This would enable applications to detect when some features are enabled or when hooks have been added and modify their behavior appropriately. However, this idea is rejected because there are no appropriate reasons for an application to change its behavior based on whether these APIs are in use.
The proposal also suggests adding a value in sys.flags to indicate when Python is running in a “secure” or “audited” mode. This would allow applications to detect when some features are enabled or when hooks have been added and modify their behavior appropriately. However, this idea is rejected because there are no appropriate reasons for an application to change its behavior based on whether these APIs are in use.
The proposal does not attempt to restrict functionality but simply exposes the fact that the functionality is being used. Particularly for intrusion scenarios, detection is significantly more important than early prevention (as early prevention will generally drive attackers to use an alternate, less-detectable, approach). The availability of audit hooks alone does not change the attack surface of Python in any way but enables defenders to integrate Python into their environment in ways that are currently not possible.