From 31769047675be9cf83aa67abefb85c7371c90267 Mon Sep 17 00:00:00 2001 From: ssmubc Date: Wed, 10 Jun 2026 16:38:39 -0700 Subject: [PATCH] fix: ignore requires-python in supply-chain scan --- CHANGELOG.md | 4 ++++ src/mcts/analyzers/supply_chain.py | 15 ++++++++++++++- tests/test_supply_chain.py | 26 ++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/test_supply_chain.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3f46a..a663a7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Ignore PEP 621 `requires-python` metadata in supply-chain dependency findings. + ## [0.1.2] - 2026-06-10 ### Added diff --git a/src/mcts/analyzers/supply_chain.py b/src/mcts/analyzers/supply_chain.py index 1557ae0..c63cca5 100644 --- a/src/mcts/analyzers/supply_chain.py +++ b/src/mcts/analyzers/supply_chain.py @@ -84,7 +84,20 @@ def _scan_pyproject(self, root: Path) -> list[Finding]: findings: list[Finding] = [] for path in _find_files(root, "pyproject.toml"): text = path.read_text(encoding="utf-8", errors="ignore") + current_section = "" + for line_no, line in enumerate(text.splitlines(), start=1): + stripped = line.strip() + + section_match = re.fullmatch(r"\[([^\]]+)\]", stripped) + if section_match: + current_section = section_match.group(1) + continue + + key, separator, _ = stripped.partition("=") + if current_section == "project" and separator and key.strip() == "requires-python": + continue + if UNPINNED_PATTERN.search(line) and any( token in line for token in ('"', "dependencies", "requires") ): @@ -93,7 +106,7 @@ def _scan_pyproject(self, root: Path) -> list[Finding]: path, f"supply-unpinned-py-{line_no}", "Unpinned Python dependency", - line.strip(), + stripped, Severity.MEDIUM, "MCTS-T-1014", line=line_no, diff --git a/tests/test_supply_chain.py b/tests/test_supply_chain.py new file mode 100644 index 0000000..9116c65 --- /dev/null +++ b/tests/test_supply_chain.py @@ -0,0 +1,26 @@ +"""Tests for supply-chain analysis.""" + +from pathlib import Path + +from mcts.analyzers.supply_chain import SupplyChainAnalyzer +from mcts.mcp.models import MCPServerInfo + + +def test_pyproject_ignores_requires_python(tmp_path: Path) -> None: + pyproject = tmp_path / "pyproject.toml" + pyproject.write_text( + """ +[project] +name = "demo" +version = "0.1.0" +requires-python = ">=3.9" +dependencies = ["requests>=2.31.0"] +""".strip(), + encoding="utf-8", + ) + + findings = SupplyChainAnalyzer(tmp_path).analyze(MCPServerInfo()) + descriptions = [finding.description for finding in findings] + + assert not any("requires-python" in description for description in descriptions) + assert any("requests>=2.31.0" in description for description in descriptions)