Merge pull request #8894 from ThomasWaldmann/bandit

use bandit
This commit is contained in:
TW 2025-06-03 09:07:35 +02:00 committed by GitHub
commit 0fa548beac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 59 additions and 20 deletions

View file

@ -40,9 +40,28 @@ jobs:
- uses: actions/checkout@v4
- uses: chartboost/ruff-action@v1
security:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install bandit[toml]
- name: Run Bandit
run: |
bandit -r src/borg -c pyproject.toml
linux:
needs: lint
needs: [lint, security]
strategy:
fail-fast: true
matrix:

View file

@ -159,7 +159,7 @@ ignore_missing_imports = true
[tool.tox]
requires = ["tox>=4.19", "pkgconfig", "cython", "wheel", "setuptools_scm"]
env_list = ["py{310,311,312,313}-{none,fuse2,fuse3}", "docs", "ruff", "mypy"]
env_list = ["py{310,311,312,313}-{none,fuse2,fuse3}", "docs", "ruff", "mypy", "bandit"]
[tool.tox.env_run_base]
package = "editable-legacy" # without this it does not find setup_docs when running under fakeroot
@ -195,3 +195,15 @@ commands = [["mypy", "--ignore-missing-imports"]]
change_dir = "docs"
deps = ["sphinx", "sphinxcontrib-jquery", "guzzle_sphinx_theme"]
commands = [["sphinx-build", "-n", "-v", "-W", "--keep-going", "-b", "html", "-d", "{envtmpdir}/doctrees", ".", "{envtmpdir}/html"]]
[tool.bandit]
exclude_dirs = [".cache", ".eggs", ".git", ".git-rewrite", ".idea", ".mypy_cache", ".ruff_cache", ".tox", "build", "dist", "src/borg/testsuite"]
skips = [
"B101", # skip assert warnings, we do not allow running borg with assertions disabled.
"B404", # do not warn about just import subprocess
]
[tool.tox.env.bandit]
skip_install = true
deps = ["bandit[toml]"]
commands = [["bandit", "-r", "src/borg", "-c", "pyproject.toml"]]

View file

@ -12,3 +12,4 @@ pytest-cov
pytest-benchmark
Cython
pre-commit
bandit[toml]

View file

