T08 · Insecure Dependencies
- Location
setup.py:9- Finding
Automatic Installation of Unpinned Third-Party Dependencies
- Content
View full analysis
=1.14.0", "pandas>=2.0.0", "numpy>=1.24.0", "pyarrow>=12.0.0", "pyyaml>=6.0", "requests>=2.28.0", "python-dotenv>=1.0.0", ] missing = [] for dep in deps: name = dep.split(">=")[0].split("<")[0] try: __import__(name.replace("-", "_")) except ImportError: missing.append(dep) if not missing: print("All dependencies are installed.") return print(f"Installing: {' '.join(missing)}") cmd = [sys.executable, "-m", "pip", "install"] + missing try: subprocess.run(cmd, check=True) ``` ### Technical Analysis The documented `python setup.py` installation workflow launches pip and resolves mutable versions directly from the configured package index. The installer specifies only minimum versions and does not use an exact lock file, package hashes, or upper bounds. This creates a supply-chain trust boundary in which the code ultimately installed may differ from the code reviewed. A compromised future release, compromised package-index account, malicious transitive dependency, or unsafe private package-index configuration could introduce arbitrary code. The import checks also incorrectly derive import names from distribution names: - `pyyaml` is imported as `yaml`, not `pyyaml`. - `python-dotenv` is imported as `dotenv`, not `python_dotenv`. Consequently, these packages may be treated as missing even when already installed, unnecessarily invoking network-based dependency resolution. `requirements.txt` applies some upper bounds, but it still does not pin exact versions or hashes. Moreover, `setup.py` does not use those upper bounds, so the two installation mechanisms do not enforce equivalent dependency ...[truncated 1464 chars]- Remediation
View remediation
