From 4132b7453463aa1334b7ce3463517cadf40c33b8 Mon Sep 17 00:00:00 2001 From: ungrav <11377950+ungrav@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:16:44 -0400 Subject: [PATCH 1/3] fix(security): pin Hugging Face model revisions --- StabilityMatrix.Core/Helper/RemoteModels.cs | 8 +++--- .../Core/RemoteModelsTests.cs | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 StabilityMatrix.Tests/Core/RemoteModelsTests.cs diff --git a/StabilityMatrix.Core/Helper/RemoteModels.cs b/StabilityMatrix.Core/Helper/RemoteModels.cs index 659617646..e7053104b 100644 --- a/StabilityMatrix.Core/Helper/RemoteModels.cs +++ b/StabilityMatrix.Core/Helper/RemoteModels.cs @@ -199,7 +199,7 @@ private static RemoteResource ControlNetCommon(string path, string sha256) [ new() { - Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/main/face_yolov8m.pt"), + Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/b0a075fd35454c86bb453a1ca06b29ffee704c20/face_yolov8m.pt"), HashSha256 = "f02b8a23e6f12bd2c1b1f6714f66f984c728fa41ed749d033e7d6dea511ef70c", InfoUrl = new Uri("https://huggingface.co/Bingsu/adetailer"), Author = "Bingsu", @@ -212,7 +212,7 @@ private static RemoteResource ControlNetCommon(string path, string sha256) }, new() { - Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/main/hand_yolov8s.pt"), + Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/b0a075fd35454c86bb453a1ca06b29ffee704c20/hand_yolov8s.pt"), HashSha256 = "5c4faf8d17286ace2c3d3346c6d0d4a0c8d62404955263a7ae95c1dd7eb877af", InfoUrl = new Uri("https://huggingface.co/Bingsu/adetailer"), Author = "Bingsu", @@ -225,7 +225,7 @@ private static RemoteResource ControlNetCommon(string path, string sha256) }, new() { - Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/main/person_yolov8m-seg.pt"), + Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/b0a075fd35454c86bb453a1ca06b29ffee704c20/person_yolov8m-seg.pt"), HashSha256 = "9d881ec50b831f546e37977081b18f4e3bf65664aec163f97a311b0955499795", InfoUrl = new Uri("https://huggingface.co/Bingsu/adetailer"), Author = "Bingsu", @@ -238,7 +238,7 @@ private static RemoteResource ControlNetCommon(string path, string sha256) }, new() { - Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/main/person_yolov8s-seg.pt"), + Url = new Uri("https://huggingface.co/Bingsu/adetailer/resolve/b0a075fd35454c86bb453a1ca06b29ffee704c20/person_yolov8s-seg.pt"), HashSha256 = "b5684835e79fd8b805459e0f7a0f9daa437e421cb4a214fff45ec4ac61767ef9", InfoUrl = new Uri("https://huggingface.co/Bingsu/adetailer"), Author = "Bingsu", diff --git a/StabilityMatrix.Tests/Core/RemoteModelsTests.cs b/StabilityMatrix.Tests/Core/RemoteModelsTests.cs new file mode 100644 index 000000000..5c3c5080b --- /dev/null +++ b/StabilityMatrix.Tests/Core/RemoteModelsTests.cs @@ -0,0 +1,28 @@ +using StabilityMatrix.Core.Helper; + +namespace StabilityMatrix.Tests.Core; + +public class RemoteModelsTests +{ + [Fact] + public void ExecutableHuggingFaceModelsUsePinnedRevisions() + { + var executableExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) + { + ".bin", + ".ckpt", + ".pt", + ".pth", + }; + + var unpinnedModels = RemoteModels + .UltralyticsModelFiles + .Where(model => model.DownloadableResource?.Url.Host == "huggingface.co") + .Where(model => executableExtensions.Contains(Path.GetExtension(model.DownloadableResource!.Value.Url.AbsolutePath))) + .Where(model => model.DownloadableResource!.Value.Url.AbsolutePath.Contains("/resolve/main/", StringComparison.Ordinal)) + .Select(model => model.DownloadableResource!.Value.Url) + .ToArray(); + + Assert.Empty(unpinnedModels); + } +} From 24e9af919f16535287567079b61abfd46d23d23f Mon Sep 17 00:00:00 2001 From: ungrav <11377950+ungrav@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:33:33 -0400 Subject: [PATCH 2/3] test: cover all remote model collections --- .../Core/RemoteModelsTests.cs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/StabilityMatrix.Tests/Core/RemoteModelsTests.cs b/StabilityMatrix.Tests/Core/RemoteModelsTests.cs index 5c3c5080b..ad98a2f9f 100644 --- a/StabilityMatrix.Tests/Core/RemoteModelsTests.cs +++ b/StabilityMatrix.Tests/Core/RemoteModelsTests.cs @@ -1,4 +1,6 @@ +using System.Reflection; using StabilityMatrix.Core.Helper; +using StabilityMatrix.Core.Models; namespace StabilityMatrix.Tests.Core; @@ -15,12 +17,27 @@ public void ExecutableHuggingFaceModelsUsePinnedRevisions() ".pth", }; - var unpinnedModels = RemoteModels - .UltralyticsModelFiles - .Where(model => model.DownloadableResource?.Url.Host == "huggingface.co") - .Where(model => executableExtensions.Contains(Path.GetExtension(model.DownloadableResource!.Value.Url.AbsolutePath))) - .Where(model => model.DownloadableResource!.Value.Url.AbsolutePath.Contains("/resolve/main/", StringComparison.Ordinal)) - .Select(model => model.DownloadableResource!.Value.Url) + var resources = typeof(RemoteModels) + .GetProperties(BindingFlags.Public | BindingFlags.Static) + .Select(property => property.GetValue(null)) + .SelectMany( + value => + value switch + { + IEnumerable remoteResources => remoteResources, + IEnumerable hybridModels => hybridModels + .Where(model => model.DownloadableResource.HasValue) + .Select(model => model.DownloadableResource!.Value), + HybridModelFile { DownloadableResource: { } resource } => [resource], + _ => [], + } + ); + + var unpinnedModels = resources + .Where(resource => resource.Url.Host == "huggingface.co") + .Where(resource => executableExtensions.Contains(Path.GetExtension(resource.Url.AbsolutePath))) + .Where(resource => resource.Url.AbsolutePath.Contains("/resolve/main/", StringComparison.Ordinal)) + .Select(resource => resource.Url) .ToArray(); Assert.Empty(unpinnedModels); From 81dbe85bbbdae6e031525dd3c917d8b55ead5b8b Mon Sep 17 00:00:00 2001 From: ungrav <11377950+ungrav@users.noreply.github.com> Date: Sat, 18 Jul 2026 20:00:31 -0400 Subject: [PATCH 3/3] test: use MSTest for remote model regression --- StabilityMatrix.Tests/Core/RemoteModelsTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/StabilityMatrix.Tests/Core/RemoteModelsTests.cs b/StabilityMatrix.Tests/Core/RemoteModelsTests.cs index ad98a2f9f..035e1952c 100644 --- a/StabilityMatrix.Tests/Core/RemoteModelsTests.cs +++ b/StabilityMatrix.Tests/Core/RemoteModelsTests.cs @@ -4,9 +4,10 @@ namespace StabilityMatrix.Tests.Core; +[TestClass] public class RemoteModelsTests { - [Fact] + [TestMethod] public void ExecutableHuggingFaceModelsUsePinnedRevisions() { var executableExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) @@ -40,6 +41,10 @@ public void ExecutableHuggingFaceModelsUsePinnedRevisions() .Select(resource => resource.Url) .ToArray(); - Assert.Empty(unpinnedModels); + Assert.AreEqual( + 0, + unpinnedModels.Length, + $"Executable Hugging Face model URLs must use pinned revisions: {string.Join(", ", unpinnedModels.Select(url => url.AbsoluteUri))}" + ); } }