@ -73,7 +73,7 @@ class CreateMixIn:
try:
try:
env = prepare_subprocess_env(system=True)
proc = subprocess.Popen(
proc = subprocess.Popen( # nosec B603
args.paths,
stdout=subprocess.PIPE,
env=env,
@ -97,7 +97,7 @@ class CreateMixIn:
if args.paths_from_command:
try:
env = prepare_subprocess_env(system=True)
proc = subprocess.Popen(
proc = subprocess.Popen( # nosec B603
args.paths, stdout=subprocess.PIPE, env=env, preexec_fn=None if is_win32 else ignore_sigint
)
except (FileNotFoundError, PermissionError) as e:

View file

@ -22,7 +22,7 @@ class LocksMixIn:
env = prepare_subprocess_env(system=True)
try:
# we exit with the return code we get from the subprocess
rc = subprocess.call([args.command] + args.args, env=env)
rc = subprocess.call([args.command] + args.args, env=env) # nosec B603
set_ec(rc)
except (FileNotFoundError, OSError, ValueError) as e:
raise CommandError(f"Error while trying to run '{args.command}': {e}")

View file

@ -57,7 +57,7 @@ def pytest_report_header(config, start_path):
def set_env_variables():
os.environ["BORG_CHECK_I_KNOW_WHAT_I_AM_DOING"] = "YES"
os.environ["BORG_DELETE_I_KNOW_WHAT_I_AM_DOING"] = "YES"
os.environ["BORG_PASSPHRASE"] = "waytooeasyonlyfortests"
os.environ["BORG_PASSPHRASE"] = "waytooeasyonlyfortests" # nosec B105
os.environ["BORG_SELFTEST"] = "disabled"
@ -103,7 +103,8 @@ def archiver(tmp_path, set_env_variables):
os.environ["BORG_KEYS_DIR"] = archiver.keys_path
os.environ["BORG_CACHE_DIR"] = archiver.cache_path
os.mkdir(archiver.input_path)
os.chmod(archiver.input_path, 0o777) # avoid troubles with fakeroot / FUSE
# avoid troubles with fakeroot / FUSE:
os.chmod(archiver.input_path, 0o777) # nosec B103
os.mkdir(archiver.output_path)
os.mkdir(archiver.keys_path)
os.mkdir(archiver.cache_path)

View file

@ -658,7 +658,7 @@ class FlexiKey:
elif self.STORAGE == KeyBlobStorage.REPO:
# While the repository is encrypted, we consider a repokey repository with a blank
# passphrase an unencrypted repository.
self.logically_encrypted = passphrase != ""
self.logically_encrypted = passphrase != "" # nosec B105
# what we get in target is just a repo location, but we already have the repo obj:
target = self.repository
@ -688,7 +688,7 @@ class FlexiKey:
fd.write(key_data)
fd.write("\n")
elif self.STORAGE == KeyBlobStorage.REPO:
self.logically_encrypted = passphrase != ""
self.logically_encrypted = passphrase != "" # nosec B105
key_data = key_data.encode("utf-8") # remote repo: msgpack issue #99, giving bytes
target.save_key(key_data)
else:

View file

@ -169,11 +169,11 @@ class ExclusiveLock:
# should be cleaned up anyway. Try to clean up, but don't crash.
try:
os.unlink(temp_unique_name)
except: # noqa
except: # nosec B110 # noqa
pass
try:
os.rmdir(temp_path)
except: # noqa
except: # nosec B110 # noqa
pass
def release(self):

View file

@ -558,9 +558,9 @@ def umount(mountpoint):
env = prepare_subprocess_env(system=True)
try:
rc = subprocess.call(["fusermount", "-u", mountpoint], env=env)
rc = subprocess.call(["fusermount", "-u", mountpoint], env=env) # nosec B603, B607
except FileNotFoundError:
rc = subprocess.call(["umount", mountpoint], env=env)
rc = subprocess.call(["umount", mountpoint], env=env) # nosec B603, B607
set_ec(rc)

View file

@ -67,7 +67,7 @@ class Passphrase(str):
# passcommand is a system command (not inside pyinstaller env)
env = prepare_subprocess_env(system=True)
try:
passphrase = subprocess.check_output(shlex.split(passcommand), text=True, env=env)
passphrase = subprocess.check_output(shlex.split(passcommand), text=True, env=env) # nosec B603
except (subprocess.CalledProcessError, FileNotFoundError) as e:
raise PasscommandFailure(e)
return cls(passphrase.rstrip("\n"))

View file

@ -286,7 +286,7 @@ def popen_with_error_handling(cmd_line: str, log_prefix="", **kwargs):
return
logger.debug("%scommand line: %s", log_prefix, command)
try:
return subprocess.Popen(command, **kwargs)
return subprocess.Popen(command, **kwargs) # nosec B603
except FileNotFoundError:
logger.error("%sexecutable not found: %s", log_prefix, command[0])
return

View file

@ -275,7 +275,9 @@ class LegacyRemoteRepository:
borg_cmd = self.ssh_cmd(location) + borg_cmd
logger.debug("SSH command line: %s", borg_cmd)
# we do not want the ssh getting killed by Ctrl-C/SIGINT because it is needed for clean shutdown of borg.
self.p = Popen(borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env, preexec_fn=ignore_sigint)
self.p = Popen(
borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env, preexec_fn=ignore_sigint
) # nosec B603
self.stdin_fd = self.p.stdin.fileno()
self.stdout_fd = self.p.stdout.fileno()
self.stderr_fd = self.p.stderr.fileno()

View file

@ -269,7 +269,7 @@ def getfqdn(name=""):
An empty argument is interpreted as meaning the local host.
"""
name = name.strip()
if not name or name == "0.0.0.0":
if not name or name == "0.0.0.0": # nosec B104:hardcoded_bind_all_interfaces
name = socket.gethostname()
try:
addrs = socket.getaddrinfo(name, None, 0, socket.SOCK_DGRAM, 0, socket.AI_CANONNAME)

View file

@ -576,7 +576,9 @@ class RemoteRepository:
borg_cmd = self.ssh_cmd(location) + borg_cmd
logger.debug("SSH command line: %s", borg_cmd)
# we do not want the ssh getting killed by Ctrl-C/SIGINT because it is needed for clean shutdown of borg.
self.p = Popen(borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env, preexec_fn=ignore_sigint)
self.p = Popen(
borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env, preexec_fn=ignore_sigint
) # nosec B603
self.stdin_fd = self.p.stdin.fileno()
self.stdout_fd = self.p.stdout.fileno()
self.stderr_fd = self.p.stderr.fileno()

View file

@ -201,7 +201,9 @@ class Lock:
logger.debug("LOCK-ACQUIRE: exclusive locks detected, deleting our shared lock.")
self._delete_lock(key, ignore_not_found=True, update_last_refresh=True)
# wait a random bit before retrying
time.sleep(self.retry_delay_min + (self.retry_delay_max - self.retry_delay_min) * random.random())
time.sleep(
self.retry_delay_min + (self.retry_delay_max - self.retry_delay_min) * random.random() # nosec B311
)
logger.debug("LOCK-ACQUIRE: timeout while trying to acquire a lock.")
raise LockTimeout(str(self.store))

View file

@ -28,7 +28,7 @@ if sys.platform.startswith("linux"):
for preload in preloads:
if preload.startswith("libfakeroot"):
env = prepare_subprocess_env(system=True)
fakeroot_output = subprocess.check_output(["fakeroot", "-v"], env=env)
fakeroot_output = subprocess.check_output(["fakeroot", "-v"], env=env) # nosec B603, B607
fakeroot_version = parse_version(fakeroot_output.decode("ascii").split()[-1])
if fakeroot_version >= parse_version("1.20.2"):
# 1.20.2 has been confirmed to have xattr support