Reject script tags in components, but allow overriding. Fixes #552 (#553)

This commit is contained in:
Steve Sanderson 2018-04-12 16:28:31 +01:00 committed by GitHub
parent 2f4e60b134
commit ce3c79e051
6 changed files with 128 additions and 0 deletions

View File

@ -165,6 +165,17 @@ namespace Microsoft.AspNetCore.Blazor.Razor
"'bind', 'bind-value' or 'bind-value-change'",
RazorDiagnosticSeverity.Error);
public static readonly RazorDiagnosticDescriptor DisallowedScriptTag = new RazorDiagnosticDescriptor(
"BL9992",
() => "Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. For more information see http://some/link",
RazorDiagnosticSeverity.Error);
public static RazorDiagnostic Create_DisallowedScriptTag(SourceSpan? source)
{
var diagnostic = RazorDiagnostic.Create(DisallowedScriptTag, source ?? SourceSpan.Undefined);
return diagnostic;
}
public static RazorDiagnostic CreateBindAttribute_InvalidSyntax(SourceSpan? source, string attribute)
{
var diagnostic = RazorDiagnostic.Create(

View File

@ -243,6 +243,8 @@ namespace Microsoft.AspNetCore.Blazor.Razor
if (nextToken.Type == HtmlTokenType.StartTag)
{
RejectDisallowedHtmlTags(node, nextTag);
_scopeStack.IncrementCurrentScopeChildCount(context);
codeWriter
@ -304,6 +306,26 @@ namespace Microsoft.AspNetCore.Blazor.Razor
}
}
private void RejectDisallowedHtmlTags(IntermediateNode node, HtmlTagToken tagToken)
{
// Disallow <script> in components as per #552
// Case-sensitive comparison is fine because AngleSharp always lowercases tag names
if (tagToken.Name.Equals("script", StringComparison.Ordinal))
{
const string suppressErrorAttributeName = "suppress-error";
if (string.Equals(tagToken.GetAttribute(suppressErrorAttributeName), "BL9992", StringComparison.Ordinal))
{
tagToken.Attributes.RemoveAll(kvp => kvp.Key.Equals(suppressErrorAttributeName, StringComparison.Ordinal));
}
else
{
var adjustedSpan = CalculateSourcePosition(node.Source, tagToken.Position);
var diagnostic = BlazorDiagnosticFactory.Create_DisallowedScriptTag(adjustedSpan);
throw new RazorCompilerException(diagnostic);
}
}
}
public override void WriteUsingDirective(CodeRenderingContext context, UsingDirectiveIntermediateNode node)
{
context.CodeWriter.WriteUsing(node.Content, endLine: true);

View File

@ -87,5 +87,28 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var diagnostic = Assert.Single(generated.Diagnostics);
Assert.Equal("BL9979", diagnostic.Id);
}
[Fact]
public void RejectsScriptTag()
{
// Arrange/Act
var result = CompileToCSharp(@"Hello
<div>
<script src='anything'>
something
</script>
</div>
Goodbye");
// Assert
Assert.Collection(result.Diagnostics,
item =>
{
Assert.Equal("BL9992", item.Id);
Assert.Equal("Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. For more information see http://some/link", item.GetMessage());
Assert.Equal(2, item.Span.LineIndex);
Assert.Equal(4, item.Span.CharacterIndex);
});
}
}
}

View File

@ -365,5 +365,24 @@ namespace Test
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]
public void ScriptTag_WithErrorSuppressed()
{
// Arrange/Act
var generated = CompileToCSharp(@"
<div>
<script src='some/url.js' anotherattribute suppress-error='BL9992'>
some text
some more text
</script>
</div>
");
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
}
}

View File

@ -0,0 +1,30 @@
// <auto-generated/>
#pragma warning disable 1591
namespace Test
{
#line hidden
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.OpenElement(0, "div");
builder.AddContent(1, "\n ");
builder.OpenElement(2, "script");
builder.AddAttribute(3, "src", "some/url.js");
builder.AddAttribute(4, "anotherattribute", "");
builder.AddContent(5, "\n some text\n some more text\n ");
builder.CloseElement();
builder.AddContent(6, "\n");
builder.CloseElement();
builder.AddContent(7, "\n");
}
#pragma warning restore 1998
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,23 @@
Document -
NamespaceDeclaration - - Test
UsingDirective - (3:1,1 [14] ) - System
UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
UsingDirective - (53:3,1 [19] ) - System.Linq
UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent -
MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (0:0,0 [146] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (0:0,0 [5] x:\dir\subdir\Test\TestComponent.cshtml) - Html - <div>
IntermediateToken - (5:0,5 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
IntermediateToken - (11:1,4 [7] x:\dir\subdir\Test\TestComponent.cshtml) - Html - <script
IntermediateToken - (18:1,11 [18] x:\dir\subdir\Test\TestComponent.cshtml) - Html - src='some/url.js'
IntermediateToken - (36:1,29 [17] x:\dir\subdir\Test\TestComponent.cshtml) - Html - anotherattribute
IntermediateToken - (53:1,46 [24] x:\dir\subdir\Test\TestComponent.cshtml) - Html - suppress-error='BL9992'
IntermediateToken - (77:1,70 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Html - >
IntermediateToken - (78:1,71 [49] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n some text\n some more text\n
IntermediateToken - (127:4,4 [9] x:\dir\subdir\Test\TestComponent.cshtml) - Html - </script>
IntermediateToken - (136:4,13 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
IntermediateToken - (138:5,0 [6] x:\dir\subdir\Test\TestComponent.cshtml) - Html - </div>
IntermediateToken - (144:5,6 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n