Skip to content

Style attribute triggers a RemovingAttribute Event with an empty value #504

@florianculie

Description

@florianculie

Hi,

We are using the HtmlSanitizer 8.0.746 release to filter user input. To be precise, we do not sanitize it, we forbid the user to write the data if HtmlSanitizer triggers a RemovingN event.

We are having problems regarding the following HTML string :

<p style="text-align: start;">this is the content of the p tag</p>

We have a custom RemovingAttributeEvent that we are adding like this :

private void InitSanitizerEvents()
{
    // We adapt all the following events to set the IsValid variable to false if one of them trigger.
    // We also log the error message according to what was detected.
    _sanitizer.RemovingTag += RemovingTagEvent;
    _sanitizer.RemovingAtRule += RemovingAtRuleEvent;
    _sanitizer.RemovingStyle += RemovingStyleEvent;
    _sanitizer.RemovingAttribute += RemovingAttributeEvent;
    _sanitizer.RemovingComment += RemovingCommentEvent;
    _sanitizer.RemovingCssClass += RemovingCssClassEvent;
}

The code of our custom event is the following :

private void RemovingAttributeEvent(object sender, RemovingAttributeEventArgs args)
{
    string attName = args.Attribute.Name;
    string attValue = args.Attribute.Value;

    // Check if this is an event with allowed values, and if the value is allowed.
    if (_allowedEvents.TryGetValue(attName, out ISet<string> allowedValues))
    {
        if (allowedValues.Contains(attValue))
            args.Cancel = true;
    }
    else
    {
        // Handle specific cases in a switch
        switch (attName)
        {
            // We need this case as the 'class' attribute trigger this event, but we don't want to treat it here
            case "class":
                args.Cancel = true;
                break;
            case "src":
                if (attValue.StartsWith("data:image/", StringComparison.Ordinal))
                    args.Cancel = true;
                else
                    OnUnauthorizedLinkError(attValue);

                break;
            case "href":
                if (attValue.StartsWith("mailto:", StringComparison.Ordinal))
                {
                    try
                    {
                        var providedEmail = attValue.Split(':')[1];
                        var email = new System.Net.Mail.MailAddress(providedEmail);

                        args.Cancel = email.Address.Equals(providedEmail, StringComparison.Ordinal);
                    }
                    catch (Exception ex) when (ex is ArgumentException || ex is FormatException)
                    {/* error in parsing value means that email is invalid, which leads to security error. */}
                }
                else
                    OnUnauthorizedLinkError(attValue);

                break;
        }
    }

    if (!args.Cancel)
    {
        _isRichTextValid = false;
        _errors.Add(new CssAttributeError(args.Reason.ToString(), args.Tag.TagName, attName));
    }
}

To put it simply, base on the logic I described at the begining, we cancel the RemovingAttribute Event if the reason for the trigger is considered safe for us, otherwise we confirm the trigger, and we add the reason to the _error object to log all reasons.

The problem we are facing is the fact that the event is being triggered with an "incomplete" html, as you can see below :
image
Which gives us an args.Attribute.Name = "style" but an empty value for the actual style.

During the investigation of the issue, I did notice we were using the 6.0 version of your package, and by updating to 8.0, I still reproduce it. On a side note, we have been using your package for 6 year now, and we do not reproduce this issue with the 4.0.183 version, the version being used in an old version of our software.

Do you happen to have any idea if this is a normal behaviour or a bug ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions