From 595ef648dbe6dd73f04fcd537b085eb5ef2df278 Mon Sep 17 00:00:00 2001 From: openoms Date: Thu, 7 May 2026 14:47:49 +0200 Subject: [PATCH] fix: pnpm audit critical protobufjs advisory Update the root protobufjs resolution from 7.2.5 to 7.5.5 and refresh pnpm-lock.yaml so all workspace audit targets resolve to the patched version. This clears the critical pnpm audit advisory that caused the Buck audit targets to fail in CI. Also improve the shared pnpm audit wrapper to report failing advisories from the JSON audit result directly. The previous wrapper reran `pnpm audit` without JSON after detecting vulnerabilities, which could hang until Buck's 10 minute test timeout and leave CI with empty audit stdout/stderr. The wrapper now captures stderr for parse failures and prints concise advisory details for vulnerabilities at or above the configured audit level. Validation: - pnpm audit metadata reports critical: 0 - run_audit.py passes at --audit-level critical - all seven previously failing Buck audit targets pass --- package.json | 2 +- pnpm-lock.yaml | 16 +++--- toolchains/workspace-pnpm/run_audit.py | 76 +++++++++++++++++++++----- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 1d79790f80..594af9e2b3 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "resolutions": { "@types/ws": "^8.5.12", "basic-ftp": "^5.2.0", - "protobufjs": "7.2.5", + "protobufjs": "7.5.5", "http-cache-semantics": "4.1.1", "elliptic": "^6.6.1", "form-data": "^4.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 89f6e3d4f5..6179ecafca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,7 +7,7 @@ settings: overrides: '@types/ws': ^8.5.12 basic-ftp: ^5.2.0 - protobufjs: 7.2.5 + protobufjs: 7.5.5 http-cache-semantics: 4.1.1 elliptic: ^6.6.1 form-data: ^4.0.4 @@ -5630,7 +5630,7 @@ packages: fast-deep-equal: 3.1.3 functional-red-black-tree: 1.0.1 google-gax: 4.6.1 - protobufjs: 7.2.5 + protobufjs: 7.5.5 transitivePeerDependencies: - encoding - supports-color @@ -7431,7 +7431,7 @@ packages: dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.2.5 + protobufjs: 7.5.5 yargs: 17.7.2 dev: false @@ -8757,7 +8757,7 @@ packages: '@opentelemetry/sdk-logs': 0.53.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 1.26.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) - protobufjs: 7.2.5 + protobufjs: 7.5.5 dev: false /@opentelemetry/propagator-b3@1.26.0(@opentelemetry/api@1.9.0): @@ -21634,7 +21634,7 @@ packages: node-fetch: 2.7.0 object-hash: 3.0.0 proto3-json-serializer: 2.0.2 - protobufjs: 7.2.5 + protobufjs: 7.5.5 retry-request: 7.0.2 uuid: 9.0.1 transitivePeerDependencies: @@ -27163,12 +27163,12 @@ packages: engines: {node: '>=14.0.0'} requiresBuild: true dependencies: - protobufjs: 7.2.5 + protobufjs: 7.5.5 dev: false optional: true - /protobufjs@7.2.5: - resolution: {integrity: sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==} + /protobufjs@7.5.5: + resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} engines: {node: '>=12.0.0'} requiresBuild: true dependencies: diff --git a/toolchains/workspace-pnpm/run_audit.py b/toolchains/workspace-pnpm/run_audit.py index be07786885..927d624e1c 100644 --- a/toolchains/workspace-pnpm/run_audit.py +++ b/toolchains/workspace-pnpm/run_audit.py @@ -7,20 +7,60 @@ import subprocess import sys +SEVERITY_ORDER = [ + "low", + "moderate", + "high", + "critical", +] + + def sum_severities(severity_dict, start_level): - severity_order = [ - "low", - "moderate", - "high", - "critical" + start_index = SEVERITY_ORDER.index(start_level) + return sum( + severity_dict.get(level, 0) + for level in SEVERITY_ORDER[start_index:] + ) + + +def severity_meets_threshold(severity, audit_level): + return SEVERITY_ORDER.index(severity) >= SEVERITY_ORDER.index(audit_level) + + +def print_advisories(result_dict, audit_level): + advisories = result_dict.get("advisories", {}) + matching_advisories = [ + advisory + for advisory in advisories.values() + if severity_meets_threshold(advisory["severity"], audit_level) ] - start_index = severity_order.index(start_level) - return sum( - severity_dict[level] - for level in severity_order[start_index:] + matching_advisories.sort( + key=lambda advisory: SEVERITY_ORDER.index(advisory["severity"]), + reverse=True, ) + print(f"pnpm audit found advisories at or above '{audit_level}':") + for advisory in matching_advisories: + print() + print(f"{advisory['severity']}: {advisory['module_name']}") + print(f" title: {advisory['title']}") + if patched_versions := advisory.get("patched_versions"): + print(f" patched versions: {patched_versions}") + if url := advisory.get("url"): + print(f" url: {url}") + + findings = advisory.get("findings", []) + paths = [ + " > ".join(finding["paths"][0]) + for finding in findings + if finding.get("paths") + ] + for path in paths[:3]: + print(f" path: {path}") + if len(paths) > 3: + print(f" ... {len(paths) - 3} more paths") + if __name__ == "__main__": parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( @@ -34,18 +74,25 @@ def sum_severities(severity_dict, start_level): ) args = parser.parse_args() - audit_args = args.args[1:] # ignore '--' separator + audit_args = args.args[1:] # ignore '--' separator pnpm_cmd = ["pnpm", "audit"] audit_cmd = [*pnpm_cmd, *audit_args] audit_cmd_json_out = [*audit_cmd, "--json"] - result = subprocess.run(audit_cmd_json_out, stdout=subprocess.PIPE) + result = subprocess.run( + audit_cmd_json_out, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) try: result_dict = json.loads(result.stdout) - except: - print("Could not parse audit response. Got 'result.stdout' value:", file=sys.stderr) + except json.JSONDecodeError: + print("Could not parse audit response. Got stdout value:", file=sys.stderr) print(result.stdout, file=sys.stderr) + print("stderr:", file=sys.stderr) + print(result.stderr, file=sys.stderr) sys.exit(1) num_vulns = sum_severities( @@ -53,8 +100,7 @@ def sum_severities(severity_dict, start_level): args.audit_level ) if num_vulns > 0: - printable_result = subprocess.run(audit_cmd, stdout=subprocess.PIPE, text=True) - print(printable_result.stdout) + print_advisories(result_dict, args.audit_level) sys.exit(1) sys.exit(0)