Skip to content

Commit 6d28ce2

Browse files
Merge pull request #72 from drpeck/patch-1
A malformed SVG can tank the entire page
2 parents be63b4f + 3a547d7 commit 6d28ce2

File tree

2 files changed

+40
-25
lines changed

2 files changed

+40
-25
lines changed

Our.Umbraco.TagHelpers.Tests/InlineSvgTagHelperTests.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.AspNetCore.Hosting;
22
using Microsoft.AspNetCore.Razor.TagHelpers;
33
using Microsoft.Extensions.FileProviders;
4+
using Microsoft.Extensions.Logging;
45
using Microsoft.Extensions.Options;
56
using Moq;
67
using NUnit.Framework;
@@ -56,7 +57,7 @@ public void Setup()
5657
public void NoOutputIfNoMediaOrFileSet()
5758
{
5859

59-
var tagHelper = new InlineSvgTagHelper(null, null, null, _settings, null);
60+
var tagHelper = new InlineSvgTagHelper(null, null, null, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>());
6061

6162
tagHelper.Process(_context, _output);
6263

@@ -67,7 +68,7 @@ public void NoOutputIfNoMediaOrFileSet()
6768
public void NoOutputIfBothMediaAndFileSet()
6869
{
6970
var umbContent = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media);
70-
var tagHelper = new InlineSvgTagHelper(null, null, null, _settings, null)
71+
var tagHelper = new InlineSvgTagHelper(null, null, null, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>())
7172
{
7273
FileSource = "test.svg",
7374
MediaItem = umbContent
@@ -81,7 +82,7 @@ public void NoOutputIfBothMediaAndFileSet()
8182
[Test]
8283
public void NoOutputIfFileNotSvg()
8384
{
84-
var tagHelper = new InlineSvgTagHelper(null, null, null, _settings, null)
85+
var tagHelper = new InlineSvgTagHelper(null, null, null, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>())
8586
{
8687
FileSource = "test.notsvg"
8788
};
@@ -97,7 +98,7 @@ public void NoOutputIfFileNotFound()
9798
var fileProvider = new Mock<IFileProvider>();
9899
fileProvider.Setup(p => p.GetFileInfo(It.IsAny<string>())).Returns(Mock.Of<IFileInfo>(f => !f.Exists));
99100
var hostEnv = Mock.Of<IWebHostEnvironment>(e => e.WebRootFileProvider == fileProvider.Object);
100-
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null, _settings, null)
101+
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>())
101102
{
102103
FileSource = "test.svg"
103104
};
@@ -113,7 +114,7 @@ public void ExpectedOutputIfValidFile()
113114
var fileProvider = new Mock<IFileProvider>();
114115
fileProvider.Setup(p => p.GetFileInfo(It.IsAny<string>())).Returns(Mock.Of<IFileInfo>(f => f.Exists && f.CreateReadStream() == new MemoryStream(Encoding.UTF8.GetBytes("test svg"))));
115116
var hostEnv = Mock.Of<IWebHostEnvironment>(e => e.WebRootFileProvider == fileProvider.Object);
116-
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null, _settings, null)
117+
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>())
117118
{
118119
FileSource = "test.svg"
119120
};
@@ -131,7 +132,7 @@ public void NoOutputIfMediaUrlNull()
131132
{
132133
var urlProvider = new Mock<IPublishedUrlProvider>();
133134
urlProvider.Setup(p => p.GetMediaUrl(It.IsAny<IPublishedContent>(), It.IsAny<UrlMode>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns((string)null!);
134-
var tagHelper = new InlineSvgTagHelper(null, null, urlProvider.Object, _settings, null)
135+
var tagHelper = new InlineSvgTagHelper(null, null, urlProvider.Object, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>())
135136
{
136137
MediaItem = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media)
137138
};
@@ -147,7 +148,7 @@ public void NoOutputIfMediaNotSvg()
147148
var umbContent = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media);
148149
var urlProvider = new Mock<IPublishedUrlProvider>();
149150
urlProvider.Setup(p => p.GetMediaUrl(umbContent, It.IsAny<UrlMode>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns("test.notsvg");
150-
var tagHelper = new InlineSvgTagHelper(null, null, urlProvider.Object, _settings, null)
151+
var tagHelper = new InlineSvgTagHelper(null, null, urlProvider.Object, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>())
151152
{
152153
MediaItem = umbContent
153154
};
@@ -169,7 +170,8 @@ public void NoOutputIfMediaNotFound()
169170
null,
170171
urlProvider.Object,
171172
_settings,
172-
null)
173+
null,
174+
Mock.Of<ILogger<InlineSvgTagHelper>>())
173175
{
174176
MediaItem = umbContent
175177
};
@@ -191,7 +193,8 @@ public void ExpectedOutputIfValidMedia()
191193
null,
192194
urlProvider.Object,
193195
_settings,
194-
null)
196+
null,
197+
Mock.Of<ILogger<InlineSvgTagHelper>>())
195198
{
196199
MediaItem = umbContent
197200
};
@@ -212,7 +215,7 @@ public void SanitizesJavascript()
212215
.Setup(p => p.GetFileInfo(It.IsAny<string>()))
213216
.Returns(Mock.Of<IFileInfo>(f => f.Exists && f.CreateReadStream() == new MemoryStream(Encoding.UTF8.GetBytes("<a xlink:href=\"javascript:alert('test');\">Click here</a><script attr=\"test\">test</script>end"))));
214217
var hostEnv = Mock.Of<IWebHostEnvironment>(e => e.WebRootFileProvider == fileProvider.Object);
215-
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null, _settings, null)
218+
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null, _settings, null, Mock.Of<ILogger<InlineSvgTagHelper>>())
216219
{
217220
FileSource = "test.svg"
218221
};

