Moderate severityNVD Advisory· Published May 21, 2024· Updated Aug 2, 2024
Umbraco CMS Vulnerable to Stored XSS on Content Page Through Markdown Editor Preview Pane
CVE-2024-35218
Description
Umbraco CMS is an ASP.NET CMS used by more than 730.000 websites. Stored Cross-site scripting (XSS) enable attackers that have access to backoffice to bring malicious content into a website or application. This vulnerability has been patched in version(s) 8.18.13, 10.8.4, 12.3.7, 13.1.1 by implementing IHtmlSanitizer.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
UmbracoCms.CoreNuGet | >= 8.0.0, < 8.18.13 | 8.18.13 |
UmbracoCms.CoreNuGet | >= 10.0.0, < 10.8.4 | 10.8.4 |
UmbracoCms.CoreNuGet | >= 12.0.0, < 12.3.7 | 12.3.7 |
UmbracoCms.CoreNuGet | >= 13.0.0, < 13.1.1 | 13.1.1 |
Affected products
1- Range: >= 8.0.0, < 8.18.13
Patches
41b712fe6ec52Merge pull request from GHSA-gvpc-3pj6-4m9w
5 files changed · +71 −1
src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs+2 −1 modified@@ -317,8 +317,9 @@ private void AddCoreServices() Services.AddSingleton<ConflictingPackageData>(); Services.AddSingleton<CompiledPackageXmlParser>(); - // Register a noop IHtmlSanitizer to be replaced + // Register a noop IHtmlSanitizer & IMarkdownSanitizer to be replaced Services.AddUnique<IHtmlSanitizer, NoopHtmlSanitizer>(); + Services.AddUnique<IMarkdownSanitizer, NoopMarkdownSanitizer>(); Services.AddUnique<IPropertyTypeUsageService, PropertyTypeUsageService>(); Services.AddUnique<IDataTypeUsageService, DataTypeUsageService>();
src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs+8 −0 modified@@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Core.PropertyEditors; @@ -50,4 +51,11 @@ public MarkdownPropertyEditor( /// <inheritdoc /> protected override IConfigurationEditor CreateConfigurationEditor() => new MarkdownConfigurationEditor(_ioHelper, _editorConfigurationParser); + + /// <summary> + /// Create a custom value editor + /// </summary> + /// <returns></returns> + protected override IDataValueEditor CreateValueEditor() => + DataValueEditorFactory.Create<MarkDownPropertyValueEditor>(Attribute!); }
src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs+39 −0 added@@ -0,0 +1,39 @@ +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models.Editors; +using Umbraco.Cms.Core.Security; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Strings; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Core.PropertyEditors; + +/// <summary> +/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for +/// display in the editor +/// </summary> +internal class MarkDownPropertyValueEditor : DataValueEditor +{ + private readonly IMarkdownSanitizer _markdownSanitizer; + + public MarkDownPropertyValueEditor( + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + IIOHelper ioHelper, + DataEditorAttribute attribute, + IMarkdownSanitizer markdownSanitizer) + : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) => _markdownSanitizer = markdownSanitizer; + + public override object? FromEditor(ContentPropertyData editorValue, object? currentValue) + { + if (string.IsNullOrWhiteSpace(editorValue.Value?.ToString())) + { + return null; + } + + var sanitized = _markdownSanitizer.Sanitize(editorValue.Value.ToString()!); + + return sanitized.NullOrWhiteSpaceAsNull(); + } +}
src/Umbraco.Core/Security/IMarkdownSanitizer.cs+14 −0 added@@ -0,0 +1,14 @@ +namespace Umbraco.Cms.Core.Security; + +/// <summary> +/// Sanitizer service for the markdown editor. +/// </summary> +public interface IMarkdownSanitizer +{ + /// <summary> + /// Sanitizes Markdown + /// </summary> + /// <param name="markdown">Markdown to be sanitized</param> + /// <returns>Sanitized Markdown</returns> + string Sanitize(string markdown); +}
src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs+8 −0 added@@ -0,0 +1,8 @@ +namespace Umbraco.Cms.Core.Security; + +/// <inheritdoc /> +public class NoopMarkdownSanitizer : IMarkdownSanitizer +{ + /// <inheritdoc /> + public string Sanitize(string markdown) => markdown; +}
a2684069b1e9Merge pull request from GHSA-gvpc-3pj6-4m9w
7 files changed · +70 −2
src/Umbraco.Core/Composing/CompositionExtensions/Services.cs+1 −0 modified@@ -83,6 +83,7 @@ public static Composition ComposeServices(this Composition composition) composition.RegisterUnique<ITelemetryService, TelemetryService>(); composition.RegisterUnique<IHtmlSanitizer, NoopHtmlSanitizer>(); + composition.RegisterUnique<IMarkdownSanitizer, NoopMarkdownSanitizer>(); composition.RegisterUnique<IFileStreamSecurityValidator, FileStreamSecurityValidator>(); return composition;
src/Umbraco.Core/Security/IMarkdownSanitizer.cs+14 −0 added@@ -0,0 +1,14 @@ +namespace Umbraco.Core.Security +{ + public interface IMarkdownSanitizer + { + /// <summary> + /// Sanitizes Markdown + /// </summary> + /// <param name="markdown">Markdown to be sanitized</param> + /// <returns>Sanitized Markdown</returns> + string Sanitize(string markdown); + } +} + +
src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs+10 −0 added@@ -0,0 +1,10 @@ +namespace Umbraco.Core.Security +{ + public class NoopMarkdownSanitizer : IMarkdownSanitizer + { + public string Sanitize(string markdown) + { + return markdown; + } + } +}
src/Umbraco.Core/Umbraco.Core.csproj+2 −0 modified@@ -201,7 +201,9 @@ <Compile Include="Security\IFileStreamSecurityAnalyzer.cs" /> <Compile Include="Security\IFileStreamSecurityValidator.cs" /> <Compile Include="Security\IHtmlSanitizer.cs" /> + <Compile Include="Security\IMarkdownSanitizer.cs" /> <Compile Include="Security\NoopHtmlSanitizer.cs" /> + <Compile Include="Security\NoopMarkdownSanitizer.cs" /> <Compile Include="Serialization\AutoInterningStringConverter.cs" /> <Compile Include="Serialization\AutoInterningStringKeyCaseInsensitiveDictionaryConverter.cs" /> <Compile Include="PropertyEditors\EyeDropperColorPickerConfiguration.cs" />
src/Umbraco.Web/PropertyEditors/MarkdownPropertyEditor.cs+13 −2 modified@@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; namespace Umbraco.Web.PropertyEditors { @@ -16,14 +17,24 @@ namespace Umbraco.Web.PropertyEditors Icon = "icon-code")] public class MarkdownPropertyEditor : DataEditor { + private readonly IMarkdownSanitizer _markdownSanitizer; + /// <summary> /// Initializes a new instance of the <see cref="MarkdownPropertyEditor"/> class. /// </summary> - public MarkdownPropertyEditor(ILogger logger) + public MarkdownPropertyEditor(ILogger logger, IMarkdownSanitizer markdownSanitizer) : base(logger) - { } + { + _markdownSanitizer = markdownSanitizer; + } /// <inheritdoc /> protected override IConfigurationEditor CreateConfigurationEditor() => new MarkdownConfigurationEditor(); + + /// <summary> + /// Create a custom value editor + /// </summary> + /// <returns></returns> + protected override IDataValueEditor CreateValueEditor() => new MarkDownPropertyValueEditor(Attribute, _markdownSanitizer); } }
src/Umbraco.Web/PropertyEditors/MarkDownPropertyValueEditor.cs+29 −0 added@@ -0,0 +1,29 @@ +using Umbraco.Core; +using Umbraco.Core.Models.Editors; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Security; + +namespace Umbraco.Web.PropertyEditors; + +internal class MarkDownPropertyValueEditor : DataValueEditor +{ + private readonly IMarkdownSanitizer _markdownSanitizer; + + public MarkDownPropertyValueEditor(DataEditorAttribute attribute, IMarkdownSanitizer markdownSanitizer) : base(attribute) + { + _markdownSanitizer = markdownSanitizer; + } + + public override object FromEditor(ContentPropertyData editorValue, object currentValue) + { + var editorValueString = editorValue.Value?.ToString(); + if (string.IsNullOrWhiteSpace(editorValueString)) + { + return null; + } + + var sanitized = _markdownSanitizer.Sanitize(editorValueString); + + return sanitized.NullOrWhiteSpaceAsNull(); + } +}
src/Umbraco.Web/Umbraco.Web.csproj+1 −0 modified@@ -288,6 +288,7 @@ <Compile Include="PropertyEditors\ComplexEditorValidator.cs" /> <Compile Include="PropertyEditors\FileUploadConfiguration.cs" /> <Compile Include="PropertyEditors\FileUploadConfigurationEditor.cs" /> + <Compile Include="PropertyEditors\MarkDownPropertyValueEditor.cs" /> <Compile Include="PropertyEditors\MediaPicker3Configuration.cs" /> <Compile Include="PropertyEditors\MediaPicker3ConfigurationEditor.cs" /> <Compile Include="PropertyEditors\MediaPicker3PropertyEditor.cs" />
cbf9f9bcd199Merge pull request from GHSA-gvpc-3pj6-4m9w
5 files changed · +71 −1
src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs+2 −1 modified@@ -318,8 +318,9 @@ private void AddCoreServices() Services.AddSingleton<ConflictingPackageData>(); Services.AddSingleton<CompiledPackageXmlParser>(); - // Register a noop IHtmlSanitizer to be replaced + // Register a noop IHtmlSanitizer & IMarkdownSanitizer to be replaced Services.AddUnique<IHtmlSanitizer, NoopHtmlSanitizer>(); + Services.AddUnique<IMarkdownSanitizer, NoopMarkdownSanitizer>(); Services.AddUnique<IPropertyTypeUsageService, PropertyTypeUsageService>(); Services.AddUnique<IDataTypeUsageService, DataTypeUsageService>();
src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs+8 −0 modified@@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Web.Common.DependencyInjection; @@ -50,4 +51,11 @@ public MarkdownPropertyEditor( /// <inheritdoc /> protected override IConfigurationEditor CreateConfigurationEditor() => new MarkdownConfigurationEditor(_ioHelper, _editorConfigurationParser); + + /// <summary> + /// Create a custom value editor + /// </summary> + /// <returns></returns> + protected override IDataValueEditor CreateValueEditor() => + DataValueEditorFactory.Create<MarkDownPropertyValueEditor>(Attribute!); }
src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs+39 −0 added@@ -0,0 +1,39 @@ +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models.Editors; +using Umbraco.Cms.Core.Security; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Strings; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Core.PropertyEditors; + +/// <summary> +/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for +/// display in the editor +/// </summary> +internal class MarkDownPropertyValueEditor : DataValueEditor +{ + private readonly IMarkdownSanitizer _markdownSanitizer; + + public MarkDownPropertyValueEditor( + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + IIOHelper ioHelper, + DataEditorAttribute attribute, + IMarkdownSanitizer markdownSanitizer) + : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) => _markdownSanitizer = markdownSanitizer; + + public override object? FromEditor(ContentPropertyData editorValue, object? currentValue) + { + if (string.IsNullOrWhiteSpace(editorValue.Value?.ToString())) + { + return null; + } + + var sanitized = _markdownSanitizer.Sanitize(editorValue.Value.ToString()!); + + return sanitized.NullOrWhiteSpaceAsNull(); + } +}
src/Umbraco.Core/Security/IMarkdownSanitizer.cs+14 −0 added@@ -0,0 +1,14 @@ +namespace Umbraco.Cms.Core.Security; + +/// <summary> +/// Sanitizer service for the markdown editor. +/// </summary> +public interface IMarkdownSanitizer +{ + /// <summary> + /// Sanitizes Markdown + /// </summary> + /// <param name="markdown">Markdown to be sanitized</param> + /// <returns>Sanitized Markdown</returns> + string Sanitize(string markdown); +}
src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs+8 −0 added@@ -0,0 +1,8 @@ +namespace Umbraco.Cms.Core.Security; + +/// <inheritdoc /> +public class NoopMarkdownSanitizer : IMarkdownSanitizer +{ + /// <inheritdoc /> + public string Sanitize(string markdown) => markdown; +}
d090176272d0Merge pull request from GHSA-gvpc-3pj6-4m9w
5 files changed · +71 −1
src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs+2 −1 modified@@ -317,8 +317,9 @@ private void AddCoreServices() Services.AddSingleton<ConflictingPackageData>(); Services.AddSingleton<CompiledPackageXmlParser>(); - // Register a noop IHtmlSanitizer to be replaced + // Register a noop IHtmlSanitizer & IMarkdownSanitizer to be replaced Services.AddUnique<IHtmlSanitizer, NoopHtmlSanitizer>(); + Services.AddUnique<IMarkdownSanitizer, NoopMarkdownSanitizer>(); Services.AddUnique<IPropertyTypeUsageService, PropertyTypeUsageService>(); Services.AddUnique<IDataTypeUsageService, DataTypeUsageService>();
src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs+8 −0 modified@@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Core.PropertyEditors; @@ -50,4 +51,11 @@ public MarkdownPropertyEditor( /// <inheritdoc /> protected override IConfigurationEditor CreateConfigurationEditor() => new MarkdownConfigurationEditor(_ioHelper, _editorConfigurationParser); + + /// <summary> + /// Create a custom value editor + /// </summary> + /// <returns></returns> + protected override IDataValueEditor CreateValueEditor() => + DataValueEditorFactory.Create<MarkDownPropertyValueEditor>(Attribute!); }
src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs+39 −0 added@@ -0,0 +1,39 @@ +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Models.Editors; +using Umbraco.Cms.Core.Security; +using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Strings; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Core.PropertyEditors; + +/// <summary> +/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for +/// display in the editor +/// </summary> +internal class MarkDownPropertyValueEditor : DataValueEditor +{ + private readonly IMarkdownSanitizer _markdownSanitizer; + + public MarkDownPropertyValueEditor( + ILocalizedTextService localizedTextService, + IShortStringHelper shortStringHelper, + IJsonSerializer jsonSerializer, + IIOHelper ioHelper, + DataEditorAttribute attribute, + IMarkdownSanitizer markdownSanitizer) + : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute) => _markdownSanitizer = markdownSanitizer; + + public override object? FromEditor(ContentPropertyData editorValue, object? currentValue) + { + if (string.IsNullOrWhiteSpace(editorValue.Value?.ToString())) + { + return null; + } + + var sanitized = _markdownSanitizer.Sanitize(editorValue.Value.ToString()!); + + return sanitized.NullOrWhiteSpaceAsNull(); + } +}
src/Umbraco.Core/Security/IMarkdownSanitizer.cs+14 −0 added@@ -0,0 +1,14 @@ +namespace Umbraco.Cms.Core.Security; + +/// <summary> +/// Sanitizer service for the markdown editor. +/// </summary> +public interface IMarkdownSanitizer +{ + /// <summary> + /// Sanitizes Markdown + /// </summary> + /// <param name="markdown">Markdown to be sanitized</param> + /// <returns>Sanitized Markdown</returns> + string Sanitize(string markdown); +}
src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs+8 −0 added@@ -0,0 +1,8 @@ +namespace Umbraco.Cms.Core.Security; + +/// <inheritdoc /> +public class NoopMarkdownSanitizer : IMarkdownSanitizer +{ + /// <inheritdoc /> + public string Sanitize(string markdown) => markdown; +}
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-gvpc-3pj6-4m9wghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-35218ghsaADVISORY
- github.com/umbraco/Umbraco-CMS/commit/1b712fe6ec52aa4e71b3acf63e393c8e6ab85385ghsax_refsource_MISCWEB
- github.com/umbraco/Umbraco-CMS/commit/a2684069b1e9976444f60b4b37a80be05b87f6b6ghsax_refsource_MISCWEB
- github.com/umbraco/Umbraco-CMS/commit/cbf9f9bcd199d7ca0412be3071d275556f10b7baghsax_refsource_MISCWEB
- github.com/umbraco/Umbraco-CMS/commit/d090176272d07500dac0daee7c598aa8bb321050ghsax_refsource_MISCWEB
- github.com/umbraco/Umbraco-CMS/security/advisories/GHSA-gvpc-3pj6-4m9wghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.