Enforce SHA256 verification on every binary install path
Three gaps allowed an unverified binary to reach a trusted location: - The ffmpeg ZIP fallback logged a warning on checksum mismatch and installed anyway (the 7z path already aborted). Abort instead. - The yt-dlp auto-update path downloaded and renamed the binary over the verified one with no checksum at all. Verify against the official SHA2-256SUMS like the first-install path, and use atomic os.replace. - The yt-dlp first install streamed the download directly to the trusted path and only verified afterwards; a crash in between left an unverified executable to be run on next launch. Download to .part and os.replace only after verification. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,10 @@ class DownloadYtdlpThread(QThread):
|
||||
try:
|
||||
# Extra logic moved to src\utils\ytsage_constants.py
|
||||
exe_path = YTDLP_APP_BIN_PATH
|
||||
# Download to a temp name and only move to the trusted path after
|
||||
# the hash checks out, so a crash mid-download can never leave an
|
||||
# unverified binary where the app will execute it.
|
||||
part_path = exe_path.with_name(exe_path.name + ".part")
|
||||
|
||||
# Download with progress reporting
|
||||
logger.info(f"Downloading yt-dlp from: {YTDLP_DOWNLOAD_URL}")
|
||||
@@ -123,7 +127,7 @@ class DownloadYtdlpThread(QThread):
|
||||
if total_size == 0:
|
||||
self.progress_signal.emit(100)
|
||||
|
||||
with open(exe_path, "wb") as f:
|
||||
with open(part_path, "wb") as f:
|
||||
downloaded = 0
|
||||
for data in response.iter_content(block_size):
|
||||
f.write(data)
|
||||
@@ -133,22 +137,23 @@ class DownloadYtdlpThread(QThread):
|
||||
self.progress_signal.emit(progress)
|
||||
|
||||
logger.info("Download complete, verifying SHA256 hash...")
|
||||
|
||||
|
||||
# Verify SHA256 hash
|
||||
if not verify_ytdlp_sha256(exe_path, YTDLP_DOWNLOAD_URL):
|
||||
if not verify_ytdlp_sha256(part_path, YTDLP_DOWNLOAD_URL):
|
||||
# Hash verification failed - delete the downloaded file
|
||||
logger.error("SHA256 verification failed! Removing downloaded file.")
|
||||
if Path(exe_path).exists():
|
||||
Path(exe_path).unlink()
|
||||
part_path.unlink(missing_ok=True)
|
||||
self.finished_signal.emit(
|
||||
False,
|
||||
False,
|
||||
"SHA256 verification failed. The downloaded file may be corrupted or tampered with."
|
||||
)
|
||||
return
|
||||
|
||||
# Make executable on macOS and Linux
|
||||
if OS_NAME != "Windows":
|
||||
os.chmod(exe_path, 0o755)
|
||||
os.chmod(part_path, 0o755)
|
||||
|
||||
os.replace(part_path, exe_path)
|
||||
|
||||
logger.info("yt-dlp downloaded and verified successfully!")
|
||||
self.finished_signal.emit(True, str(exe_path))
|
||||
|
||||
Reference in New Issue
Block a user