diff --git a/src/Umbraco.Infrastructure/Examine/ExamineIndexRebuilder.cs b/src/Umbraco.Infrastructure/Examine/ExamineIndexRebuilder.cs
index a1c70d0ec3..ced539ebc0 100644
--- a/src/Umbraco.Infrastructure/Examine/ExamineIndexRebuilder.cs
+++ b/src/Umbraco.Infrastructure/Examine/ExamineIndexRebuilder.cs
@@ -66,7 +66,17 @@ public class ExamineIndexRebuilder : IIndexRebuilder
_logger.LogInformation("Starting async background thread for rebuilding index {indexName}.", indexName);
_backgroundTaskQueue.QueueBackgroundWorkItem(
- cancellationToken => Task.Run(() => RebuildIndex(indexName, delay.Value, cancellationToken)));
+ cancellationToken =>
+ {
+ // Do not flow AsyncLocal to the child thread
+ using (ExecutionContext.SuppressFlow())
+ {
+ Task.Run(() => RebuildIndex(indexName, delay.Value, cancellationToken));
+
+ // immediately return so the queue isn't waiting.
+ return Task.CompletedTask;
+ }
+ });
}
else
{
@@ -93,12 +103,16 @@ public class ExamineIndexRebuilder : IIndexRebuilder
_backgroundTaskQueue.QueueBackgroundWorkItem(
cancellationToken =>
{
- // This is a fire/forget task spawned by the background thread queue (which means we
- // don't need to worry about ExecutionContext flowing).
- Task.Run(() => RebuildIndexes(onlyEmptyIndexes, delay.Value, cancellationToken));
+ // Do not flow AsyncLocal to the child thread
+ using (ExecutionContext.SuppressFlow())
+ {
+ // This is a fire/forget task spawned by the background thread queue (which means we
+ // don't need to worry about ExecutionContext flowing).
+ Task.Run(() => RebuildIndexes(onlyEmptyIndexes, delay.Value, cancellationToken));
- // immediately return so the queue isn't waiting.
- return Task.CompletedTask;
+ // immediately return so the queue isn't waiting.
+ return Task.CompletedTask;
+ }
});
}
else
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/CreatedPackageSchemaRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/CreatedPackageSchemaRepository.cs
index 9f921266ca..093fadd8fe 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/CreatedPackageSchemaRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/CreatedPackageSchemaRepository.cs
@@ -266,7 +266,12 @@ public class CreatedPackageSchemaRepository : ICreatedPackagesRepository
definition.Name.Replace(' ', '_')));
Directory.CreateDirectory(directoryName);
+ var expectedRoot = _hostingEnvironment.MapPathContentRoot(_createdPackagesFolderPath);
var finalPackagePath = Path.Combine(directoryName, fileName);
+ if (finalPackagePath.StartsWith(expectedRoot) == false)
+ {
+ throw new IOException("Invalid path due to the package name");
+ }
// Clean existing files
foreach (var packagePath in new[] { definition.PackagePath, finalPackagePath })
diff --git a/src/Umbraco.Web.BackOffice/Controllers/AnalyticsController.cs b/src/Umbraco.Web.BackOffice/Controllers/AnalyticsController.cs
index 1820f2b5e0..b9980308b9 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/AnalyticsController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/AnalyticsController.cs
@@ -1,9 +1,12 @@
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Web.Common.Authorization;
namespace Umbraco.Cms.Web.BackOffice.Controllers;
+[Authorize(Policy = AuthorizationPolicies.SectionAccessSettings)]
public class AnalyticsController : UmbracoAuthorizedJsonController
{
private readonly IMetricsConsentService _metricsConsentService;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
index cce95fd609..89f9c525e6 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs
@@ -404,6 +404,9 @@ public class AuthenticationController : UmbracoApiControllerBase
}
BackOfficeIdentityUser? identityUser = await _userManager.FindByEmailAsync(model.Email);
+
+ await Task.Delay(RandomNumberGenerator.GetInt32(400, 2500)); // To randomize response time preventing user enumeration
+
if (identityUser != null)
{
IUser? user = _userService.GetByEmail(model.Email);
@@ -424,14 +427,20 @@ public class AuthenticationController : UmbracoApiControllerBase
var mailMessage = new EmailMessage(from, user.Email, subject, message, true);
- await _emailSender.SendAsync(mailMessage, Constants.Web.EmailTypes.PasswordReset, true);
+ try
+ {
+ await _emailSender.SendAsync(mailMessage, Constants.Web.EmailTypes.PasswordReset, true);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error sending email, please check your SMTP configuration: {ErrorMessage}", ex.Message);
+ return Ok();
+ }
_userManager.NotifyForgotPasswordRequested(User, user.Id.ToString());
}
}
- await Task.Delay(RandomNumberGenerator.GetInt32(400, 2500));
-
return Ok();
}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs
index 4cb7dc52fc..cef2352ab4 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs
@@ -18,6 +18,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers;
/// Backoffice controller supporting the dashboard for language administration.
///
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
+[Authorize(Policy = AuthorizationPolicies.SectionAccessSettings)]
public class LanguageController : UmbracoAuthorizedJsonController
{
private readonly ILocalizationService _localizationService;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/PublishedSnapshotCacheStatusController.cs b/src/Umbraco.Web.BackOffice/Controllers/PublishedSnapshotCacheStatusController.cs
index c8c391d990..91cd16a0f6 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/PublishedSnapshotCacheStatusController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/PublishedSnapshotCacheStatusController.cs
@@ -1,13 +1,16 @@
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Web.Common.Attributes;
+using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Web.BackOffice.Controllers;
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
+[Authorize(Policy = AuthorizationPolicies.SectionAccessSettings)]
public class PublishedSnapshotCacheStatusController : UmbracoAuthorizedApiController
{
private readonly DistributedCache _distributedCache;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs
index c4d7d47d87..08057d82fa 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs
@@ -2,6 +2,7 @@
// See LICENSE for more details.
using System.Security;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -14,11 +15,13 @@ using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.Attributes;
+using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Web.BackOffice.Controllers;
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
+[Authorize(Policy = AuthorizationPolicies.SectionAccessContent)]
public class RedirectUrlManagementController : UmbracoAuthorizedApiController
{
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
@@ -45,6 +48,8 @@ public class RedirectUrlManagementController : UmbracoAuthorizedApiController
_configManipulator = configManipulator ?? throw new ArgumentNullException(nameof(configManipulator));
}
+ private bool IsEnabled => _webRoutingSettings.CurrentValue.DisableRedirectUrlTracking == false;
+
///
{{vm.errorMsg}}
+{{vm.errorMsg}}