From 43d05ff5dfe6800553bc3ea35fd0ea2fb0d8d6e3 Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Tue, 21 Apr 2026 09:44:11 +0200 Subject: [PATCH 1/2] Add test to ensure tbx security cve works --- doc/changes/unreleased.md | 4 + test/integration/test_security_issues.py | 98 ++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 test/integration/test_security_issues.py diff --git a/doc/changes/unreleased.md b/doc/changes/unreleased.md index 6f88b33b79..610e9056c8 100644 --- a/doc/changes/unreleased.md +++ b/doc/changes/unreleased.md @@ -12,3 +12,7 @@ * #785: Removed nox session `project:report` and metrics-schema, as superseded by Sonar usage * #763: Parsed and manipulated Changes Files * #788: Removed tbx workflow CLI commands, as superseded by nox session `workflow:generate` + +## Bugfix + +* #798: Added test to ensure `tbx security cve` works diff --git a/test/integration/test_security_issues.py b/test/integration/test_security_issues.py new file mode 100644 index 0000000000..3a63f5279c --- /dev/null +++ b/test/integration/test_security_issues.py @@ -0,0 +1,98 @@ +import os +import shutil +import site +import subprocess +from pathlib import Path + +from noxconfig import PROJECT_CONFIG + + +def get_env(test_path: Path) -> dict[str, str]: + venv_bin = test_path / "venv" / "bin" + env = os.environ.copy() + env["VIRTUAL_ENV"] = str(test_path / "venv") + env["PATH"] = f"{venv_bin}{os.pathsep}{env['PATH']}" + env["PYTHONPATH"] = os.pathsep.join(site.getsitepackages()) + return env + + +def test_security_issues_works(tmp_path): + """ + To ensure that the `tbx security cve` CLI commands work for Java and + other non-Python projects, this test was created which: + - builds a wheel of the python-toolbox + - installs the wheel in a temporary directory + - executes `tbx security cve -- help` to ensure that no errors occur + + This issue primarily arises when one of the modules in `tools` imports something + from `noxconfig`, which is used in the Python projects using the toolbox, but it + is not needed nor used in the non-Python projects. + """ + build_output = subprocess.run(["poetry", "build", "--output", tmp_path]) + assert build_output.returncode == 0 + + venv_output = subprocess.run(["python", "-m", "venv", "venv"], cwd=tmp_path) + assert venv_output.returncode == 0 + + env = get_env(tmp_path) + wheel = min(tmp_path.glob("exasol_toolbox-*.whl")) + pip_output = subprocess.run( + ["pip", "install", "--no-deps", str(wheel)], cwd=tmp_path, env=env + ) + assert pip_output.returncode == 0 + + tbx_output = subprocess.run( + ["tbx", "security", "cve", "--help"], cwd=tmp_path, env=env + ) + assert tbx_output.returncode == 0 + + +def test_security_issues_fails_when_imports_noxconfig(tmp_path): + """ + Reproduces the failure mode where a toolbox runtime module imports + `noxconfig`, which is not available in non-Python projects. + """ + source_root = PROJECT_CONFIG.root_path + project_copy = tmp_path / "python-toolbox-copy" + shutil.copytree( + source_root, + project_copy, + ignore=shutil.ignore_patterns( + ".git", ".venv", "dist", "__pycache__", ".pytest_cache" + ), + ) + + security_py = project_copy / "exasol" / "toolbox" / "tools" / "security.py" + security_text = security_py.read_text() + security_py.write_text( + security_text.replace( + "from __future__ import annotations\n", + "from __future__ import annotations\n\nfrom noxconfig import PROJECT_CONFIG\n", + 1, + ) + ) + + build_output = subprocess.run( + ["poetry", "build", "--output", tmp_path], cwd=project_copy + ) + assert build_output.returncode == 0 + + venv_output = subprocess.run(["python", "-m", "venv", "venv"], cwd=tmp_path) + assert venv_output.returncode == 0 + + env = get_env(tmp_path) + wheel = min(tmp_path.glob("exasol_toolbox-*.whl")) + pip_output = subprocess.run( + ["pip", "install", "--no-deps", str(wheel)], cwd=tmp_path, env=env + ) + assert pip_output.returncode == 0 + + tbx_output = subprocess.run( + ["tbx", "security", "cve", "--help"], + cwd=tmp_path, + env=env, + capture_output=True, + text=True, + ) + assert tbx_output.returncode != 0 + assert "No module named 'noxconfig'" in tbx_output.stderr From 2b02b37f8ee71ad4e95cf4a8400d74a120bc7e45 Mon Sep 17 00:00:00 2001 From: Ariel Schulz Date: Tue, 21 Apr 2026 10:51:24 +0200 Subject: [PATCH 2/2] Rename file & switch to monkeypatch --- ...rity_issues.py => security_issues_test.py} | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) rename test/integration/{test_security_issues.py => security_issues_test.py} (82%) diff --git a/test/integration/test_security_issues.py b/test/integration/security_issues_test.py similarity index 82% rename from test/integration/test_security_issues.py rename to test/integration/security_issues_test.py index 3a63f5279c..a8438fde4d 100644 --- a/test/integration/test_security_issues.py +++ b/test/integration/security_issues_test.py @@ -7,16 +7,14 @@ from noxconfig import PROJECT_CONFIG -def get_env(test_path: Path) -> dict[str, str]: +def set_venv_env(monkeypatch, test_path: Path) -> None: venv_bin = test_path / "venv" / "bin" - env = os.environ.copy() - env["VIRTUAL_ENV"] = str(test_path / "venv") - env["PATH"] = f"{venv_bin}{os.pathsep}{env['PATH']}" - env["PYTHONPATH"] = os.pathsep.join(site.getsitepackages()) - return env + monkeypatch.setenv("VIRTUAL_ENV", str(test_path / "venv")) + monkeypatch.setenv("PATH", f"{venv_bin}{os.pathsep}{os.environ['PATH']}") + monkeypatch.setenv("PYTHONPATH", os.pathsep.join(site.getsitepackages())) -def test_security_issues_works(tmp_path): +def test_security_issues_works(tmp_path, monkeypatch): """ To ensure that the `tbx security cve` CLI commands work for Java and other non-Python projects, this test was created which: @@ -34,20 +32,18 @@ def test_security_issues_works(tmp_path): venv_output = subprocess.run(["python", "-m", "venv", "venv"], cwd=tmp_path) assert venv_output.returncode == 0 - env = get_env(tmp_path) + set_venv_env(monkeypatch, tmp_path) wheel = min(tmp_path.glob("exasol_toolbox-*.whl")) pip_output = subprocess.run( - ["pip", "install", "--no-deps", str(wheel)], cwd=tmp_path, env=env + ["pip", "install", "--no-deps", str(wheel)], cwd=tmp_path ) assert pip_output.returncode == 0 - tbx_output = subprocess.run( - ["tbx", "security", "cve", "--help"], cwd=tmp_path, env=env - ) + tbx_output = subprocess.run(["tbx", "security", "cve", "--help"], cwd=tmp_path) assert tbx_output.returncode == 0 -def test_security_issues_fails_when_imports_noxconfig(tmp_path): +def test_security_issues_fails_when_imports_noxconfig(tmp_path, monkeypatch): """ Reproduces the failure mode where a toolbox runtime module imports `noxconfig`, which is not available in non-Python projects. @@ -80,17 +76,16 @@ def test_security_issues_fails_when_imports_noxconfig(tmp_path): venv_output = subprocess.run(["python", "-m", "venv", "venv"], cwd=tmp_path) assert venv_output.returncode == 0 - env = get_env(tmp_path) + set_venv_env(monkeypatch, tmp_path) wheel = min(tmp_path.glob("exasol_toolbox-*.whl")) pip_output = subprocess.run( - ["pip", "install", "--no-deps", str(wheel)], cwd=tmp_path, env=env + ["pip", "install", "--no-deps", str(wheel)], cwd=tmp_path ) assert pip_output.returncode == 0 tbx_output = subprocess.run( ["tbx", "security", "cve", "--help"], cwd=tmp_path, - env=env, capture_output=True, text=True, )