[Python-checkins] bpo-37363: Add audit events for a range of modules (GH-14301)

Miss Islington (bot) webhook-mailer at python.org
Mon Jun 24 12:09:55 EDT 2019


https://github.com/python/cpython/commit/8763d43a9558b345af6a3a298afa18e7d3b42fd0
commit: 8763d43a9558b345af6a3a298afa18e7d3b42fd0
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2019-06-24T09:09:47-07:00
summary:

bpo-37363: Add audit events for a range of modules (GH-14301)

(cherry picked from commit 60419a7e96577cf783b3b45bf3984f9fb0d7ddff)

Co-authored-by: Steve Dower <steve.dower at python.org>

files:
A Misc/NEWS.d/next/Security/2019-06-21-15-58-59.bpo-37363.diouyl.rst
M Doc/library/ctypes.rst
M Doc/library/ensurepip.rst
M Doc/library/ftplib.rst
M Doc/library/functions.rst
M Doc/library/glob.rst
M Doc/library/imaplib.rst
M Doc/library/io.rst
M Doc/library/nntplib.rst
M Doc/library/os.rst
M Doc/library/pdb.rst
M Doc/library/poplib.rst
M Doc/library/shutil.rst
M Doc/library/smtplib.rst
M Doc/library/sqlite3.rst
M Doc/library/subprocess.rst
M Doc/library/telnetlib.rst
M Doc/library/tempfile.rst
M Doc/library/urllib.request.rst
M Doc/library/webbrowser.rst
M Doc/tools/extensions/suspicious.py
M Lib/ensurepip/__init__.py
M Lib/ftplib.py
M Lib/glob.py
M Lib/imaplib.py
M Lib/nntplib.py
M Lib/pdb.py
M Lib/poplib.py
M Lib/shutil.py
M Lib/smtplib.py
M Lib/subprocess.py
M Lib/telnetlib.py
M Lib/tempfile.py
M Lib/webbrowser.py
M Modules/_sqlite/module.c
M Modules/posixmodule.c
M Python/bltinmodule.c

diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index 97172c588ae9..c1218ad32ec8 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -2046,7 +2046,7 @@ Data types
       .. audit-event:: ctypes.cdata address
 
          This method, and others that indirectly call this method, raises an
-         :func:`auditing event <sys.audit>` ``ctypes.cdata`` with argument
+         :ref:`auditing event <auditing>` ``ctypes.cdata`` with argument
          ``address``.
 
    .. method:: from_param(obj)
diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst
index c797f63326d1..3b6b01fb4524 100644
--- a/Doc/library/ensurepip.rst
+++ b/Doc/library/ensurepip.rst
@@ -119,6 +119,8 @@ Module API
    *verbosity* controls the level of output to :data:`sys.stdout` from the
    bootstrapping operation.
 
+   .. audit-event:: ensurepip.bootstrap root
+
    .. note::
 
       The bootstrapping process has side effects on both ``sys.path`` and
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index 6c39f9a59fc1..36abfbde3e34 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -190,6 +190,8 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
    *source_address* is a 2-tuple ``(host, port)`` for the socket to bind to as
    its source address before connecting.
 
+   .. audit-event:: ftplib.FTP.connect "self host port"
+
    .. versionchanged:: 3.3
       *source_address* parameter was added.
 
@@ -223,6 +225,8 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
 
    Send a simple command string to the server and return the response string.
 
+   .. audit-event:: ftplib.FTP.sendcmd "self cmd"
+
 
 .. method:: FTP.voidcmd(cmd)
 
@@ -230,6 +234,8 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
    nothing if a response code corresponding to success (codes in the range
    200--299) is received.  Raise :exc:`error_reply` otherwise.
 
+   .. audit-event:: ftplib.FTP.sendcmd "self cmd"
+
 
 .. method:: FTP.retrbinary(cmd, callback, blocksize=8192, rest=None)
 
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 88977056723f..637c82b67080 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -128,6 +128,8 @@ are always available.  They are listed here in alphabetical order.
    :func:`breakpoint` will automatically call that, allowing you to drop into
    the debugger of choice.
 
+   .. audit-event:: builtins.breakpoint "sys.breakpointhook"
+
    .. versionadded:: 3.7
 
 .. _func-bytearray:
@@ -277,7 +279,7 @@ are always available.  They are listed here in alphabetical order.
 
    .. audit-event:: compile "source filename"
 
-      Raises an :func:`auditing event <sys.audit>` ``compile`` with arguments
+      Raises an :ref:`auditing event <auditing>` ``compile`` with arguments
       ``source`` and ``filename``. This event may also be raised by implicit
       compilation.
 
