The following issues were found
certbot/certbot/achallenges.py
6 issues
Line: 23
Column: 1
import logging
from typing import Type
import josepy as jose
from acme import challenges
from acme.challenges import Challenge
logger = logging.getLogger(__name__)
Reported by Pylint.
Line: 25
Column: 1
import josepy as jose
from acme import challenges
from acme.challenges import Challenge
logger = logging.getLogger(__name__)
Reported by Pylint.
Line: 26
Column: 1
import josepy as jose
from acme import challenges
from acme.challenges import Challenge
logger = logging.getLogger(__name__)
class AnnotatedChallenge(jose.ImmutableMap):
Reported by Pylint.
Line: 31
Column: 1
logger = logging.getLogger(__name__)
class AnnotatedChallenge(jose.ImmutableMap):
"""Client annotated challenge.
Wraps around server provided challenge and annotates with data
useful for the client.
Reported by Pylint.
Line: 47
Column: 1
return getattr(self.challb, name)
class KeyAuthorizationAnnotatedChallenge(AnnotatedChallenge):
"""Client annotated `KeyAuthorizationChallenge` challenge."""
__slots__ = ('challb', 'domain', 'account_key')
def response_and_validation(self, *args, **kwargs):
"""Generate response and validation."""
Reported by Pylint.
Line: 57
Column: 1
self.account_key, *args, **kwargs)
class DNS(AnnotatedChallenge):
"""Client annotated "dns" ACME challenge."""
__slots__ = ('challb', 'domain')
acme_type = challenges.DNS
Reported by Pylint.
certbot/certbot/plugins/storage.py
6 issues
Line: 67
Column: 17
errmsg = "PluginStorage file {0} is corrupted.".format(
self._storagepath)
logger.error(errmsg)
raise errors.PluginStorageError(errmsg)
self._data = data
def save(self):
"""Saves PluginStorage content to disk
Reported by Pylint.
Line: 48
Column: 50
data: Dict[str, Any] = {}
filedata = ""
try:
with open(self._storagepath, 'r') as fh:
filedata = fh.read()
except IOError as e:
errmsg = "Could not read PluginStorage data file: {0} : {1}".format(
self._storagepath, str(e))
if os.path.isfile(self._storagepath):
Reported by Pylint.
Line: 50
Column: 9
try:
with open(self._storagepath, 'r') as fh:
filedata = fh.read()
except IOError as e:
errmsg = "Could not read PluginStorage data file: {0} : {1}".format(
self._storagepath, str(e))
if os.path.isfile(self._storagepath):
# Only error out if file exists, but cannot be read
logger.error(errmsg)
Reported by Pylint.
Line: 83
Column: 9
try:
serialized = json.dumps(self._data)
except TypeError as e:
errmsg = "Could not serialize PluginStorage data: {0}".format(
str(e))
logger.error(errmsg)
raise errors.PluginStorageError(errmsg)
try:
Reported by Pylint.
Line: 92
Column: 37
with os.fdopen(filesystem.open(
self._storagepath,
os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
0o600), 'w') as fh:
fh.write(serialized)
except IOError as e:
errmsg = "Could not write PluginStorage data to file {0} : {1}".format(
self._storagepath, str(e))
logger.error(errmsg)
Reported by Pylint.
Line: 94
Column: 9
os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
0o600), 'w') as fh:
fh.write(serialized)
except IOError as e:
errmsg = "Could not write PluginStorage data to file {0} : {1}".format(
self._storagepath, str(e))
logger.error(errmsg)
raise errors.PluginStorageError(errmsg)
Reported by Pylint.
certbot-compatibility-test/certbot_compatibility_test/validator.py
6 issues
Line: 7
Column: 1
import requests
from acme import crypto_util
from acme import errors as acme_errors
logger = logging.getLogger(__name__)
Reported by Pylint.
Line: 8
Column: 1
import requests
from acme import crypto_util
from acme import errors as acme_errors
logger = logging.getLogger(__name__)
class Validator:
Reported by Pylint.
Line: 16
Column: 5
class Validator:
"""Collection of functions to test a live webserver's configuration"""
def certificate(self, cert, name, alt_host=None, port=443):
"""Verifies the certificate presented at name is cert"""
if alt_host is None:
host = socket.gethostbyname(name).encode()
elif isinstance(alt_host, bytes):
host = alt_host
Reported by Pylint.
Line: 34
Column: 5
return presented_cert.digest("sha256") == cert.digest("sha256")
def redirect(self, name, port=80, headers=None):
"""Test whether webserver redirects to secure connection."""
url = "http://{0}:{1}".format(name, port)
if headers:
response = requests.get(url, headers=headers, allow_redirects=False)
else:
Reported by Pylint.
Line: 55
Column: 5
return True
def any_redirect(self, name, port=80, headers=None):
"""Test whether webserver redirects."""
url = "http://{0}:{1}".format(name, port)
if headers:
response = requests.get(url, headers=headers, allow_redirects=False)
else:
Reported by Pylint.
Line: 65
Column: 5
return response.status_code in range(300, 309)
def hsts(self, name):
"""Test for HTTP Strict Transport Security header"""
headers = requests.get("https://" + name).headers
hsts_header = headers.get("strict-transport-security")
if not hsts_header:
Reported by Pylint.
certbot-nginx/certbot_nginx/_internal/parser.py
6 issues
Line: 17
Column: 1
import pyparsing
from certbot import errors
from certbot.compat import os
from certbot_nginx._internal import nginxparser
from certbot_nginx._internal import obj
from certbot_nginx._internal.nginxparser import UnspacedList
Reported by Pylint.
Line: 18
Column: 1
import pyparsing
from certbot import errors
from certbot.compat import os
from certbot_nginx._internal import nginxparser
from certbot_nginx._internal import obj
from certbot_nginx._internal.nginxparser import UnspacedList
logger = logging.getLogger(__name__)
Reported by Pylint.
Line: 41
Column: 3
self.config_root = self._find_config_root()
# Parse nginx.conf and included files.
# TODO: Check sites-available/ as well. For now, the configurator does
# not enable sites from there.
self.load()
def load(self):
"""Loads Nginx files into a parsed tree.
Reported by Pylint.
Line: 201
Column: 3
"""
files = glob.glob(filepath) # nginx on unix calls glob(3) for this
# XXX Windows nginx uses FindFirstFile, and
# should have a narrower call here
trees = []
for item in files:
if item in self.parsed and not override:
continue
Reported by Pylint.
Line: 380
Column: 3
:returns: A vhost object for the newly created vhost
:rtype: :class:`~certbot_nginx._internal.obj.VirtualHost`
"""
# TODO: https://github.com/certbot/certbot/issues/5185
# put it in the same file as the template, at the same level
new_vhost = copy.deepcopy(vhost_template)
enclosing_block = self.parsed[vhost_template.filep]
for index in vhost_template.path[:-1]:
Reported by Pylint.
Line: 269
Column: 5
_apply_global_addr_ssl(addr_to_ssl, parsed_server)
return parsed_server
def has_ssl_on_directive(self, vhost):
"""Does vhost have ssl on for all ports?
:param :class:`~certbot_nginx._internal.obj.VirtualHost` vhost: The vhost in question
:returns: True if 'ssl on' directive is included
Reported by Pylint.
certbot/certbot/_internal/log.py
6 issues
Line: 34
Column: 1
from types import TracebackType
from typing import IO
from acme import messages
from certbot import errors
from certbot import util
from certbot._internal import constants
from certbot.compat import os
Reported by Pylint.
Line: 151
Column: 3
:rtype: tuple
"""
# TODO: logs might contain sensitive data such as contents of the
# private key! #525
util.set_up_core_dir(config.logs_dir, 0o700, config.strict_permissions)
log_file_path = os.path.join(config.logs_dir, logfile)
try:
handler = logging.handlers.RotatingFileHandler(
Reported by Pylint.
Line: 164
Column: 3
# rotate on each invocation, rollover only possible when maxBytes
# is nonzero and backupCount is nonzero, so we set maxBytes as big
# as possible not to overrun in single CLI invocation (1MB).
handler.doRollover() # TODO: creates empty letsencrypt.log.1 file
handler.setLevel(logging.DEBUG)
handler_formatter = logging.Formatter(fmt=fmt)
handler.setFormatter(handler_formatter)
return handler, log_file_path
Reported by Pylint.
Line: 111
Suggestion:
https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html
elif isinstance(handler, MemoryHandler):
memory_handler = handler
msg = 'Previously configured logging handlers have been removed!'
assert memory_handler is not None and stderr_handler is not None, msg
root_logger.addHandler(file_handler)
root_logger.removeHandler(memory_handler)
temp_handler = getattr(memory_handler, 'target', None)
memory_handler.setTarget(file_handler) # pylint: disable=no-member
Reported by Bandit.
Line: 322
Column: 1
memory_handler.flush(force=True)
def post_arg_parse_except_hook(exc_type: type, exc_value: BaseException, trace: TracebackType,
debug: bool, quiet: bool, log_path: str):
"""Logs fatal exceptions and reports them to the user.
If debug is True, the full exception and traceback is shown to the
user, otherwise, it is suppressed. sys.exit is always called with a
Reported by Pylint.
Line: 345
Suggestion:
https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html
# display message the user, otherwise, a lower level like
# logger.DEBUG should be used
if debug or not issubclass(exc_type, Exception):
assert constants.QUIET_LOGGING_LEVEL <= logging.ERROR
if exc_type is KeyboardInterrupt:
logger.error('Exiting due to user request.')
sys.exit(1)
logger.error('Exiting abnormally:', exc_info=exc_info)
else:
Reported by Bandit.
certbot-apache/certbot_apache/_internal/augeasparser.py
5 issues
Line: 69
Column: 1
"""
from typing import Set
from certbot import errors
from certbot.compat import os
from certbot_apache._internal import apache_util
from certbot_apache._internal import assertions
from certbot_apache._internal import interfaces
from certbot_apache._internal import parser
Reported by Pylint.
Line: 70
Column: 1
from typing import Set
from certbot import errors
from certbot.compat import os
from certbot_apache._internal import apache_util
from certbot_apache._internal import assertions
from certbot_apache._internal import interfaces
from certbot_apache._internal import parser
from certbot_apache._internal import parsernode_util as util
Reported by Pylint.
Line: 97
Column: 13
)
)
except KeyError:
raise errors.PluginError("Augeas path is required")
def save(self, msg):
self.parser.save(msg)
def find_ancestors(self, name):
Reported by Pylint.
Line: 149
Column: 5
filepath=apache_util.get_file_path(path),
metadata=metadata)
def _aug_get_name(self, path):
"""
Helper function to get name of a configuration block or variable from path.
"""
# Remove the ending slash if any
Reported by Pylint.
Line: 222
Column: 13
param_path = "{}/arg[1]".format(self.metadata["augeaspath"])
self.parser.aug.remove(param_path)
# Insert new ones
for pi, param in enumerate(parameters):
param_path = "{}/arg[{}]".format(self.metadata["augeaspath"], pi+1)
self.parser.aug.set(param_path, param)
@property
def parameters(self):
Reported by Pylint.
certbot/certbot/plugins/dns_common.py
5 issues
Line: 9
Column: 1
import configobj
from acme import challenges
from certbot import errors
from certbot import interfaces
from certbot.compat import filesystem
from certbot.compat import os
from certbot.display import ops
Reported by Pylint.
Line: 170
Column: 1
indicate any issue.
"""
def __validator(filename): # pylint: disable=unused-private-member
configuration = CredentialsConfiguration(filename, self.dest)
if required_variables:
configuration.require(required_variables)
Reported by Pylint.
Line: 200
Column: 1
:rtype: str
"""
def __validator(i): # pylint: disable=unused-private-member
if not i:
raise errors.PluginError('Please enter your {0}.'.format(label))
code, response = ops.validated_input(
__validator,
Reported by Pylint.
Line: 226
Column: 1
:rtype: str
"""
def __validator(filename): # pylint: disable=unused-private-member
if not filename:
raise errors.PluginError('Please enter a valid path to your {0}.'.format(label))
filename = os.path.expanduser(filename)
Reported by Pylint.
Line: 260
Column: 9
try:
self.confobj = configobj.ConfigObj(filename)
except configobj.ConfigObjError as e:
logger.debug("Error parsing credentials configuration: %s", e, exc_info=True)
raise errors.PluginError("Error parsing credentials configuration: {0}".format(e))
self.mapper = mapper
Reported by Pylint.
acme/acme/standalone.py
5 issues
Line: 52
Column: 3
class ACMEServerMixin:
"""ACME server common settings mixin."""
# TODO: c.f. #858
server_version = "ACME client standalone challenge solver"
allow_reuse_address = True
class BaseDualNetworkedServers:
Reported by Pylint.
Line: 149
Column: 3
self.challenge_certs = challenge_certs
def _cert_selection(self, connection):
# TODO: We would like to serve challenge cert only if asked for it via
# ALPN. To do this, we need to retrieve the list of protos from client
# hello, but this is currently impossible with openssl [0], and ALPN
# negotiation is done after cert selection.
# Therefore, currently we always return challenge cert, and terminate
# handshake in alpn_selection() if ALPN protos are not what we expect.
Reported by Pylint.
Line: 50
Column: 1
return socketserver.TCPServer.server_bind(self)
class ACMEServerMixin:
"""ACME server common settings mixin."""
# TODO: c.f. #858
server_version = "ACME client standalone challenge solver"
allow_reuse_address = True
Reported by Pylint.
Line: 89
Column: 13
logger.debug(
"Successfully bound to %s:%s using %s", new_address[0],
new_address[1], "IPv6" if ip_version else "IPv4")
except socket.error as e:
last_socket_err = e
if self.servers:
# Already bound using IPv6.
logger.debug(
"Certbot wasn't able to bind to %s:%s using %s, this "
Reported by Pylint.
Line: 109
Column: 13
# bind to the same port for both servers.
port = server.socket.getsockname()[1]
if not self.servers:
if last_socket_err:
raise last_socket_err
else: # pragma: no cover
raise socket.error("Could not bind to IPv4 or IPv6.")
def serve_forever(self):
Reported by Pylint.
tools/install_and_test.py
5 issues
Line: 15
Suggestion:
https://bandit.readthedocs.io/en/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html
def call_with_print(command):
print(command)
subprocess.check_call(command, shell=True)
def main(args):
script_dir = os.path.dirname(os.path.abspath(__file__))
command = [sys.executable, os.path.join(script_dir, 'pip_install_editable.py')]
Reported by Bandit.
Line: 1
Column: 1
#!/usr/bin/env python
# pip installs the requested packages in editable mode and runs unit tests on
# them. Each package is installed and tested in the order they are provided
# before the script moves on to the next package. If CERTBOT_NO_PIN is set not
# set to 1, packages are installed using pinned versions of all of our
# dependencies. See pip_install.py for more information on the versions pinned
# to.
import os
import re
Reported by Pylint.
Line: 10
Suggestion:
https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html#b404-import-subprocess
# to.
import os
import re
import subprocess
import sys
def call_with_print(command):
print(command)
subprocess.check_call(command, shell=True)
Reported by Bandit.
Line: 13
Column: 1
import subprocess
import sys
def call_with_print(command):
print(command)
subprocess.check_call(command, shell=True)
def main(args):
Reported by Pylint.
Line: 18
Column: 1
subprocess.check_call(command, shell=True)
def main(args):
script_dir = os.path.dirname(os.path.abspath(__file__))
command = [sys.executable, os.path.join(script_dir, 'pip_install_editable.py')]
for requirement in args:
current_command = command[:]
Reported by Pylint.
certbot/certbot/_internal/plugins/selection.py
5 issues
Line: 109
Column: 5
verified.prepare()
prepared = verified.available()
if len(prepared) > 1:
logger.debug("Multiple candidate plugins: %s", prepared)
plugin_ep = choose_plugin(list(prepared.values()), question)
if plugin_ep is None:
return None
return plugin_ep.init()
Reported by Pylint.
Line: 168
Column: 1
config.authenticator, config.installer)
def choose_configurator_plugins(config: configuration.NamespaceConfig,
plugins: disco.PluginsRegistry,
verb: str) -> Tuple[Optional[interfaces.Installer],
Optional[interfaces.Authenticator]]:
"""
Figure out which configurator we're going to use, modifies
Reported by Pylint.
Line: 193
Column: 9
# Which plugins do we need?
if verb == "run":
need_inst = need_auth = True
from certbot._internal.cli import cli_command
if req_auth in noninstaller_plugins and not req_inst:
msg = ('With the {0} plugin, you probably want to use the "certonly" command, eg:{1}'
'{1} {2} certonly --{0}{1}{1}'
'(Alternatively, add a --installer flag. See https://eff.org/letsencrypt-plugins'
'{1} and "--help plugins" for more information.)'.format(
Reported by Pylint.
Line: 250
Column: 1
return now
def cli_plugin_requests(config):
"""
Figure out which plugins the user requested with CLI and config options
:returns: (requested authenticator string or None, requested installer string or None)
:rtype: tuple
Reported by Pylint.
Line: 324
Column: 9
"your existing configuration.\nThe error was: {1!r}"
.format(requested, plugins[requested].problem))
elif cfg_type == "installer":
from certbot._internal.cli import cli_command
msg = ('Certbot doesn\'t know how to automatically configure the web '
'server on this system. However, it can still get a certificate for '
'you. Please run "{0} certonly" to do so. You\'ll need to '
'manually configure your web server to use the resulting '
'certificate.').format(cli_command)
Reported by Pylint.