Skip to content

Commit 7c19f37

Browse files
Harden auto updater source selection
1 parent c63edfb commit 7c19f37

File tree

3 files changed

+156
-211
lines changed

3 files changed

+156
-211
lines changed

src/UniGetUI.Avalonia/Infrastructure/AvaloniaAutoUpdater.cs

Lines changed: 55 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,6 @@ internal static partial class AvaloniaAutoUpdater
3333
private const string REG_SKIP_HASH_VALIDATION = "UpdaterSkipHashValidation";
3434
private const string REG_SKIP_SIGNER_THUMBPRINT_CHECK = "UpdaterSkipSignerThumbprintCheck";
3535
private const string REG_DISABLE_TLS_VALIDATION = "UpdaterDisableTlsValidation";
36-
private const string REG_USE_LEGACY_GITHUB = "UpdaterUseLegacyGithub";
37-
38-
private const string STABLE_ENDPOINT =
39-
"https://www.marticliment.com/versions/unigetui/stable.ver";
40-
private const string BETA_ENDPOINT =
41-
"https://www.marticliment.com/versions/unigetui/beta.ver";
42-
private const string STABLE_INSTALLER_URL =
43-
"https://github.com/Devolutions/UniGetUI/releases/latest/download/UniGetUI.Installer.exe";
44-
private const string BETA_INSTALLER_URL =
45-
"https://github.com/Devolutions/UniGetUI/releases/download/$TAG/UniGetUI.Installer.exe";
4636

4737
private static readonly string[] DEVOLUTIONS_CERT_THUMBPRINTS =
4838
[
@@ -51,6 +41,17 @@ internal static partial class AvaloniaAutoUpdater
5141
"50f753333811ff11f1920274afde3ffd4468b210",
5242
];
5343

44+
#if !DEBUG
45+
private static readonly string[] RELEASE_IGNORED_REGISTRY_VALUES =
46+
[
47+
REG_PRODUCTINFO_KEY,
48+
REG_ALLOW_UNSAFE_URLS,
49+
REG_SKIP_HASH_VALIDATION,
50+
REG_SKIP_SIGNER_THUMBPRINT_CHECK,
51+
REG_DISABLE_TLS_VALIDATION,
52+
];
53+
#endif
54+
5455
private static readonly AutoUpdaterJsonContext _jsonContext = new(
5556
new JsonSerializerOptions(SerializationHelpers.DefaultOptions)
5657
);
@@ -245,21 +246,7 @@ private static async Task LaunchInstallerAndQuitAsync(string installerLocation)
245246
// ------------------------------------------------------------------ update check sources
246247
private static async Task<UpdateCandidate> GetUpdateCandidateAsync(UpdaterOverrides overrides)
247248
{
248-
if (overrides.UseLegacyGithub)
249-
{
250-
return await CheckFromLegacyGitHubAsync(overrides);
251-
}
252-
253-
try
254-
{
255-
return await CheckFromProductInfoAsync(overrides);
256-
}
257-
catch (Exception ex)
258-
{
259-
Logger.Warn("ProductInfo source failed; falling back to legacy GitHub source.");
260-
Logger.Warn(ex);
261-
return await CheckFromLegacyGitHubAsync(overrides);
262-
}
249+
return await CheckFromProductInfoAsync(overrides);
263250
}
264251

265252
private static async Task<UpdateCandidate> CheckFromProductInfoAsync(UpdaterOverrides overrides)
@@ -329,40 +316,6 @@ private static async Task<UpdateCandidate> CheckFromProductInfoAsync(UpdaterOver
329316
return new UpdateCandidate(upgradable, channel.Version, installer.Hash, installer.Url, "ProductInfo");
330317
}
331318

332-
private static async Task<UpdateCandidate> CheckFromLegacyGitHubAsync(UpdaterOverrides overrides)
333-
{
334-
bool useBeta = Settings.Get(Settings.K.EnableUniGetUIBeta);
335-
string endpoint = useBeta ? BETA_ENDPOINT : STABLE_ENDPOINT;
336-
string installerUrl = useBeta ? BETA_INSTALLER_URL : STABLE_INSTALLER_URL;
337-
338-
Logger.Debug($"Checking updates via legacy GitHub endpoint: {endpoint}");
339-
340-
string[] parts;
341-
using (HttpClient client = new(CreateHttpClientHandler(overrides)))
342-
{
343-
client.Timeout = TimeSpan.FromSeconds(600);
344-
client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreData.UserAgentString);
345-
parts = (await client.GetStringAsync(endpoint)).Split("////");
346-
}
347-
348-
if (parts.Length >= 3)
349-
{
350-
int latestBuild = int.Parse(parts[0].Trim());
351-
string hash = parts[1].Trim();
352-
string versionName = parts[2].Trim();
353-
354-
return new UpdateCandidate(
355-
latestBuild > CoreData.BuildNumber,
356-
versionName,
357-
hash,
358-
installerUrl.Replace("$TAG", versionName),
359-
"LegacyGitHub"
360-
);
361-
}
362-
363-
throw new FormatException("Legacy update file does not follow the expected format.");
364-
}
365-
366319
// ------------------------------------------------------------------ validation helpers
367320
private static async Task<bool> CheckInstallerHashAsync(
368321
string path,
@@ -488,9 +441,7 @@ private static bool IsSourceUrlAllowed(string url, bool allowUnsafe)
488441
return uri.Host.EndsWith("devolutions.net", StringComparison.OrdinalIgnoreCase)
489442
|| uri.Host.Equals("github.com", StringComparison.OrdinalIgnoreCase)
490443
|| uri.Host.Equals("objects.githubusercontent.com", StringComparison.OrdinalIgnoreCase)
491-
|| uri.Host.Equals("release-assets.githubusercontent.com", StringComparison.OrdinalIgnoreCase)
492-
|| uri.Host.Equals("marticliment.com", StringComparison.OrdinalIgnoreCase)
493-
|| uri.Host.EndsWith("marticliment.com", StringComparison.OrdinalIgnoreCase);
444+
|| uri.Host.Equals("release-assets.githubusercontent.com", StringComparison.OrdinalIgnoreCase);
494445
}
495446