@@ -490,8 +492,8 @@ are always available.  They are listed here in alphabetical order.
 
    .. audit-event:: exec code_object
 
-      Raises an :func:`auditing event <sys.audit>` ``exec`` with the code object as
-      the argument. Code compilation events may also be raised.
+      Raises an :ref:`auditing event <auditing>` ``exec`` with the code object
+      as the argument. Code compilation events may also be raised.
 
 .. index:: builtin: exec
 
@@ -525,8 +527,8 @@ are always available.  They are listed here in alphabetical order.
 
    .. audit-event:: exec code_object
 
-      Raises an :func:`auditing event <sys.audit>` ``exec`` with the code object as
-      the argument. Code compilation events may also be raised.
+      Raises an :ref:`auditing event <auditing>` ``exec`` with the code object
+      as the argument. Code compilation events may also be raised.
 
    .. note::
 
@@ -779,7 +781,7 @@ are always available.  They are listed here in alphabetical order.
 
    .. audit-event:: builtins.input prompt
 
-      Raises an :func:`auditing event <sys.audit>` ``builtins.input`` with
+      Raises an :ref:`auditing event <auditing>` ``builtins.input`` with
       argument ``prompt`` before reading input
 
    .. audit-event:: builtins.input/result result
diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst
index 2a5f0ddc4ef3..1f29fc562dde 100644
--- a/Doc/library/glob.rst
+++ b/Doc/library/glob.rst
@@ -52,6 +52,8 @@ For example, ``'[?]'`` matches the character ``'?'``.
    more directories and subdirectories.  If the pattern is followed by an
    ``os.sep``, only directories and subdirectories match.
 
+   .. audit-event:: glob.glob "pathname recursive"
+
    .. note::
       Using the "``**``" pattern in large directory trees may consume
       an inordinate amount of time.
@@ -65,6 +67,8 @@ For example, ``'[?]'`` matches the character ``'?'``.
    Return an :term:`iterator` which yields the same values as :func:`glob`
    without actually storing them all simultaneously.
 
+   .. audit-event:: glob.glob "pathname recursive"
+
 
 .. function:: escape(pathname)
 
diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst
index f027f82ddebe..c08c0a5591bd 100644
--- a/Doc/library/imaplib.rst
+++ b/Doc/library/imaplib.rst
@@ -361,6 +361,8 @@ An :class:`IMAP4` instance has the following methods:
    :meth:`IMAP4.send`, and :meth:`IMAP4.shutdown` methods.  You may override
    this method.
 
+   .. audit-event:: imaplib.IMAP4.open "self host port"
+
 
 .. method:: IMAP4.partial(message_num, message_part, start, length)
 
@@ -430,6 +432,8 @@ An :class:`IMAP4` instance has the following methods:
 
    Sends ``data`` to the remote server. You may override this method.
 
+   .. audit-event:: imaplib.IMAP4.send "self data"
+
 
 .. method:: IMAP4.setacl(mailbox, who, what)
 
diff --git a/Doc/library/io.rst b/Doc/library/io.rst
index 5ae30a3b5899..28c5da96d904 100644
--- a/Doc/library/io.rst
+++ b/Doc/library/io.rst
@@ -122,7 +122,7 @@ High-level Module Interface
 
    .. audit-event:: open "path mode flags"
 
-      This function raises an :func:`auditing event <sys.audit>` ``open`` with
+      This function raises an :ref:`auditing event <auditing>` ``open`` with
       arguments ``path``, ``mode`` and ``flags``. The ``mode`` and ``flags``
       arguments may have been modified or inferred from the original call.
 
diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst
index 56188c7ef538..297bbedc867f 100644
--- a/Doc/library/nntplib.rst
+++ b/Doc/library/nntplib.rst
@@ -79,6 +79,11 @@ The module itself defines the following classes:
     ('211 1755 1 1755 gmane.comp.python.committers', 1755, 1, 1755, 'gmane.comp.python.committers')
     >>>
 
+   .. audit-event:: nntplib.NNTP "self host port"
+
+   All commands will raise an :ref:`auditing event <auditing>`
+   ``nntplib.NNTP.putline`` with arguments ``self`` and ``line``,
+   where ``line`` is the bytes about to be sent to the remote host.
 
    .. versionchanged:: 3.2
       *usenetrc* is now ``False`` by default.
@@ -100,6 +105,12 @@ The module itself defines the following classes:
    STARTTLS as described below.  However, some servers only support the
    former.
 
