From 6db03f05a9cc56ce9beb1b0b4e91104ca642f4d9 Mon Sep 17 00:00:00 2001 From: Sucukdeluxe Date: Thu, 5 Mar 2026 02:32:59 +0100 Subject: [PATCH] Fix DDownload downloads failing due to SSL certificate verification DDownload's storage servers (dstorage.org) use certificates that fail Node.js TLS verification. Add skipTlsVerify flag to UnrestrictedLink and temporarily disable TLS verification for the download fetch when the flag is set. Co-Authored-By: Claude Opus 4.6 --- package.json | 2 +- src/main/debrid.ts | 9 ++++++--- src/main/download-manager.ts | 13 +++++++++++-- src/main/realdebrid.ts | 1 + 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7df4e5a..88b3095 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "real-debrid-downloader", - "version": "1.6.37", + "version": "1.6.38", "description": "Desktop downloader", "main": "build/main/main/main.js", "author": "Sucukdeluxe", diff --git a/src/main/debrid.ts b/src/main/debrid.ts index 12ba2b0..65345df 100644 --- a/src/main/debrid.ts +++ b/src/main/debrid.ts @@ -1053,7 +1053,8 @@ class DdownloadClient { fileName: filenameFromUrl(directUrl) || filenameFromUrl(link), directUrl, fileSize: null, - retriesUsed: attempt - 1 + retriesUsed: attempt - 1, + skipTlsVerify: true }; } } @@ -1102,7 +1103,8 @@ class DdownloadClient { fileName: fileName || filenameFromUrl(directUrl), directUrl, fileSize: null, - retriesUsed: attempt - 1 + retriesUsed: attempt - 1, + skipTlsVerify: true }; } } @@ -1115,7 +1117,8 @@ class DdownloadClient { fileName, directUrl: directMatch[0], fileSize: null, - retriesUsed: attempt - 1 + retriesUsed: attempt - 1, + skipTlsVerify: true }; } diff --git a/src/main/download-manager.ts b/src/main/download-manager.ts index d1c56e8..d56d5a1 100644 --- a/src/main/download-manager.ts +++ b/src/main/download-manager.ts @@ -4717,7 +4717,7 @@ export class DownloadManager extends EventEmitter { item.updatedAt = nowMs(); this.emitState(); } - const result = await this.downloadToFile(active, unrestricted.directUrl, item.targetPath, item.totalBytes); + const result = await this.downloadToFile(active, unrestricted.directUrl, item.targetPath, item.totalBytes, unrestricted.skipTlsVerify); active.resumable = result.resumable; if (!active.resumable && !active.nonResumableCounted) { active.nonResumableCounted = true; @@ -5102,7 +5102,8 @@ export class DownloadManager extends EventEmitter { active: ActiveTask, directUrl: string, targetPath: string, - knownTotal: number | null + knownTotal: number | null, + skipTlsVerify?: boolean ): Promise<{ resumable: boolean }> { const item = this.session.items[active.itemId]; if (!item) { @@ -5148,12 +5149,16 @@ export class DownloadManager extends EventEmitter { const connectTimeoutMs = getDownloadConnectTimeoutMs(); let connectTimer: NodeJS.Timeout | null = null; const connectAbortController = new AbortController(); + const prevTlsReject = process.env.NODE_TLS_REJECT_UNAUTHORIZED; try { if (connectTimeoutMs > 0) { connectTimer = setTimeout(() => { connectAbortController.abort("connect_timeout"); }, connectTimeoutMs); } + if (skipTlsVerify) { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + } response = await fetch(directUrl, { method: "GET", headers, @@ -5173,6 +5178,10 @@ export class DownloadManager extends EventEmitter { } throw error; } finally { + if (skipTlsVerify) { + if (prevTlsReject === undefined) delete process.env.NODE_TLS_REJECT_UNAUTHORIZED; + else process.env.NODE_TLS_REJECT_UNAUTHORIZED = prevTlsReject; + } if (connectTimer) { clearTimeout(connectTimer); } diff --git a/src/main/realdebrid.ts b/src/main/realdebrid.ts index d07831f..93d27c4 100644 --- a/src/main/realdebrid.ts +++ b/src/main/realdebrid.ts @@ -8,6 +8,7 @@ export interface UnrestrictedLink { directUrl: string; fileSize: number | null; retriesUsed: number; + skipTlsVerify?: boolean; } function shouldRetryStatus(status: number): boolean {