summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-15 14:56:35 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-15 14:56:35 +0200
commit7fc2fa04d7d88a1cdf0d290ddd2de3815a7d52a5 (patch)
treec2ca93040bb95f5bcb667846a2fa91ddf0dd99bb /packages/meshbay-node
parent9dd6d1003cf92c0e4e7f23414565314691aa5516 (diff)
downloadmeshbay-7fc2fa04d7d88a1cdf0d290ddd2de3815a7d52a5.tar.gz
build: audit the shipped Python dependencies with pip-audit
No lock file pins the dependencies, so each build installs the newest releases and what ships is only known once it has. packaging/audit_deps.py runs pip-audit then: build-common.sh on the venv before stripping it, build-node-runtime.ps1 on the environment before PyInstaller freezes it. A known vulnerability stops the build, unless its id is listed in packaging/pip-audit-ignore.txt with why it does not apply. No network only skips the audit with a warning, as does a pip-audit that cannot be installed or writes no report. pip-audit runs from a venv of its own, never from the one that ships. Our packages are not audited (not on PyPI), nor pip, setuptools and wheel, which do not ship. Checked with the real build-common.sh (79 packages, none known), with PyJWT 2.14 (the build stops on its two advisories, and goes on once they are listed) and offline (a warning, the build goes on). The PowerShell step was not run here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node')
-rw-r--r--packages/meshbay-node/tests/test_packaging_audit.py64
1 files changed, 64 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_packaging_audit.py b/packages/meshbay-node/tests/test_packaging_audit.py
new file mode 100644
index 0000000..4409b01
--- /dev/null
+++ b/packages/meshbay-node/tests/test_packaging_audit.py
@@ -0,0 +1,64 @@
+"""
+packaging/audit_deps.py, the pip-audit step of the builds.
+
+What can be checked without the network: a build with no network goes on
+(the audit is skipped with a warning, never a failure), what is audited is
+what ships, and the ignore list is read as ids. Whether pip-audit stops a
+build on a real advisory needs the network and was checked by hand.
+"""
+
+import importlib.util
+import os
+import subprocess
+import sys
+from pathlib import Path
+
+import pytest
+
+ROOT = Path(__file__).resolve().parents[3]
+SCRIPT = ROOT / "packaging" / "audit_deps.py"
+
+pytestmark = pytest.mark.skipif(not SCRIPT.exists(), reason="packaging not present")
+
+
+def _module():
+ spec = importlib.util.spec_from_file_location("audit_deps", SCRIPT)
+ mod = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(mod)
+ return mod
+
+
+def test_no_network_skips_the_audit_without_failing_the_build(tmp_path):
+ # A proxy nobody listens on: every request is refused at once.
+ dead = "http://127.0.0.1:9"
+ env = {**os.environ, "HTTPS_PROXY": dead, "https_proxy": dead,
+ "HTTP_PROXY": dead, "http_proxy": dead}
+ run = subprocess.run([sys.executable, str(SCRIPT), "--tool-dir", str(tmp_path / "t")],
+ capture_output=True, text=True, env=env, timeout=60)
+ assert run.returncode == 0, run.stderr
+ assert "pip-audit skipped: no network" in run.stderr
+ assert not (tmp_path / "t").exists(), "nothing is installed when it cannot run"
+
+
+def test_what_is_audited_is_what_ships():
+ names = {line.split("==")[0].lower() for line in _module().shipped()}
+ assert "pytest" in names, "the environment's packages are listed"
+ assert not {n for n in names if n.startswith("meshbay")}, "ours are not on PyPI"
+ assert not names & {"pip", "setuptools", "wheel"}, "build tools do not ship"
+
+
+def test_the_ignore_list_is_read_as_ids(tmp_path, monkeypatch):
+ mod = _module()
+ f = tmp_path / "ignore.txt"
+ f.write_text("# a comment\n\nPYSEC-2026-1 # not reached: no JWK import\n"
+ "GHSA-xxxx-yyyy-zzzz\n", encoding="utf-8")
+ monkeypatch.setattr(mod, "IGNORE_FILE", f)
+ assert mod.ignored() == ["PYSEC-2026-1", "GHSA-xxxx-yyyy-zzzz"]
+
+
+def test_the_shipped_ignore_list_lets_nothing_through_unexplained():
+ """Every id in the real file carries its reason."""
+ mod = _module()
+ for line in mod.IGNORE_FILE.read_text(encoding="utf-8").splitlines():
+ if line.strip() and not line.lstrip().startswith("#"):
+ assert "#" in line, f"no reason given: {line!r}"