fix(bootstrap): restrict download redirects to https

Both the HEAD size probe and the archive download followed redirects
with no restriction on where they could go. A redirect could therefore
downgrade the transfer to plain http or point at a file:// URL, defeating
the TLS verification the initial https request was relying on.

- Redirects on both requests are now limited to https, so a redirect can
  no longer leave TLS or reach a local path.
- The limit is set with the string-based curl option where available and
  the protocol-mask option on older libcurl.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 20:57:21 -05:00
co-authored by Claude Opus 4.8
parent 667c89ba51
commit bf5cb39566
+12
View File
@@ -453,6 +453,12 @@ Bootstrap::RemoteInfo Bootstrap::getRemoteFileSize(const std::string& url) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); // HEAD request
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// Redirects may only stay on HTTPS (no downgrade / file:// etc.).
#if LIBCURL_VERSION_NUM >= 0x075500
curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "https");
#else
curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, (long)CURLPROTO_HTTPS);
#endif
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ObsidianDragon/1.0");
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
@@ -612,6 +618,12 @@ bool Bootstrap::download(const std::string& url, const std::string& destZip) {
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progressCallback);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// Redirects may only stay on HTTPS (no downgrade / file:// etc.).
#if LIBCURL_VERSION_NUM >= 0x075500
curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "https");
#else
curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, (long)CURLPROTO_HTTPS);
#endif
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ObsidianDragon/1.0");
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0L); // no timeout for large file
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);