79 lines
3.0 KiB
Python
Executable File
79 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Offline minimum-version gates for network-facing RustSec advisories reviewed 2026-10-04.
|
|
|
|
This is deliberately not a replacement for `cargo audit`: it prevents known-fixed
|
|
packages from being accidentally downgraded when the lockfile changes.
|
|
"""
|
|
from __future__ import annotations
|
|
from pathlib import Path
|
|
import re
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
LOCK = (ROOT / "Cargo.lock").read_text(encoding="utf-8")
|
|
|
|
|
|
def versions() -> dict[str, list[str]]:
|
|
found: dict[str, list[str]] = {}
|
|
for block in LOCK.split("[[package]]")[1:]:
|
|
match = re.search(r'\n?name = "([^"]+)"\nversion = "([^"]+)"', block)
|
|
if match:
|
|
found.setdefault(match.group(1), []).append(match.group(2))
|
|
return found
|
|
|
|
|
|
def triplet(value: str) -> tuple[int, int, int]:
|
|
match = re.match(r"^(\d+)\.(\d+)\.(\d+)", value)
|
|
if not match:
|
|
raise AssertionError(f"unsupported version syntax: {value}")
|
|
return tuple(map(int, match.groups()))
|
|
|
|
|
|
packages = versions()
|
|
minimums = {
|
|
# RUSTSEC-2026-0285
|
|
"rustls": (0, 23, 45),
|
|
# RUSTSEC-2026-0185 and RUSTSEC-2026-0037
|
|
"quinn-proto": (0, 11, 15),
|
|
# RUSTSEC-2026-0104 (also covers 0049/0098/0099)
|
|
"rustls-webpki": (0, 103, 13),
|
|
# RUSTSEC-2025-0009
|
|
"ring": (0, 17, 12),
|
|
# RUSTSEC-2024-0363
|
|
"sqlx": (0, 8, 1),
|
|
# RUSTSEC-2026-0258
|
|
"h2": (0, 4, 16),
|
|
# RUSTSEC-2026-0007
|
|
"bytes": (1, 11, 1),
|
|
# RUSTSEC-2026-0009
|
|
"time": (0, 3, 47),
|
|
}
|
|
for package, minimum in minimums.items():
|
|
locked = packages.get(package)
|
|
if not locked:
|
|
raise AssertionError(f"expected security-critical dependency {package} in Cargo.lock")
|
|
for value in locked:
|
|
if triplet(value) < minimum:
|
|
raise AssertionError(f"{package} {value} is below reviewed patched minimum {'.'.join(map(str, minimum))}")
|
|
|
|
# 2026 malicious-crate campaign snapshot reviewed against RustSec on 2026-10-04.
|
|
# Keep the exact arrayref version gate because earlier arrayref releases are legitimate.
|
|
for value in packages.get("arrayref", []):
|
|
if value == "0.3.10":
|
|
raise AssertionError("Cargo.lock contains compromised arrayref 0.3.10")
|
|
|
|
malicious_packages = {
|
|
"greentic-setup", "greentic-setup-dev", "append-only-vec", "proc-macro1",
|
|
"internment", "proc-macro-en", "onering", "logflux", "exploration",
|
|
"sui-execution-cut", "mysten-metrics", "microsoftsystem64",
|
|
"pretty-changelog-logger", "safe-agent-rs", "logtrace", "jfrog_quotes",
|
|
"tree-sitter-pkl", "custom-req-on-workers", "sophosfirewall-python",
|
|
"statsrelay-protobuf", "time_calibrator", "tracings", "tracing_checks",
|
|
"rpc-check", "tracing-check", "clob-sdk", "polymarkets-rs-clob-client",
|
|
"polymarkets-client-sdk", "polymarket-client-sdks", "finch-rst",
|
|
}
|
|
present = sorted(malicious_packages.intersection(packages))
|
|
if present:
|
|
raise AssertionError(f"Cargo.lock contains RustSec-listed malicious package(s): {', '.join(present)}")
|
|
|
|
print("PASS: Cargo.lock stays above reviewed RustSec minimums and excludes the reviewed 2026 malicious-crate set (snapshot 2026-10-04).")
|