Our.Umbraco.TagHelpers/InlineSvgTagHelper.cs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using HtmlAgilityPack;
22
using Microsoft.AspNetCore.Hosting;
33
using Microsoft.AspNetCore.Razor.TagHelpers;
4+
using Microsoft.Extensions.Logging;
45
using Microsoft.Extensions.Options;
56
using Our.Umbraco.TagHelpers.Configuration;
67
using Our.Umbraco.TagHelpers.Utils;
@@ -27,14 +28,16 @@ public class InlineSvgTagHelper : TagHelper
2728
private IPublishedUrlProvider _urlProvider;
2829
private OurUmbracoTagHelpersConfiguration _globalSettings;
2930
private AppCaches _appCaches;
31+
private readonly ILogger<InlineSvgTagHelper> _logger;
3032

31-
public InlineSvgTagHelper(MediaFileManager mediaFileManager, IWebHostEnvironment webHostEnvironment, IPublishedUrlProvider urlProvider, IOptions<OurUmbracoTagHelpersConfiguration> globalSettings, AppCaches appCaches)
33+
public InlineSvgTagHelper(MediaFileManager mediaFileManager, IWebHostEnvironment webHostEnvironment, IPublishedUrlProvider urlProvider, IOptions<OurUmbracoTagHelpersConfiguration> globalSettings, AppCaches appCaches, ILogger<InlineSvgTagHelper> logger)
3234
{
3335
_mediaFileManager = mediaFileManager;
3436
_webHostEnvironment = webHostEnvironment;
3537
_urlProvider = urlProvider;
3638
_globalSettings = globalSettings.Value;
3739
_appCaches = appCaches;
40+
_logger = logger;
3841
}
3942

4043
/// <summary>
@@ -204,25 +207,34 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
204207
if ((EnsureViewBox || (_globalSettings.OurSVG.EnsureViewBox && !IgnoreAppSettings)) || !string.IsNullOrEmpty(CssClass))
205208
{
206209
HtmlDocument doc = new HtmlDocument();
207-
doc.LoadHtml(cleanedFileContents);
208-
var svgs = doc.DocumentNode.SelectNodes("//svg");
209-
foreach (var svgNode in svgs)
210-
{
211-
if (!string.IsNullOrEmpty(CssClass))
210+
try {
211+
doc.LoadHtml(cleanedFileContents);
212+
var svgs = doc.DocumentNode.SelectNodes("//svg");
213+
foreach (var svgNode in svgs)
212214
{
213-
svgNode.AddClass(CssClass);
215+
if (!string.IsNullOrEmpty(CssClass))
216+
{
217+
svgNode.AddClass(CssClass);
218+
}
219+
if ((EnsureViewBox || (_globalSettings.OurSVG.EnsureViewBox && !IgnoreAppSettings)) && svgNode.Attributes.Contains("width") && svgNode.Attributes.Contains("height") && !svgNode.Attributes.Contains("viewbox"))
220+
{
221+
var width = StringUtils.GetDecimal(svgNode.GetAttributeValue("width", "0"));
222+
var height = StringUtils.GetDecimal(svgNode.GetAttributeValue("height", "0"));
223+
svgNode.SetAttributeValue("viewbox", $"0 0 {width} {height}");
224+
225+
svgNode.Attributes.Remove("width");
226+
svgNode.Attributes.Remove("height");
227+
}
214228
}
215-
if ((EnsureViewBox || (_globalSettings.OurSVG.EnsureViewBox && !IgnoreAppSettings)) && svgNode.Attributes.Contains("width") && svgNode.Attributes.Contains("height") && !svgNode.Attributes.Contains("viewbox"))
229+
cleanedFileContents = doc.DocumentNode.OuterHtml;
230+
}
231+
catch(Exception exc) {
232+
if(_logger.IsEnabled(LogLevel.Warning))
216233
{
217-
var width = StringUtils.GetDecimal(svgNode.GetAttributeValue("width", "0"));
218-
var height = StringUtils.GetDecimal(svgNode.GetAttributeValue("height", "0"));
219-
svgNode.SetAttributeValue("viewbox", $"0 0 {width} {height}");
220-
221-
svgNode.Attributes.Remove("width");
222-
svgNode.Attributes.Remove("height");
234+
_logger.LogWarning(exc, "Invalid svg markup");
223235
}
236+
return string.Empty;
224237
}
225-
cleanedFileContents = doc.DocumentNode.OuterHtml;
226238
}
227239

228240
return cleanedFileContents;

0 commit comments

Comments
 (0)