Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .trivyignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,3 @@ yt_dlp/extractor/vice.py
# Guarded by scripts/checks/verify_supply_chain.py and remove when upstream
# drops or patches the chain. Revisit by 2026-10-31.
GHSA-wrw7-89jp-8q8g exp:2026-10-31

# CVE-2026-59890: setuptools 81.0.0 in services/analysis-engine/uv.lock.
# 81.0.0 is the latest version uv resolves (`uv lock --upgrade-package
# setuptools` does not advance it), so no fixed release is installable yet.
# setuptools is a build/packaging-time transitive dependency and is never
# imported on the runtime analysis path (the engine runs from its built
# wheel), so it is outside the request-time attack surface. Remove once a
# fixed setuptools publishes and uv can resolve it. Revisit by 2026-10-31.
CVE-2026-59890 exp:2026-10-31
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

### Fixed

- Patched the Python analysis dependency baseline by locking `torch` 2.13.0, `setuptools` 84.0.0, and `yt-dlp` 2026.8.19, retiring the obsolete torch exception while preserving the intentional macOS Intel Demucs exclusion.
- Upgraded the local score PDF parser to `pdfjs-dist` 6.2.108, pinned Undici 7.29.0 across the workspace, and constrained PDF loading to copied in-memory bytes with a same-origin bundled worker and npm-generated lock provenance.

## [0.1.3] - 2026-04-29
Expand Down
4 changes: 3 additions & 1 deletion docs/security/dependency-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ Current controlled exceptions:
Retired third-party deprecation and advisory signal:

- `proc-macro-hack v0.5.20+deprecated`, `RUSTSEC-2025-0057` for `fxhash`, and `RUSTSEC-2026-0097` for legacy `rand 0.7.3` were removed by a compatible Tauri lockfile refresh that moved `tauri` to `2.11.0` and `tauri-utils` to `2.9.0`, dropping the `kuchikiki`/`selectors`/`phf 0.8` owner chain. Do not reintroduce this chain or restore the `RUSTSEC-2026-0097` Cargo audit exception; `scripts/checks/verify_supply_chain.py` rejects any future `rand 0.7.x` lockfile entry.
- `GHSA-53q9-r3pm-6pq6` (`torch.load` RCE, fixed in torch 2.6) is allowed only for `torch 2.2.2` in `services/analysis-engine`: torch 2.2.2 is the last release publishing macOS Intel (x86_64) wheels, and the cross-platform build policy mandates macOS Intel + arm64. The vulnerable API only ever loads demucs's pinned model weights (bundled/checksum-tracked per this policy); user-supplied audio never reaches `torch.load`. The exception is encoded in `.github/workflows/dependency-review.yml` (`allow-ghsas`) and `services/analysis-engine/osv-scanner.toml`, and must be removed when the engine migrates off torch (e.g. ONNX runtime) or the Intel-mac mandate changes.
- `GHSA-53q9-r3pm-6pq6` (`torch.load` RCE, fixed in torch 2.6) and `GHSA-rrmf-rvhw-rf47` (`torch.jit.script` memory corruption, fixed in torch 2.13.0) are retired for BandScope's supported Demucs platforms by locking `torch` to `2.13.0`. The analysis-engine manifest intentionally excludes Demucs on macOS Intel (`darwin` non-arm64), so that platform does not install Demucs or torch; macOS Intel packaging remains required, but it must not be used as a reason to restore a vulnerable torch exception.
- `GHSA-h35f-9h28-mq5c` for `setuptools <83.0.0` is retired by locking `setuptools` to `84.0.0`. No Python audit ignore is permitted for this advisory.
Comment thread
seonghobae marked this conversation as resolved.
- `GHSA-6v4j-43gg-vj32` for `yt-dlp <2026.7.4` was fixed in 2026.7.4. BandScope currently requires and locks `yt-dlp` at `2026.8.19` as forward maintenance hardening of the untrusted remote-media boundary; the newer lock is not evidence that the advisory's patched floor changed.
- Yanked `fastrand 2.4.0` was transiently inherited through target-specific `wry`/`dom_query` HTML parsing dependencies and must stay updated to `2.4.1` or newer in `apps/desktop/src-tauri/Cargo.lock`; `scripts/checks/verify_supply_chain.py` guards against reintroducing the yanked version.