+   .. audit-event:: nntplib.NNTP "self host port"
+
+   All commands will raise an :ref:`auditing event <auditing>`
+   ``nntplib.NNTP.putline`` with arguments ``self`` and ``line``,
+   where ``line`` is the bytes about to be sent to the remote host.
+
    .. versionadded:: 3.2
 
    .. versionchanged:: 3.4
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index f0df35e9ddd5..e7acb356d38b 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -1801,6 +1801,8 @@ features:
    This function can also support :ref:`specifying a file descriptor
    <path_fd>`; the file descriptor must refer to a directory.
 
+   .. audit-event:: os.listdir path
+
    .. note::
       To encode ``str`` filenames to ``bytes``, use :func:`~os.fsencode`.
 
@@ -2178,6 +2180,8 @@ features:
    This function can also support :ref:`specifying a file descriptor
    <path_fd>`; the file descriptor must refer to a directory.
 
+   .. audit-event:: os.scandir path
+
    The :func:`scandir` iterator supports the :term:`context manager` protocol
    and has the following method:
 
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index c7864e9e3f22..7ebad79130ae 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -181,6 +181,8 @@ access further features, you have to do this yourself:
 
       import pdb; pdb.Pdb(skip=['django.*']).set_trace()
 
+   .. audit-event:: pdb.Pdb
+
    .. versionadded:: 3.1
       The *skip* argument.
 
diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst
index d72b660d6ea9..d227b53ff909 100644
--- a/Doc/library/poplib.rst
+++ b/Doc/library/poplib.rst
@@ -39,6 +39,12 @@ The :mod:`poplib` module provides two classes:
    connection attempt (if not specified, the global default timeout setting will
    be used).
 
+   .. audit-event:: poplib.POP3 "self host port"
+
+   All commands will raise an :ref:`auditing event <auditing>`
+   ``poplib.POP3.putline`` with arguments ``self`` and ``line``,
+   where ``line`` is the bytes about to be sent to the remote host.
+
 
 .. class:: POP3_SSL(host, port=POP3_SSL_PORT, keyfile=None, certfile=None, timeout=None, context=None)
 
@@ -54,6 +60,12 @@ The :mod:`poplib` module provides two classes:
    point to PEM-formatted private key and certificate chain files,
    respectively, for the SSL connection.
 
+   .. audit-event:: poplib.POP3 "self host port"
+
+   All commands will raise an :ref:`auditing event <auditing>`
+   ``poplib.POP3.putline`` with arguments ``self`` and ``line``,
+   where ``line`` is the bytes about to be sent to the remote host.
+
    .. versionchanged:: 3.2
       *context* parameter added.
 
diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
index dcb2a16cff98..3cca9c84a27f 100644
--- a/Doc/library/shutil.rst
+++ b/Doc/library/shutil.rst
@@ -249,6 +249,8 @@ Directory and files operations
    as arguments. By default, :func:`~shutil.copy2` is used, but any function
    that supports the same signature (like :func:`~shutil.copy`) can be used.
 
+   .. audit-event:: shutil.copytree "src dst"
+
    .. versionchanged:: 3.3
       Copy metadata when *symlinks* is false.
       Now returns *dst*.
@@ -296,6 +298,8 @@ Directory and files operations
    *excinfo*, will be the exception information returned by
    :func:`sys.exc_info`.  Exceptions raised by *onerror* will not be caught.
 
+   .. audit-event:: shutil.rmtree path
+
    .. versionchanged:: 3.3
       Added a symlink attack resistant version that is used automatically
       if platform supports fd-based functions.
@@ -558,6 +562,8 @@ provided.  They rely on the :mod:`zipfile` and :mod:`tarfile` modules.
 
    The *verbose* argument is unused and deprecated.
 
+   .. audit-event:: shutil.make_archive "base_name format root_dir base_dir"
+
    .. versionchanged:: 3.8
       The modern pax (POSIX.1-2001) format is now used instead of
       the legacy GNU format for archives created with ``format="tar"``.
diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst
index 2c3a5f0c6f72..8771f1093804 100644
--- a/Doc/library/smtplib.rst
+++ b/Doc/library/smtplib.rst
@@ -55,6 +55,10 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
     (250, b'Ok')
     >>>
 
+   All commands will raise an :ref:`auditing event <auditing>`
+   ``smtplib.SMTP.send`` with arguments ``self`` and ``data``,
+   where ``data`` is the bytes about to be sent to the remote host.
+
    .. versionchanged:: 3.3
       Support for the :keyword:`with` statement was added.
 
@@ -242,6 +246,8 @@ An :class:`SMTP` instance has the following methods:
    2-tuple of the response code and message sent by the server in its
    connection response.
 