496447
private static ProductInfoFile SelectInstallerFile(List<ProductInfoFile> files)
@@ -531,11 +482,12 @@ private static string NormalizeThumbprint(string thumbprint) =>
531482
private static UpdaterOverrides LoadUpdaterOverrides()
532483
{
533484
#pragma warning disable CA1416
534-
using RegistryKey? key = Registry.CurrentUser.OpenSubKey(REGISTRY_PATH);
485+
using RegistryKey? key = Registry.LocalMachine.OpenSubKey(REGISTRY_PATH);
535486

487+
#if DEBUG
536488
if (key is not null)
537489
{
538-
Logger.Info($"Updater registry overrides loaded from HKCU\\{REGISTRY_PATH}");
490+
Logger.Info($"Updater registry overrides loaded from HKLM\\{REGISTRY_PATH}");
539491
}
540492

541493
return new UpdaterOverrides(
@@ -544,11 +496,45 @@ private static UpdaterOverrides LoadUpdaterOverrides()
544496
GetRegistryBool(key, REG_ALLOW_UNSAFE_URLS),
545497
GetRegistryBool(key, REG_SKIP_HASH_VALIDATION),
546498
GetRegistryBool(key, REG_SKIP_SIGNER_THUMBPRINT_CHECK),
547-
GetRegistryBool(key, REG_DISABLE_TLS_VALIDATION),
548-
GetRegistryBool(key, REG_USE_LEGACY_GITHUB)
499+
GetRegistryBool(key, REG_DISABLE_TLS_VALIDATION)
500+
);
501+
#else
502+
LogIgnoredReleaseOverrides(key);
503+
string productInfoUrl = GetRegistryString(key, REG_PRODUCTINFO_URL) ?? DEFAULT_PRODUCTINFO_URL;
504+
505+
return new UpdaterOverrides(
506+
productInfoUrl,
507+
DEFAULT_PRODUCTINFO_KEY,
508+
false,
509+
false,
510+
false,
511+
false
549512
);
513+
#endif
514+
#pragma warning restore CA1416
515+
}
516+
517+
#if !DEBUG
518+
private static void LogIgnoredReleaseOverrides(RegistryKey? key)
519+
{
520+
#pragma warning disable CA1416
521+
if (key is null)
522+
{
523+
return;
524+
}
525+
526+
foreach (string valueName in RELEASE_IGNORED_REGISTRY_VALUES)
527+
{
528+
if (key.GetValue(valueName) is not null)
529+
{
530+
Logger.Warn(
531+
$"Release build is ignoring updater registry value HKLM\\{REGISTRY_PATH}\\{valueName}."
532+
);
533+
}
534+
}
550535
#pragma warning restore CA1416
551536
}
537+
#endif
552538

553539
private static string? GetRegistryString(RegistryKey? key, string valueName)
554540
{
@@ -558,6 +544,7 @@ private static UpdaterOverrides LoadUpdaterOverrides()
558544
return string.IsNullOrWhiteSpace(parsed) ? null : parsed.Trim();
559545
}
560546

547+
#if DEBUG
561548
private static bool GetRegistryBool(RegistryKey? key, string valueName)
562549
{
563550
#pragma warning disable CA1416
@@ -572,6 +559,7 @@ private static bool GetRegistryBool(RegistryKey? key, string valueName)
572559
|| s.Equals("yes", StringComparison.OrdinalIgnoreCase)
573560
|| s.Equals("on", StringComparison.OrdinalIgnoreCase);
574561
}
562+
#endif
575563

576564
// ------------------------------------------------------------------ data types
577565
private sealed record UpdateCandidate(
@@ -588,8 +576,7 @@ private sealed record UpdaterOverrides(
588576
bool AllowUnsafeUrls,
589577
bool SkipHashValidation,
590578
bool SkipSignerThumbprintCheck,
591-
bool DisableTlsValidation,
592-
bool UseLegacyGithub
579+
bool DisableTlsValidation
593580
);
594581

595582
private sealed class ProductInfoProduct

0 commit comments

Comments
 (0)