## Required checks intent
Expand Down
2 changes: 1 addition & 1 deletion services/analysis-engine/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies = [
"numpy>=1.26",
"soundfile>=0.13.1",
"urllib3>=2.7.0",
"yt-dlp>=2026.7.4",
"yt-dlp>=2026.8.19",
]

[dependency-groups]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""Regression contracts for BandScope's patched Python dependency baseline."""

from __future__ import annotations

import tomllib
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[3]
PYPROJECT = REPO_ROOT / "services" / "analysis-engine" / "pyproject.toml"
UV_LOCK = REPO_ROOT / "services" / "analysis-engine" / "uv.lock"
DEPENDENCY_POLICY = REPO_ROOT / "docs" / "security" / "dependency-policy.md"
TRIVYIGNORE = REPO_ROOT / ".trivyignore"


def _locked_version(package_name: str) -> str:
"""Return the single locked version for ``package_name``."""
lock = tomllib.loads(UV_LOCK.read_text(encoding="utf-8"))
matches = [
package.get("version")
for package in lock.get("package", [])
if package.get("name") == package_name
]
assert len(matches) == 1
version = matches[0]
assert isinstance(version, str)
return version


def _project_dependencies() -> list[str]:
"""Return validated direct analysis-engine dependency requirements."""
pyproject = tomllib.loads(PYPROJECT.read_text(encoding="utf-8"))
project = pyproject.get("project")
assert isinstance(project, dict)
dependencies = project.get("dependencies")
assert isinstance(dependencies, list)
assert all(isinstance(requirement, str) for requirement in dependencies)
return dependencies


def _active_exceptions(policy: str) -> str:
"""Return the policy's controlled-exception section and fail on schema drift."""
_prefix, start, remainder = policy.partition("Current controlled exceptions:")
assert start
active, end, _retired = remainder.partition(
"Retired third-party deprecation and advisory signal:"
)
assert end
return active


def test_python_security_baseline_keeps_patched_versions() -> None:
"""Prevent reintroduction of the patched setuptools, torch, and yt-dlp releases."""
assert _locked_version("setuptools") == "84.0.0"
assert _locked_version("torch") == "2.13.0"
assert _locked_version("yt-dlp") == "2026.8.19"


def test_torch_security_policy_matches_supported_platform_contract() -> None:
"""Retire obsolete torch exceptions while preserving macOS Intel exclusion."""
dependencies = _project_dependencies()
policy = DEPENDENCY_POLICY.read_text(encoding="utf-8")
active_exceptions = _active_exceptions(policy)
expected_demucs_requirement = (
"demucs>=4.0.1 ; sys_platform != 'darwin' or platform_machine == 'arm64'"
)

assert expected_demucs_requirement in dependencies
assert not any(requirement.lower().startswith("torch") for requirement in dependencies)
assert "GHSA-53q9-r3pm-6pq6" not in active_exceptions
assert "GHSA-rrmf-rvhw-rf47" not in active_exceptions
assert "torch 2.2.2" not in active_exceptions
assert ".github/workflows/dependency-review.yml" not in policy
assert "services/analysis-engine/osv-scanner.toml" not in policy
assert "macOS Intel" in policy
assert "does not install Demucs or torch" in policy


def test_setuptools_security_exception_is_retired() -> None:
"""Reject the obsolete setuptools CVE exception after upgrading past its patch floor."""
policy = DEPENDENCY_POLICY.read_text(encoding="utf-8")
trivyignore = TRIVYIGNORE.read_text(encoding="utf-8")

assert "GHSA-h35f-9h28-mq5c" not in _active_exceptions(policy)
assert "CVE-2026-59890" not in trivyignore


def test_yt_dlp_policy_distinguishes_patch_floor_from_current_lock() -> None:
"""Keep the advisory's patched floor distinct from the intentionally newer lock."""
pyproject = PYPROJECT.read_text(encoding="utf-8")
policy = DEPENDENCY_POLICY.read_text(encoding="utf-8")

assert '"yt-dlp>=2026.8.19"' in pyproject
assert "GHSA-6v4j-43gg-vj32" in policy
assert "fixed in 2026.7.4" in policy
assert "2026.8.19" in policy
Loading
Loading