From 63500749bb18de77515e95907c874e964258b0f3 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 15 Jan 2025 17:11:56 +0800 Subject: [PATCH] Add noopener noreferrer nofollow to generated content links --- src/Aspire.Dashboard/ConsoleLogs/UrlParser.cs | 2 +- .../ConsoleLogsTests/LogEntriesTests.cs | 2 +- .../ConsoleLogsTests/UrlParserTests.cs | 36 ++++++++++++------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Aspire.Dashboard/ConsoleLogs/UrlParser.cs b/src/Aspire.Dashboard/ConsoleLogs/UrlParser.cs index e5e14f5d2f..242bfc9e50 100644 --- a/src/Aspire.Dashboard/ConsoleLogs/UrlParser.cs +++ b/src/Aspire.Dashboard/ConsoleLogs/UrlParser.cs @@ -35,7 +35,7 @@ public static bool TryParse(string? text, Func? nonMatchFragment nextCharIndex = urlMatch.Index + urlMatch.Length; var url = text[urlStart..nextCharIndex]; - builder.Append(CultureInfo.InvariantCulture, $"{WebUtility.HtmlEncode(url)}"); + builder.Append(CultureInfo.InvariantCulture, $"{WebUtility.HtmlEncode(url)}"); urlMatch = urlMatch.NextMatch(); } diff --git a/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/LogEntriesTests.cs b/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/LogEntriesTests.cs index ba8fe8e771..bf3c045e7a 100644 --- a/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/LogEntriesTests.cs +++ b/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/LogEntriesTests.cs @@ -244,6 +244,6 @@ public void CreateLogEntry_AnsiAndUrl_HasUrlAnchor() var entry = parser.CreateLogEntry("\x1b[36mhttps://www.example.com\u001b[0m", isErrorOutput: false); // Assert - Assert.Equal("https://www.example.com", entry.Content); + Assert.Equal("https://www.example.com", entry.Content); } } diff --git a/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/UrlParserTests.cs b/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/UrlParserTests.cs index d1fca0c92a..d164600de4 100644 --- a/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/UrlParserTests.cs +++ b/tests/Aspire.Dashboard.Tests/ConsoleLogsTests/UrlParserTests.cs @@ -22,9 +22,9 @@ public void TryParse_NoUrl_ReturnsFalse(string? input) } [Theory] - [InlineData("This is some text with a URL at the end: https://bing.com/", true, "This is some text with a URL at the end: https://bing.com/")] - [InlineData("https://bing.com/ This is some text with a URL at the beginning", true, "https://bing.com/ This is some text with a URL at the beginning")] - [InlineData("This is some text with a https://bing.com/ in the middle", true, "This is some text with a https://bing.com/ in the middle")] + [InlineData("This is some text with a URL at the end: https://bing.com/", true, "This is some text with a URL at the end: https://bing.com/")] + [InlineData("https://bing.com/ This is some text with a URL at the beginning", true, "https://bing.com/ This is some text with a URL at the beginning")] + [InlineData("This is some text with a https://bing.com/ in the middle", true, "This is some text with a https://bing.com/ in the middle")] public void TryParse_ReturnsCorrectResult(string input, bool expectedResult, string? expectedOutput) { var result = UrlParser.TryParse(input, WebUtility.HtmlEncode, out var modifiedText); @@ -34,13 +34,13 @@ public void TryParse_ReturnsCorrectResult(string input, bool expectedResult, str } [Theory] - [InlineData("http://bing.com", "http://bing.com")] - [InlineData("https://bing.com", "https://bing.com")] - [InlineData("http://www.bing.com", "http://www.bing.com")] - [InlineData("http://bing.com/", "http://bing.com/")] - [InlineData("http://bing.com/dir", "http://bing.com/dir")] - [InlineData("http://bing.com/index.aspx", "http://bing.com/index.aspx")] - [InlineData("http://localhost", "http://localhost")] + [InlineData("http://bing.com", "http://bing.com")] + [InlineData("https://bing.com", "https://bing.com")] + [InlineData("http://www.bing.com", "http://www.bing.com")] + [InlineData("http://bing.com/", "http://bing.com/")] + [InlineData("http://bing.com/dir", "http://bing.com/dir")] + [InlineData("http://bing.com/index.aspx", "http://bing.com/index.aspx")] + [InlineData("http://localhost", "http://localhost")] public void TryParse_SupportedUrlFormats(string input, string? expectedOutput) { var result = UrlParser.TryParse(input, WebUtility.HtmlEncode, out var modifiedText); @@ -61,8 +61,18 @@ public void TryParse_UnsupportedUrlFormats(string input) } [Theory] - [InlineData("http://localhost:8080", "http://localhost:8080</url>")] - [InlineData("http://localhost:8080\"", "http://localhost:8080"")] + [InlineData("script:alert('hi')")] + [InlineData("http://script:alert('hi')")] + public void TryParse_AttemptedScriptInjection(string input) + { + var result = UrlParser.TryParse(input, WebUtility.HtmlEncode, out var _); + + Assert.False(result); + } + + [Theory] + [InlineData("http://localhost:8080", "http://localhost:8080</url>")] + [InlineData("http://localhost:8080\"", "http://localhost:8080"")] public void TryParse_ExcludeInvalidTrailingChars(string input, string? expectedOutput) { var result = UrlParser.TryParse(input, WebUtility.HtmlEncode, out var modifiedText); @@ -77,7 +87,7 @@ public void TryParse_QueryString() var result = UrlParser.TryParse("https://www.example.com?query=string¶m=value", WebUtility.HtmlEncode, out var modifiedText); Assert.True(result); - Assert.Equal("https://www.example.com?query=string&param=value", modifiedText); + Assert.Equal("https://www.example.com?query=string&param=value", modifiedText); } [Theory]