From 61405d30cf3e20b5a98d99b8c41aecbc98d7204d Mon Sep 17 00:00:00 2001 From: maliming Date: Sun, 28 Dec 2025 15:47:44 +0800 Subject: [PATCH] HTML-encode TagHelper titles and texts for security --- .../Breadcrumb/AbpBreadcrumbItemTagHelperService.cs | 2 +- .../TagHelpers/Button/AbpButtonTagHelperService.cs | 4 +++- .../Button/AbpButtonTagHelperServiceBase.cs | 10 +++++++++- .../Button/AbpLinkButtonTagHelperService.cs | 7 +++++++ .../TagHelpers/Card/AbpCardBodyTagHelperService.cs | 12 ++++++++++-- .../Carousel/AbpCarouselItemTagHelperService.cs | 4 ++-- .../Collapse/AbpAccordionItemTagHelperService.cs | 10 +++++++++- .../TagHelpers/Form/AbpRadioInputTagHelperService.cs | 7 +++++-- .../Modal/AbpModalHeaderTagHelperService.cs | 9 ++++++--- .../TagHelpers/Tab/AbpTabDropdownTagHelperService.cs | 10 +++++++++- .../TagHelpers/Tab/AbpTabLinkTagHelperService.cs | 12 ++++++++++-- .../TagHelpers/Tab/AbpTabTagHelperService.cs | 12 ++++++++++-- .../Bundling/TagHelpers/AbpTagHelperScriptService.cs | 8 ++++---- .../Bundling/TagHelpers/AbpTagHelperStyleService.cs | 7 +++++-- 14 files changed, 90 insertions(+), 24 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs index 9935b90903..3208d1c7a0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs @@ -46,7 +46,7 @@ public class AbpBreadcrumbItemTagHelperService : AbpTagHelperService L { get; } - public AbpButtonTagHelperService(IStringLocalizer localizer) + public AbpButtonTagHelperService(HtmlEncoder encoder, IStringLocalizer localizer) + : base(encoder) { L = localizer; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs index a69d09eed4..dff0d8c2cb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; using System; +using System.Text.Encodings.Web; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; @@ -8,6 +9,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; public abstract class AbpButtonTagHelperServiceBase : AbpTagHelperService where TTagHelper : TagHelper, IButtonTagHelperBase { + protected HtmlEncoder Encoder { get; } + + protected AbpButtonTagHelperServiceBase(HtmlEncoder encoder) + { + Encoder = encoder; + } + public override void Process(TagHelperContext context, TagHelperOutput output) { NormalizeTagMode(context, output); @@ -69,7 +77,7 @@ public abstract class AbpButtonTagHelperServiceBase : AbpTagHelperSe } var span = new TagBuilder("span"); - span.InnerHtml.AppendHtml(TagHelper.Text!); + span.InnerHtml.AppendHtml(Encoder.Encode(TagHelper.Text!)); output.Content.AppendHtml(span); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs index 44dc996284..295e914d4a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpLinkButtonTagHelperService.cs @@ -1,10 +1,17 @@ using System; +using System.Text.Encodings.Web; using Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; public class AbpLinkButtonTagHelperService : AbpButtonTagHelperServiceBase { + public AbpLinkButtonTagHelperService(HtmlEncoder encoder) + : base(encoder) + { + + } + public override void Process(TagHelperContext context, TagHelperOutput output) { base.Process(context, output); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs index b8462f4b5b..5907097d25 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Card/AbpCardBodyTagHelperService.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Encodings.Web; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; @@ -7,6 +8,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; public class AbpCardBodyTagHelperService : AbpTagHelperService { + protected HtmlEncoder Encoder { get; } + + public AbpCardBodyTagHelperService(HtmlEncoder encoder) + { + Encoder = encoder; + } + public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; @@ -22,7 +30,7 @@ public class AbpCardBodyTagHelperService : AbpTagHelperService { + protected HtmlEncoder Encoder { get; } + + public AbpAccordionItemTagHelperService(HtmlEncoder encoder) + { + Encoder = encoder; + } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { SetRandomIdIfNotProvided(); @@ -32,7 +40,7 @@ public class AbpAccordionItemTagHelperService : AbpTagHelperService { private readonly IAbpTagHelperLocalizer _tagHelperLocalizer; + private readonly HtmlEncoder _htmlEncoder ; - public AbpRadioInputTagHelperService(IAbpTagHelperLocalizer tagHelperLocalizer) + public AbpRadioInputTagHelperService(IAbpTagHelperLocalizer tagHelperLocalizer, HtmlEncoder htmlEncoder) { _tagHelperLocalizer = tagHelperLocalizer; + _htmlEncoder = htmlEncoder; } public override void Process(TagHelperContext context, TagHelperOutput output) @@ -74,7 +77,7 @@ public class AbpRadioInputTagHelperService : AbpTagHelperService { protected IStringLocalizer L { get; } + protected HtmlEncoder Encoder { get; } - public AbpModalHeaderTagHelperService(IStringLocalizer localizer) + public AbpModalHeaderTagHelperService(IStringLocalizer localizer, HtmlEncoder encoder) { L = localizer; + Encoder = encoder; } public override void Process(TagHelperContext context, TagHelperOutput output) @@ -27,7 +30,7 @@ public class AbpModalHeaderTagHelperService : AbpTagHelperService { + protected HtmlEncoder Encoder { get; } + + public AbpTabDropdownTagHelperService(HtmlEncoder encoder) + { + Encoder = encoder; + } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { if (string.IsNullOrWhiteSpace(TagHelper.Name)) @@ -40,7 +48,7 @@ public class AbpTabDropdownTagHelperService : AbpTagHelperService { + protected HtmlEncoder Encoder { get; } + + public AbpTabLinkTagHelperService(HtmlEncoder encoder) + { + Encoder = encoder; + } + public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { SetPlaceholderForNameIfNotProvided(); @@ -35,7 +43,7 @@ public class AbpTabLinkTagHelperService : AbpTagHelperService { + protected HtmlEncoder Encoder { get; } + + public AbpTabTagHelperService(HtmlEncoder encoder) + { + Encoder = encoder; + } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { SetPlaceholderForNameIfNotProvided(); @@ -53,7 +61,7 @@ public class AbpTabTagHelperService : AbpTagHelperService anchor.Attributes.Add(attr.Name, attr.Value.ToString()); } - anchor.InnerHtml.AppendHtml(title); + anchor.InnerHtml.AppendHtml(Encoder.Encode(title)); return anchor.ToHtmlString(); } @@ -73,7 +81,7 @@ public class AbpTabTagHelperService : AbpTagHelperService anchor.Attributes.Add(attr.Name, attr.Value.ToString()); } - anchor.InnerHtml.AppendHtml(title); + anchor.InnerHtml.AppendHtml(Encoder.Encode(title)); var listItem = new TagBuilder("li"); listItem.AddCssClass("nav-item"); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs index c4701aa7d5..17cf42c189 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Rendering; @@ -18,10 +19,9 @@ public class AbpTagHelperScriptService : AbpTagHelperResourceService public AbpTagHelperScriptService( IBundleManager bundleManager, IOptions options, - IWebHostEnvironment hostingEnvironment) : base( - bundleManager, - options, - hostingEnvironment) + IWebHostEnvironment hostingEnvironment, + HtmlEncoder encoder) + : base(bundleManager, options, hostingEnvironment, encoder) { } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs index 1ed3a76fe1..f398edaa99 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Rendering; @@ -21,10 +22,12 @@ public class AbpTagHelperStyleService : AbpTagHelperResourceService IBundleManager bundleManager, IOptions options, IWebHostEnvironment hostingEnvironment, - IOptions securityHeadersOptions) : base( + IOptions securityHeadersOptions, + HtmlEncoder encoder) : base( bundleManager, options, - hostingEnvironment) + hostingEnvironment, + encoder) { SecurityHeadersOptions = securityHeadersOptions.Value; }