HTML injection¶
What does this mean?¶
HTML injection occurs when untrusted data is interpreted as page markup instead of the intended text. Injected elements can mislead users, alter links or disrupt the interface even when scripts do not execute. If executable browser content is possible, the issue can also become cross-site scripting.
Input may come from requests, stored comments, imported files or external APIs. Its origin does not become trusted simply because it passed through a database. Review the point where the value enters the HTML response or DOM.
Recommendation¶
Use context-aware output encoding for plain text. Preserve the template engine's automatic escaping and use text-only DOM sinks for ordinary labels. Searching for angle brackets or deleting a few tag names is not a reliable HTML security policy. If rich HTML is intentional, use a maintained sanitizer with a defined allowed-content policy before granting HTML trust.
Sample code¶
This Python example builds a small HTML text fragment from an untrusted string comment. A real application should normally use an escaping template engine.
Unsafe: interpolate the value into markup.
fragment = f'<p>{comment}</p>'
Safer for this HTML text context: encode at output.
from html import escape
fragment = f'<p>{escape(comment)}</p>'
Python's html.escape reference describes the character conversion. Do not reuse this as a JavaScript, CSS or URL sanitizer; those contexts have different rules.
For ASP.NET Core Razor, assume Model.Comment is an ordinary string:
@* Unsafe for untrusted plain text. *@
<p>@Html.Raw(Model.Comment)</p>
@* Safer: retain Razor's string encoding. *@
<p>@Model.Comment</p>
Razor's expression-encoding documentation distinguishes ordinary strings from trusted HTML content. A value already marked as trusted HTML needs a separate review.
Check the fix¶
Render the harmless value <b>Demo</b> and assert that it displays literally with no nested b element. Check ampersands, quotes, Unicode and empty strings through the actual response path. For the Razor version, test the rendered view, not merely the model property.
Keep authorization and URL validation separate. Neither encoding nor a sanitizer establishes that a user may publish a link or modify another user's content. Continue with autoescaping, unsafe innerHTML and template injection.