flawopen.com/Cross-Site Scripting/C#
Imagine a guestbook where visitors write a public note. Stored XSS is like someone writing a note that isn't just text — it's a hidden trick that makes the guestbook page itself start doing things, like stealing the next visitor's login session, the moment anyone opens the page to read it.
Cross-site scripting happens when untrusted input reaches the rendered page without proper output encoding. Razor pages auto-encode by default, so this vulnerability in C# almost always traces back to its explicit raw-output helper being used on untrusted data.
In 2005, an 19-year-old user exploited a stored XSS flaw on MySpace to create the "Samy" worm — a script that added itself to every profile that viewed it, infecting over a million profiles within about 20 hours and forcing MySpace offline to contain it. It remains one of the most-cited demonstrations of how quickly stored XSS can self-propagate.
Source: widely documented in security industry retrospectives — see References below.@* Html.Raw skips encoding entirely *@
<div>
Welcome, @Html.Raw(Model.Name)
</div>
@* default Razor output auto-encodes *@
<div>
Welcome, @Model.Name
</div>
Plain Razor output (@Model.Name) HTML-encodes the value automatically before writing it — special characters become entities, so a <script> tag renders as visible text. Html.Raw() explicitly disables that encoding, writing the string exactly as given.
It exists for genuine cases (trusted CMS content, a sanitized rich-text field), but reaching for it on untrusted input reintroduces the exact vulnerability Razor's default behavior exists to prevent.
Classic <%= value %> writes raw output; <%: value %> is the encoding variant. Legacy Web Forms code still using the raw syntax is a real audit target in older codebases.
Passing server-side data into client-side JS via an inline <script> tag needs JS-context-aware encoding (or a dedicated helper), not HTML encoding — a value safe for HTML body context can still break out of a JS string literal.
True for standard @ output — false the moment Html.Raw() is used on untrusted data.
Any reflected value counts — a search query echoed on a results page, a URL parameter shown in an error message, a filename displayed after upload.
grep -rn "Html.Raw(" --include="*.cshtml" .
grep -rn "<%=" --include="*.aspx" .
Same underlying shape — untrusted data mixed into a command's structure without encoding — but the target and damage differ: SQL injection targets the database, XSS targets other users' browsers.
Blazor's standard component rendering encodes by default; its MarkupString type is the equivalent explicit opt-out, carrying the same risk as Html.Raw() if applied to untrusted content.