From 0000bf0adc11e76cae2f73be809b86c6bfaa6a59 Mon Sep 17 00:00:00 2001 From: Ulzii Otgonbaatar Date: Wed, 3 Jun 2026 10:19:35 -0600 Subject: [PATCH] Fix remediation setup for pnpm and Python lockfiles Install pnpm when Socket fixes run against pnpm workspaces, and allow Python requirements lockfiles through remediation diff validation. Co-authored-by: Cursor --- .github/workflows/vuln-remediation.yml | 36 ++++++++++++++++++++++++++ scripts/test_vuln_remediation.py | 13 ++++++++++ scripts/vuln_remediation.py | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/.github/workflows/vuln-remediation.yml b/.github/workflows/vuln-remediation.yml index 03ce3cb..9c8f704 100644 --- a/.github/workflows/vuln-remediation.yml +++ b/.github/workflows/vuln-remediation.yml @@ -254,6 +254,42 @@ jobs: if: steps.check.outputs.skip != 'true' && inputs.setup-bun run: bun install + - name: Setup pnpm for Socket fixes + if: steps.check.outputs.skip != 'true' + run: | + PNPM_VERSION=$(python3 - <<'PY' + import json + from pathlib import Path + + ignored = {"node_modules", ".git"} + for package_json in Path(".").rglob("package.json"): + if any(part in ignored for part in package_json.parts): + continue + try: + package_manager = json.loads(package_json.read_text()).get("packageManager", "") + except Exception: + package_manager = "" + if package_manager.startswith("pnpm@"): + print(package_manager.removeprefix("pnpm@")) + break + if (package_json.parent / "pnpm-lock.yaml").exists(): + print("latest") + break + else: + for lockfile in Path(".").rglob("pnpm-lock.yaml"): + if not any(part in ignored for part in lockfile.parts): + print("latest") + break + else: + print("") + PY + ) + if [ -n "$PNPM_VERSION" ]; then + npm install -g "pnpm@${PNPM_VERSION}" + else + echo "No pnpm workspace detected." + fi + - name: Setup Python if: steps.check.outputs.skip != 'true' && inputs.setup-python uses: actions/setup-python@v5 diff --git a/scripts/test_vuln_remediation.py b/scripts/test_vuln_remediation.py index a9d310f..ea42a15 100644 --- a/scripts/test_vuln_remediation.py +++ b/scripts/test_vuln_remediation.py @@ -238,6 +238,19 @@ def test_accepts_clean_socket_planned_dependency_change(self) -> None: self.assertTrue(result.ok, result.errors) + def test_accepts_python_requirements_lockfiles(self) -> None: + write(self.root / "pyproject.toml", "[project]\ndependencies = ['aiohttp==3.13.3']\n") + write(self.root / "requirements.lock", "aiohttp==3.13.3\n") + write(self.root / "requirements-dev.lock", "aiohttp==3.13.3\n") + self.commit_all() + write(self.root / "pyproject.toml", "[project]\ndependencies = ['aiohttp==3.13.4']\n") + write(self.root / "requirements.lock", "aiohttp==3.13.4\n") + write(self.root / "requirements-dev.lock", "aiohttp==3.13.4\n") + + result = vr.validate_diff(self.root, ["pyproject.toml", "requirements.lock", "requirements-dev.lock"]) + + self.assertTrue(result.ok, result.errors) + class ConfirmationTests(RemediationFixture): def test_confirmation_fails_when_old_vulnerable_version_remains(self) -> None: diff --git a/scripts/vuln_remediation.py b/scripts/vuln_remediation.py index abacfe5..66ceae7 100644 --- a/scripts/vuln_remediation.py +++ b/scripts/vuln_remediation.py @@ -49,7 +49,7 @@ "Pipfile.lock", } -REQUIREMENTS_RE = re.compile(r"(^|/)requirements[^/]*\.txt$") +REQUIREMENTS_RE = re.compile(r"(^|/)requirements[^/]*\.(?:txt|lock)$") MAX_ALLOWED_FILE_SIZE = 5 * 1024 * 1024