+   .. audit-event:: smtplib.SMTP.connect "self host port"
+
 
 .. method:: SMTP.helo(name='')
 
diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst
index 20fca54aab14..e0411fed2f9c 100644
--- a/Doc/library/sqlite3.rst
+++ b/Doc/library/sqlite3.rst
@@ -224,6 +224,8 @@ Module functions and constants
    More information about this feature, including a list of recognized options, can
    be found in the `SQLite URI documentation <https://www.sqlite.org/uri.html>`_.
 
+   .. audit-event:: sqlite3.connect "database"
+
    .. versionchanged:: 3.4
       Added the *uri* parameter.
 
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
index ede5c3c5a369..ad49d7f20176 100644
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -585,6 +585,13 @@ functions.
       with Popen(["ifconfig"], stdout=PIPE) as proc:
           log.write(proc.stdout.read())
 
+   .. audit-event:: subprocess.Popen "executable args cwd env"
+
+      Popen and the other functions in this module that use it raise an
+      :ref:`auditing event <auditing>` ``subprocess.Popen`` with arguments
+      ``executable``, ``args``, ``cwd``, ``env``. The value for ``args``
+      may be a single string or a list of strings, depending on platform.
+
    .. versionchanged:: 3.2
       Added context manager support.
 
diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst
index 4ba426425277..d238136567cc 100644
--- a/Doc/library/telnetlib.rst
+++ b/Doc/library/telnetlib.rst
@@ -141,6 +141,8 @@ Telnet Objects
 
    Do not try to reopen an already connected instance.
 
+   .. audit-event:: telnetlib.Telnet.open "self host port"
+
 
 .. method:: Telnet.msg(msg, *args)
 
@@ -176,6 +178,8 @@ Telnet Objects
    block if the connection is blocked.  May raise :exc:`OSError` if the
    connection is closed.
 
+   .. audit-event:: telnetlib.Telnet.write "self buffer"
+
    .. versionchanged:: 3.3
       This method used to raise :exc:`socket.error`, which is now an alias
       of :exc:`OSError`.
diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst
index daa6f621f137..98069f2442c7 100644
--- a/Doc/library/tempfile.rst
+++ b/Doc/library/tempfile.rst
@@ -62,6 +62,8 @@ The module defines the following user-callable items:
    The :py:data:`os.O_TMPFILE` flag is used if it is available and works
    (Linux-specific, requires Linux kernel 3.11 or later).
 
+   .. audit-event:: tempfile.mkstemp "full-path"
+
    .. versionchanged:: 3.5
 
       The :py:data:`os.O_TMPFILE` flag is now used if available.
@@ -85,6 +87,8 @@ The module defines the following user-callable items:
    attribute is the underlying true file object. This file-like object can
    be used in a :keyword:`with` statement, just like a normal file.
 
+   .. audit-event:: tempfile.mkstemp "full-path"
+
    .. versionchanged:: 3.8
       Added *errors* parameter.
 
@@ -130,6 +134,8 @@ The module defines the following user-callable items:
    The directory can be explicitly cleaned up by calling the
    :func:`cleanup` method.
 
+   .. audit-event:: tempfile.mkdtemp "full-path"
+
    .. versionadded:: 3.2
 
 
@@ -177,6 +183,8 @@ The module defines the following user-callable items:
    file (as would be returned by :func:`os.open`) and the absolute pathname
    of that file, in that order.
 
+   .. audit-event:: tempfile.mkstemp "full-path"
+
    .. versionchanged:: 3.5
       *suffix*, *prefix*, and *dir* may now be supplied in bytes in order to
       obtain a bytes return value.  Prior to this, only str was allowed.
@@ -198,6 +206,8 @@ The module defines the following user-callable items:
 
    :func:`mkdtemp` returns the absolute pathname of the new directory.
 
+   .. audit-event:: tempfile.mkdtemp "full-path"
+
    .. versionchanged:: 3.5
       *suffix*, *prefix*, and *dir* may now be supplied in bytes in order to
       obtain a bytes return value.  Prior to this, only str was allowed.
diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst
index a53c969ec629..9f8869c87f62 100644
--- a/Doc/library/urllib.request.rst
+++ b/Doc/library/urllib.request.rst
@@ -97,7 +97,7 @@ The :mod:`urllib.request` module defines the following functions:
 
    .. audit-event:: urllib.Request "fullurl data headers method"
 
-      The default opener raises an :func:`auditing event <sys.audit>`
+      The default opener raises an :ref:`auditing event <auditing>`
       ``urllib.Request`` with arguments ``fullurl``, ``data``, ``headers``,
       ``method`` taken from the request object.
 
