CVE-2024-35218: Insufficient Information (NVD-CWE-noinfo)
value: 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.





CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-05-21T14:15Z
Repository: https://github.com/umbraco/Umbraco-CMS
Language: C#
Files changed: src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs, src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs, src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs, src/Umbraco.Core/Security/IMarkdownSanitizer.cs, src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs
Commit date: 2024-02-06 09:53:40 +0100
Commit message: Merge pull request from GHSA-gvpc-3pj6-4m9w

* Add MarkDownPropertyValueEditor with html sanitizer

* Implement IMarkdownSanitizer.
Diff: diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
index 098f770ebc75..cf44114c19e9 100644
--- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
+++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
@@ -315,12 +315,13 @@ private void AddCoreServices()
             Services.AddUnique<IEntityXmlSerializer, EntityXmlSerializer>();
 
             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>();
 
             Services.AddUnique<ICultureImpactFactory>(provider => new CultureImpactFactory(provider.GetRequiredService<IOptionsMonitor<ContentSettings>>()));
diff --git a/src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs
new file mode 100644
index 000000000000..637a971d6836
--- /dev/null
+++ b/src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs
@@ -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();
+    }
+}
diff --git a/src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs
index 8b1b181c8cad..531262f0b2f3 100644
--- a/src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/MarkdownPropertyEditor.cs
@@ -2,10 +2,11 @@
 // See LICENSE for more details.
 
 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;
 
 /// <summary>
@@ -48,6 +49,13 @@ public class MarkdownPropertyEditor : DataEditor
     }
 
     /// <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!);
 }
diff --git a/src/Umbraco.Core/Security/IMarkdownSanitizer.cs b/src/Umbraco.Core/Security/IMarkdownSanitizer.cs
new file mode 100644
index 000000000000..ed1fed2a2cc9
--- /dev/null
+++ b/src/Umbraco.Core/Security/IMarkdownSanitizer.cs
@@ -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);
+}
diff --git a/src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs b/src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs
new file mode 100644
index 000000000000..3da03b0e6374
--- /dev/null
+++ b/src/Umbraco.Core/Security/NoopMarkdownSanitizer.cs
@@ -0,0 +1,8 @@
+﻿namespace Umbraco.Cms.Core.Security;
+
+/// <inheritdoc />
+public class NoopMarkdownSanitizer : IMarkdownSanitizer
+{
+    /// <inheritdoc />
+    public string Sanitize(string markdown) => markdown;
+}

Vulnerable code:             // Register a noop IHtmlSanitizer to be replaced
Fixed code:             // Register a noop IHtmlSanitizer & IMarkdownSanitizer to be replaced
            Services.AddUnique<IMarkdownSanitizer, NoopMarkdownSanitizer>();
﻿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();
    }
}
using Umbraco.Cms.Core.Models;

    /// <summary>
    ///     Create a custom value editor
    /// </summary>
    /// <returns></returns>
    protected override IDataValueEditor CreateValueEditor() =>
        DataValueEditorFactory.Create<MarkDownPropertyValueEditor>(Attribute!);
﻿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);
}
﻿namespace Umbraco.Cms.Core.Security;

/// <inheritdoc />
public class NoopMarkdownSanitizer : IMarkdownSanitizer
{
    /// <inheritdoc />
    public string Sanitize(string markdown) => markdown;
}