-
Notifications
You must be signed in to change notification settings - Fork 34
HTML injection vulnerability #1359
Description
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
- 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);
}- 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.
Environment
- dotnet 9.0