diff --git a/Doc/library/webbrowser.rst b/Doc/library/webbrowser.rst
index 9dc5551398ee..85e932d5a228 100644
--- a/Doc/library/webbrowser.rst
+++ b/Doc/library/webbrowser.rst
@@ -64,6 +64,8 @@ The following functions are defined:
    may work and start the operating system's associated program.  However, this
    is neither supported nor portable.
 
+   .. audit-event:: webbrowser.open "url"
+
 
 .. function:: open_new(url)
 
diff --git a/Doc/tools/extensions/suspicious.py b/Doc/tools/extensions/suspicious.py
index 494efabc4623..34a0112f5a00 100644
--- a/Doc/tools/extensions/suspicious.py
+++ b/Doc/tools/extensions/suspicious.py
@@ -115,8 +115,8 @@ def write_doc(self, docname, doctree):
     def finish(self):
         unused_rules = [rule for rule in self.rules if not rule.used]
         if unused_rules:
-            self.warn('Found %s/%s unused rules:' %
-                      (len(unused_rules), len(self.rules)))
+            self.logger.warn('Found %s/%s unused rules:' %
+                             (len(unused_rules), len(self.rules)))
             for rule in unused_rules:
                 self.logger.info(repr(rule))
         return
@@ -151,10 +151,10 @@ def report_issue(self, text, lineno, issue):
         self.any_issue = True
         self.write_log_entry(lineno, issue, text)
         if py3:
-            self.warn('[%s:%d] "%s" found in "%-.120s"' %
-                      (self.docname, lineno, issue, text))
+            self.logger.warn('[%s:%d] "%s" found in "%-.120s"' %
+                             (self.docname, lineno, issue, text))
         else:
