Skip to content

HTML injection vulnerability #1359

@Wosiu6

Description

@Wosiu6

Describe the bug
The MBToastService allows for injection of html inside a string passed into the ShowToast method. This renders and executes all and any HTML/CSS/JS on the button click.

As often this data will be something the user passes down like for example a name of something they just added, this could potentially lead to malicious code being executed on the client.

This happens because in InternalToastAnchor.razor we cast any string we pass in into a MarkupString.

To Reproduce

  1. Add this code to any of your pages and attach it to an onclick even of a button.
private void ShowToast()
{
    string html = @"
        <!doctype html>
        <html lang=""en-US"">
        <head>
          <meta charset=""utf-8"" />
          <meta name=""viewport"" content=""width=device-width, initial-scale=1"" />
          <title>Safe Injection Test Page</title>
          <style>
            :root { color-scheme: light; }
            body { font-family: system-ui, sans-serif; margin: 0; padding: 24px; background: #f6f7fb; }
            header, main, footer { max-width: 760px; margin: 0 auto; }
            .card { background: #fff; border: 1px solid #e3e6ef; border-radius: 10px; padding: 16px; margin: 12px 0; }
            .muted { color: #666; font-size: 0.9rem; }
            .btn { padding: 8px 12px; border: 1px solid #ccc; border-radius: 6px; background: #fff; cursor: pointer; }
            .btn:active { transform: translateY(1px); }
          </style>
        </head>
        <body>
          <header>
            <h1>Safe Injection Test Page</h1>
            <p class=""muted"">No scripts or external resources. JS is local and harmless.</p>
          </header>

          <main>
            <section class=""card"">
              <h2>Content Block</h2>
              <p><strong>Bold</strong>, <em>italic</em>, and <a href=""#"">link</a> text.</p>
              <img src=""x"" alt=""test image placeholder"" />
            </section>

            <section class=""card"">
              <h2>Interactive</h2>
              <p id=""status"" class=""muted"">Clicks: 0</p>
              <button class=""btn"" id=""btn"">Click me</button>
            </section>
          </main>

          <footer class=""muted"">Footer text</footer>

          <script>
            (() => {
              const btn = document.getElementById(""btn"");
              const status = document.getElementById(""status"");
              let count = 0;
              btn.addEventListener(""click"", () => {
                count++;
                status.textContent = `Clicks: ${count}`;
              });
            })();
          </script>
        </body>
        </html>
    ";

    ToastService.ShowSuccess(html);
}
  1. Click the button.

Expected behavior
The Toast does not render html or the html is being sanitized beforehand to ensure injected javascript or any other malicious code is not being run on the client

Screenshots
Example of a page injected into a Toast with a working click tracker.

Image

Environment

  • dotnet 9.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions