{"record":{"id":"c7231bf9555e6470","repo":"dotnet/machinelearning","slug":"the-function-resourcemanagerutils-ensureresourceas","errorCode":null,"errorMessage":"The function ResourceManagerUtils.EnsureResourceAsync only supports downloading from URLs of the host \"aka.ms\"","messagePattern":"The function ResourceManagerUtils\\.EnsureResourceAsync only supports downloading from URLs of the host \"aka\\.ms\"","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.Core/Utilities/ResourceManagerUtils.cs","lineNumber":120,"sourceCode":"        /// <param name=\"fileName\">The name of the file to save.</param>\n        /// <param name=\"dir\">The directory where the file should be saved to. The file will be saved in a directory with the specified name inside\n        /// a folder called \"mlnet-resources\" in the <see cref=\"Environment.SpecialFolder.ApplicationData\"/> directory.</param>\n        /// <param name=\"timeout\">An integer indicating the number of milliseconds to wait before timing out while downloading a resource.</param>\n        /// <returns>The download results, containing the file path where the resources was (or should have been) downloaded to, and an error message\n        /// (or null if there was no error).</returns>\n        public async Task<ResourceDownloadResults> EnsureResourceAsync(IHostEnvironment env, IChannel ch, string relativeUrl, string fileName, string dir, int timeout)\n        {\n            var filePath = GetFilePath(ch, fileName, dir, out var error);\n            if (File.Exists(filePath) || !string.IsNullOrEmpty(error))\n                return new ResourceDownloadResults(filePath, error);\n\n            if (!Uri.TryCreate(Path.Combine(MlNetResourcesUrl, relativeUrl), UriKind.Absolute, out var absoluteUrl))\n            {\n                return new ResourceDownloadResults(filePath,\n                    $\"Could not create a valid URI from the base URI '{MlNetResourcesUrl}' and the relative URI '{relativeUrl}'\");\n            }\n            if (absoluteUrl.Host != \"aka.ms\")\n                throw new NotSupportedException(\"The function ResourceManagerUtils.EnsureResourceAsync only supports downloading from URLs of the host \\\"aka.ms\\\"\");\n            return new ResourceDownloadResults(filePath,\n                await DownloadFromUrlWithRetryAsync(env, ch, absoluteUrl.AbsoluteUri, fileName, timeout, filePath), absoluteUrl.AbsoluteUri);\n        }\n\n        private async Task<string> DownloadFromUrlWithRetryAsync(IHostEnvironment env, IChannel ch, string url, string fileName,\n            int timeout, string filePath, int retryTimes = 5)\n        {\n            var downloadResult = \"\";\n\n            for (int i = 0; i < retryTimes; ++i)\n            {\n                try\n                {\n                    var thisDownloadResult = await DownloadFromUrlAsync(env, ch, url, fileName, timeout, filePath);\n\n                    if (string.IsNullOrEmpty(thisDownloadResult))\n                        return thisDownloadResult;\n                    else","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.Core/Utilities/ResourceManagerUtils.cs#L102-L138","documentation":"ResourceManagerUtils.EnsureResourceAsync downloads ML.NET resources (e.g. image-model pretrained models) from a known base URL, then only permits downloads whose resolved absolute host is exactly \"aka.ms\". Any other host throws NotSupportedException because Microsoft restricts this code path to its own trusted short-link domain, both for security (avoiding arbitrary downloads) and licensing. This is an intentional allowlist, not a bug.","triggerScenarios":"Calling ResourceManagerUtils.EnsureResourceAsync with a relativeUrl that resolves against MlNetResourcesUrl to a non-aka.ms host (e.g. after MlNetResourcesUrl was redirected, overridden for testing, or the relative path escaped the aka.ms domain via '../' segments).","commonSituations":"Enterprise environments redirecting aka.ms through a proxy/mirror domain; developers pointing the resource manager at a custom mirror to work offline; test setups substituting a local base URL; DNS/CDN changes causing aka.ms short links to resolve under a different host string.","solutions":["Use only URLs whose final absolute host is \"aka.ms\"; revert any customization of the resources base URL to the default Microsoft endpoint.","If you need resources from another host, download the file yourself (e.g. with HttpClient) and register/place it in the expected local cache path instead of using EnsureResourceAsync.","Check the composed URL: combine MlNetResourcesUrl with relativeUrl using Uri.TryCreate and inspect .Host before calling, so you know what the method will see."],"exampleFix":"// before\nvar results = await ResourceManagerUtils.Instance.EnsureResourceAsync(env, ch,\n    \"https://example.com/models/model.res\", \"model.res\", timeout);\n// after\nif (new Uri(modelUrl).Host == \"aka.ms\")\n{\n    var results = await ResourceManagerUtils.Instance.EnsureResourceAsync(env, ch,\n        modelUrl, \"model.res\", timeout);\n}\nelse\n{\n    // download manually and place the file in the expected cache location\n    await DownloadToCacheAsync(modelUrl, cachePath);\n}","handlingStrategy":"validation","validationCode":"if (Uri.TryCreate(Path.Combine(MlNetResourcesUrl, relativeUrl), UriKind.Absolute, out var abs)\n    && abs.Host == \"aka.ms\")\n{\n    await ResourceManagerUtils.Instance.EnsureResourceAsync(env, ch, relativeUrl, fileName, timeout);\n}","typeGuard":"static bool IsAllowedResourceUrl(Uri url) => url?.Host == \"aka.ms\";","tryCatchPattern":"try\n{\n    await ResourceManagerUtils.Instance.EnsureResourceAsync(env, ch, relativeUrl, fileName, timeout);\n}\ncatch (NotSupportedException ex)\n{\n    // non-aka.ms host: fall back to manual download or surface config error\n}","preventionTips":["Do not override the resource base URL in production.","Pre-resolve the composed URL and check Host before downloading.","Download third-party resources manually instead of routing them through this method."],"tags":["not-supported","resource-download","url-host","ml-net"],"backgroundTag":"unsupported-operation","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}