-            self.warn('[%s:%d] "%s" found in "%-.120s"' % (
+            self.logger.warn('[%s:%d] "%s" found in "%-.120s"' % (
                 self.docname.encode(sys.getdefaultencoding(),'replace'),
                 lineno,
                 issue.encode(sys.getdefaultencoding(),'replace'),
diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
index 526dfd004a41..6f2569da8167 100644
--- a/Lib/ensurepip/__init__.py
+++ b/Lib/ensurepip/__init__.py
@@ -73,6 +73,8 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
     if altinstall and default_pip:
         raise ValueError("Cannot use altinstall and default_pip together")
 
+    sys.audit("ensurepip.bootstrap", root)
+
     _disable_pip_configuration_settings()
 
     # By default, installing pip and setuptools installs all of the
diff --git a/Lib/ftplib.py b/Lib/ftplib.py
index a9b1aee39e4a..27bf6daea612 100644
--- a/Lib/ftplib.py
+++ b/Lib/ftplib.py
@@ -148,6 +148,7 @@ def connect(self, host='', port=0, timeout=-999, source_address=None):
             self.timeout = timeout
         if source_address is not None:
             self.source_address = source_address
+        sys.audit("ftplib.FTP.connect", self, self.host, self.port)
         self.sock = socket.create_connection((self.host, self.port), self.timeout,
                                              source_address=self.source_address)
         self.af = self.sock.family
@@ -188,6 +189,7 @@ def sanitize(self, s):
     def putline(self, line):
         if '\r' in line or '\n' in line:
             raise ValueError('an illegal newline character should not be contained')
+        sys.audit("ftplib.FTP.sendcmd", self, line)
         line = line + CRLF
         if self.debugging > 1:
             print('*put*', self.sanitize(line))
diff --git a/Lib/glob.py b/Lib/glob.py
index 002cd920190d..0b3fcc6bbb9a 100644
--- a/Lib/glob.py
+++ b/Lib/glob.py
@@ -3,6 +3,7 @@
 import os
 import re
 import fnmatch
+import sys
 
 __all__ = ["glob", "iglob", "escape"]
 
@@ -37,6 +38,7 @@ def iglob(pathname, *, recursive=False):
     return it
 
 def _iglob(pathname, recursive, dironly):
+    sys.audit("glob.glob", pathname, recursive)
     dirname, basename = os.path.split(pathname)
     if not has_magic(pathname):
         assert not dironly
diff --git a/Lib/imaplib.py b/Lib/imaplib.py
index 341ee25ae965..face45ba5fa0 100644
--- a/Lib/imaplib.py
+++ b/Lib/imaplib.py
@@ -289,6 +289,7 @@ def _create_socket(self):
         # (which is used by socket.create_connection()) expects None
         # as a default value for host.
         host = None if not self.host else self.host
+        sys.audit("imaplib.IMAP4.open", self, self.host, self.port)
         return socket.create_connection((host, self.port))
 
     def open(self, host = '', port = IMAP4_PORT):
@@ -318,6 +319,7 @@ def readline(self):
 
     def send(self, data):
         """Send data to remote."""
+        sys.audit("imaplib.IMAP4.send", self, data)
         self.sock.sendall(data)
 
 
diff --git a/Lib/nntplib.py b/Lib/nntplib.py
index 5961a28ab7d9..e7bbc853c078 100644
--- a/Lib/nntplib.py
+++ b/Lib/nntplib.py
@@ -68,6 +68,7 @@
 import collections
 import datetime
 import warnings
+import sys
 
 try:
     import ssl
@@ -413,6 +414,7 @@ def set_debuglevel(self, level):
     def _putline(self, line):
         """Internal: send one line to the server, appending CRLF.
         The `line` must be a bytes-like object."""
+        sys.audit("nntplib.NNTP.putline", self, line)
         line = line + _CRLF
         if self.debugging > 1: print('*put*', repr(line))
         self.file.write(line)
@@ -1040,6 +1042,7 @@ def __init__(self, host, port=NNTP_PORT, user=None, password=None,
         """
         self.host = host
         self.port = port
+        sys.audit("nntplib.NNTP", self, host, port)
         self.sock = socket.create_connection((host, port), timeout)
         file = None
         try:
@@ -1071,6 +1074,7 @@ def __init__(self, host, port=NNTP_SSL_PORT,
             """This works identically to NNTP.__init__, except for the change
             in default port and the `ssl_context` argument for SSL connections.
             """
+            sys.audit("nntplib.NNTP", self, host, port)
             self.sock = socket.create_connection((host, port), timeout)
             file = None
             try:
diff --git a/Lib/pdb.py b/Lib/pdb.py
index 0e7609e43d4e..5e62f392d932 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -141,6 +141,7 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
                  nosigint=False, readrc=True):
         bdb.Bdb.__init__(self, skip=skip)
         cmd.Cmd.__init__(self, completekey, stdin, stdout)
+        sys.audit("pdb.Pdb")
         if stdout:
             self.use_rawinput = 0
         self.prompt = '(Pdb) '
diff --git a/Lib/poplib.py b/Lib/poplib.py
index 9796f0d2f9c5..ced0a2d53c52 100644
--- a/Lib/poplib.py
+++ b/Lib/poplib.py
@@ -16,6 +16,7 @@
 import errno
 import re
 import socket
+import sys
 
 try:
     import ssl
@@ -99,6 +100,7 @@ def __init__(self, host, port=POP3_PORT,
         self.host = host
         self.port = port
         self._tls_established = False
+        sys.audit("poplib.POP3", self, host, port)
         self.sock = self._create_socket(timeout)
         self.file = self.sock.makefile('rb')
         self._debugging = 0
@@ -109,6 +111,7 @@ def _create_socket(self, timeout):
 
     def _putline(self, line):
         if self._debugging > 1: print('*put*', repr(line))
+        sys.audit("poplib.POP3.putline", self, line)
         self.sock.sendall(line + CRLF)
 
 
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 6486cd6e5d28..ab1a7d61897a 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -530,6 +530,7 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
     function that supports the same signature (like copy()) can be used.
 
     """
+    sys.audit("shutil.copytree", src, dst)
     with os.scandir(src) as entries:
         return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
                          ignore=ignore, copy_function=copy_function,
@@ -640,6 +641,7 @@ def rmtree(path, ignore_errors=False, onerror=None):
     is false and onerror is None, an exception is raised.
 
     """
+    sys.audit("shutil.rmtree", path)
     if ignore_errors:
         def onerror(*args):
             pass
@@ -965,6 +967,7 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
     'owner' and 'group' are used when creating a tar archive. By default,
     uses the current owner and group.
     """
+    sys.audit("shutil.make_archive", base_name, format, root_dir, base_dir)
     save_cwd = os.getcwd()
     if root_dir is not None:
         if logger is not None:
diff --git a/Lib/smtplib.py b/Lib/smtplib.py
index 3c5ac75ab8ab..01f3d4386f58 100755
--- a/Lib/smtplib.py
+++ b/Lib/smtplib.py
@@ -335,6 +335,7 @@ def connect(self, host='localhost', port=0, source_address=None):
             port = self.default_port
         if self.debuglevel > 0:
             self._print_debug('connect:', (host, port))
+        sys.audit("smtplib.SMTP.connect", self, host, port)
         self.sock = self._get_socket(host, port, self.timeout)
         self.file = None
         (code, msg) = self.getreply()
@@ -352,6 +353,7 @@ def send(self, s):
                 # should not be used, but 'data' needs to convert the string to
                 # binary itself anyway, so that's not a problem.
                 s = s.encode(self.command_encoding)
+            sys.audit("smtplib.SMTP.send", self, s)
             try:
                 self.sock.sendall(s)
             except OSError:
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index d34c57828b48..c0bda96cbc03 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1268,6 +1268,11 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
                 comspec = os.environ.get("COMSPEC", "cmd.exe")
                 args = '{} /c "{}"'.format (comspec, args)
 
+            if cwd is not None:
+                cwd = os.fsdecode(cwd)
+
+            sys.audit("subprocess.Popen", executable, args, cwd, env)
+
             # Start the process
             try:
                 hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
@@ -1276,7 +1281,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
                                          int(not close_fds),
                                          creationflags,
                                          env,
-                                         os.fsdecode(cwd) if cwd is not None else None,
+                                         cwd,
                                          startupinfo)
             finally:
                 # Child is launched. Close the parent's copy of those pipe
@@ -1543,6 +1548,8 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
             if executable is None:
                 executable = args[0]
 
+            sys.audit("subprocess.Popen", executable, args, cwd, env)
+
             if (_USE_POSIX_SPAWN
                     and os.path.dirname(executable)
                     and preexec_fn is None
diff --git a/Lib/telnetlib.py b/Lib/telnetlib.py
index b9d45b48e79f..8ce053e881a3 100644
--- a/Lib/telnetlib.py
+++ b/Lib/telnetlib.py
@@ -231,6 +231,7 @@ def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
         self.host = host
         self.port = port
         self.timeout = timeout
+        sys.audit("telnetlib.Telnet.open", self, host, port)
         self.sock = socket.create_connection((host, port), timeout)
 
     def __del__(self):
@@ -286,6 +287,7 @@ def write(self, buffer):
         """
         if IAC in buffer:
             buffer = buffer.replace(IAC, IAC+IAC)
+        sys.audit("telnetlib.Telnet.write", self, buffer)
         self.msg("send %r", buffer)
         self.sock.sendall(buffer)
 
diff --git a/Lib/tempfile.py b/Lib/tempfile.py
index e8b111eae223..45709cb06cf4 100644
--- a/Lib/tempfile.py
+++ b/Lib/tempfile.py
@@ -43,6 +43,7 @@
 import shutil as _shutil
 import errno as _errno
 from random import Random as _Random
+import sys as _sys
 import weakref as _weakref
 import _thread
 _allocate_lock = _thread.allocate_lock
@@ -244,6 +245,7 @@ def _mkstemp_inner(dir, pre, suf, flags, output_type):
     for seq in range(TMP_MAX):
         name = next(names)
         file = _os.path.join(dir, pre + name + suf)
+        _sys.audit("tempfile.mkstemp", file)
         try:
             fd = _os.open(file, flags, 0o600)
         except FileExistsError:
@@ -352,6 +354,7 @@ def mkdtemp(suffix=None, prefix=None, dir=None):
     for seq in range(TMP_MAX):
         name = next(names)
         file = _os.path.join(dir, prefix + name + suffix)
+        _sys.audit("tempfile.mkdtemp", file)
         try:
             _os.mkdir(file, 0o700)
         except FileExistsError:
@@ -546,7 +549,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
         _os.close(fd)
         raise
 
-if _os.name != 'posix' or _os.sys.platform == 'cygwin':
+if _os.name != 'posix' or _sys.platform == 'cygwin':
     # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
     # while it is open.
     TemporaryFile = NamedTemporaryFile
diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py
index 82bff835fdd0..0af36c4301d7 100755
--- a/Lib/webbrowser.py
+++ b/Lib/webbrowser.py
@@ -154,6 +154,7 @@ def __init__(self, name):
         self.basename = os.path.basename(self.name)
 
     def open(self, url, new=0, autoraise=True):
+        sys.audit("webbrowser.open", url)
         cmdline = [self.name] + [arg.replace("%s", url)
                                  for arg in self.args]
         try:
@@ -173,6 +174,7 @@ class BackgroundBrowser(GenericBrowser):
     def open(self, url, new=0, autoraise=True):
         cmdline = [self.name] + [arg.replace("%s", url)
                                  for arg in self.args]
+        sys.audit("webbrowser.open", url)
         try:
             if sys.platform[:3] == 'win':
                 p = subprocess.Popen(cmdline)
@@ -201,7 +203,7 @@ class UnixBrowser(BaseBrowser):
     remote_action_newwin = None
     remote_action_newtab = None
 
-    def _invoke(self, args, remote, autoraise):
+    def _invoke(self, args, remote, autoraise, url=None):
         raise_opt = []
         if remote and self.raise_opts:
             # use autoraise argument only for remote invocation
@@ -237,6 +239,7 @@ def _invoke(self, args, remote, autoraise):
             return not p.wait()
 
     def open(self, url, new=0, autoraise=True):
+        sys.audit("webbrowser.open", url)
         if new == 0:
             action = self.remote_action
         elif new == 1:
@@ -253,7 +256,7 @@ def open(self, url, new=0, autoraise=True):
         args = [arg.replace("%s", url).replace("%action", action)
                 for arg in self.remote_args]
         args = [arg for arg in args if arg]
-        success = self._invoke(args, True, autoraise)
+        success = self._invoke(args, True, autoraise, url)
         if not success:
             # remote invocation failed, try straight way
             args = [arg.replace("%s", url) for arg in self.args]
@@ -337,6 +340,7 @@ class Konqueror(BaseBrowser):
     """
 
     def open(self, url, new=0, autoraise=True):
+        sys.audit("webbrowser.open", url)
         # XXX Currently I know no way to prevent KFM from opening a new win.
         if new == 2:
             action = "newTab"
@@ -420,6 +424,7 @@ def _remote(self, action):
         return 1
 
     def open(self, url, new=0, autoraise=True):
+        sys.audit("webbrowser.open", url)
         if new:
             ok = self._remote("LOADNEW " + url)
         else:
@@ -577,6 +582,7 @@ def register_standard_browsers():
 if sys.platform[:3] == "win":
     class WindowsDefault(BaseBrowser):
         def open(self, url, new=0, autoraise=True):
+            sys.audit("webbrowser.open", url)
             try:
                 os.startfile(url)
             except OSError:
@@ -606,6 +612,7 @@ def __init__(self, name):
             self.name = name
 
         def open(self, url, new=0, autoraise=True):
+            sys.audit("webbrowser.open", url)
             assert "'" not in url
             # hack for local urls
             if not ':' in url:
diff --git a/Misc/NEWS.d/next/Security/2019-06-21-15-58-59.bpo-37363.diouyl.rst b/Misc/NEWS.d/next/Security/2019-06-21-15-58-59.bpo-37363.diouyl.rst
new file mode 100644
index 000000000000..1b724ff559e2
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2019-06-21-15-58-59.bpo-37363.diouyl.rst
@@ -0,0 +1,5 @@
+Adds audit events for :mod:`ensurepip`, :mod:`ftplib`, :mod:`glob`,
+:mod:`imaplib`, :mod:`nntplib`, :mod:`pdb`, :mod:`poplib`, :mod:`shutil`,
+:mod:`smtplib`, :mod:`sqlite3`, :mod:`subprocess`, :mod:`telnetlib`,
+:mod:`tempfile` and :mod:`webbrowser`, as well as :func:`os.listdir`,
+:func:`os.scandir` and :func:`breakpoint`.
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
index c487ba98908b..9fe0dc952f0b 100644
--- a/Modules/_sqlite/module.c
+++ b/Modules/_sqlite/module.c
@@ -85,6 +85,10 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
         factory = (PyObject*)&pysqlite_ConnectionType;
     }
 
+    if (PySys_Audit("sqlite3.connect", "O", database) < 0) {
+        return NULL;
+    }
+
     result = PyObject_Call(factory, args, kwargs);
 
     return result;
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 7a471801db39..c68bab81c782 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -3758,6 +3758,10 @@ static PyObject *
 os_listdir_impl(PyObject *module, path_t *path)
 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
 {
+    if (PySys_Audit("os.listdir", "O",
+                    path->object ? path->object : Py_None) < 0) {
+        return NULL;
+    }
 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
     return _listdir_windows_no_opendir(path, NULL);
 #else
@@ -13163,6 +13167,11 @@ os_scandir_impl(PyObject *module, path_t *path)
 #endif
 #endif
 
+    if (PySys_Audit("os.scandir", "O",
+                    path->object ? path->object : Py_None) < 0) {
+        return NULL;
+    }
+
     iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
     if (!iterator)
         return NULL;
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index c3e30593475d..82ae7116841b 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -482,6 +482,11 @@ builtin_breakpoint(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyOb
         PyErr_SetString(PyExc_RuntimeError, "lost sys.breakpointhook");
         return NULL;
     }
+
+    if (PySys_Audit("builtins.breakpoint", "O", hook) < 0) {
+        return NULL;
+    }
+
     Py_INCREF(hook);
     PyObject *retval = _PyObject_Vectorcall(hook, args, nargs, keywords);
     Py_DECREF(hook);



More information about the Python-checkins mailing list