Skip to content

Commit

Permalink
Reject script tags in components, but allow overriding. Fixes #552 (#553
Browse files Browse the repository at this point in the history
)
  • Loading branch information
SteveSandersonMS committed Apr 12, 2018
1 parent 2f4e60b commit ce3c79e
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 0 deletions.
Expand Up @@ -165,6 +165,17 @@ public static RazorDiagnostic CreateEventHandler_Duplicates(SourceSpan? source,
"'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(
Expand Down
Expand Up @@ -243,6 +243,8 @@ public override void WriteHtmlContent(CodeRenderingContext context, HtmlContentI

if (nextToken.Type == HtmlTokenType.StartTag)
{
RejectDisallowedHtmlTags(node, nextTag);

_scopeStack.IncrementCurrentScopeChildCount(context);

codeWriter
Expand Down Expand Up @@ -304,6 +306,26 @@ public override void WriteHtmlContent(CodeRenderingContext context, HtmlContentI
}
}

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);
Expand Down
Expand Up @@ -87,5 +87,28 @@ public void OldCodeBlockAttributeSyntax_ReportsError()
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);
});
}
}
}
Expand Up @@ -365,5 +365,24 @@ @using Microsoft.AspNetCore.Blazor
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);
}
}
}
@@ -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
@@ -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

0 comments on commit ce3c79e

Please sign in to comment.