HTML Entities Were Not Invented for Security. The Security Use Came Later.

ToolHQ TeamOctober 10, 20267 min read

HTML encoding was not invented for security. Security was not on anyone's mind in 1991 when Tim Berners-Lee defined the first HTML elements at CERN. The encoding system existed to solve a purely typographic problem: how do you display a less-than sign in a document where less-than signs are used to mark the beginning of tags?

The answer was character references, and they have been misunderstood and misapplied ever since. Understanding the actual origin of HTML entities, and how they became a security mechanism by accident of circumstance, clarifies when and why to use them correctly.

Berners-Lee's original HTML was a simplified application of SGML, the Standard Generalized Markup Language. He wrote the first HTML specification in 1991 as an internal CERN document called "HTML Tags," and the goal was to describe a way to create hyperlinked documents within the CERN network. The document could not have anticipated that the same format would eventually serve as the foundation for a global publishing medium handling trillions of pages.

The SGML Inheritance

HTML inherited its character reference system directly from SGML, the Standard Generalized Markup Language developed by Charles Goldfarb and colleagues at IBM in the 1970s and published as ISO 8879 in 1986. SGML used angle brackets to delimit markup, which created the fundamental conflict: the characters used to indicate "this is a tag" are the same characters that might legitimately appear in document content. SGML solved this with entity references, a mechanism that HTML adopted wholesale.

The ampersand introduces a reference, the semicolon ends it, and the text in between identifies the character. Write < and the browser renders a less-than sign. Write > and you get greater-than. Write & and you get a literal ampersand. The original HTML entity list was short. The 1992 specification included entities for angle brackets, ampersand, and a small set of accented European characters that the 128 ASCII code points could not represent.

ASCII itself, the American Standard Code for Information Interchange finalized in 1963, was a 7-bit standard covering 128 characters: the Latin alphabet in upper and lower case, digits, punctuation, and control codes. It was explicitly designed for American English, with no provision for the accented characters used throughout European languages. As HTML was adopted internationally in the early 1990s, the character set limitation became a practical problem for any non-English document, and HTML entities provided one path to expressing those characters.

The HTML 2.0 specification, published as RFC 1866 in November 1995 by Tim Berners-Lee and Dan Connolly, standardized the entity reference system formally and expanded the character set. The specification ran 72 pages and defined the core HTML element set still in use today, including entity references as a first-class part of the HTML syntax.

When the Security Dimension Arrived

The security dimension arrived gradually and was not anticipated by the entity reference designers. When web pages began accepting user input in the mid-1990s, and that input began being reflected back in page content, engineers slowly realized that an unencoded less-than sign in user-submitted text would be interpreted by the browser as an HTML tag.

A user who typed an opening script tag followed by JavaScript could inject code that would execute in other users' browsers. This class of attack became known as cross-site scripting, abbreviated XSS. Early documented cases appeared around 1995 and 1996 on CGI-based web applications. Microsoft's website was affected by a known XSS vulnerability in 2000. The Open Web Application Security Project, or OWASP, was founded in 2001 partly to document and combat exactly these kinds of vulnerabilities. OWASP listed XSS in their first Top 10 vulnerabilities document in 2003, by which point it was already the most common class of web security issue.

The defense was to encode all user-supplied content before rendering it as HTML. A less-than sign from user input becomes < before it enters the page, so the browser displays it as a character rather than treating it as markup. An ampersand becomes &. A double quote in a context that would close an HTML attribute becomes ". The character reference system that Berners-Lee adopted from SGML in 1991 for typographic reasons became, a decade later, the standard defense against one of the most exploited vulnerability classes in web security.

This is worth understanding precisely because HTML encoding is still routinely misapplied in both directions. Developers who understand it primarily as a security measure sometimes encode content that does not require it, adding unnecessary processing and producing double-encoded output where < appears literally in the rendered page. Developers who do not fully understand its security purpose skip encoding on user-supplied content that appears visually safe, not realizing that a string can contain no obvious red flags and still be exploitable if it contains unencoded HTML special characters.

Named References, Numeric References, and HTML5

The modern HTML5 specification, published by W3C in 2014 and maintained as a living standard by WHATWG, defines over 2,000 named character references. The full Unicode character set, covering over 140,000 characters across all human writing systems, is reachable through numeric references. Named references like © for the copyright symbol, ™ for the trademark symbol, and — for the em dash allow authors to use characters that may not be available on standard keyboards or that risk encoding issues when stored in certain database configurations.

Numeric references come in two forms. Decimal references use &#followed by the Unicode code point in decimal: © for the copyright symbol. Hexadecimal references use &#x followed by the code point in hex: © for the same character. Both produce identical rendering. The distinction is cosmetic for most purposes, though hexadecimal references are often more compact for characters with large code point values.

The encoding and decoding process is bidirectional. Encoding converts characters with special meaning in HTML, specifically the five characters <, >, &, ", and ', into their entity equivalents for safe inclusion in HTML content. Decoding converts entity references back to their character equivalents, needed when extracting text content from HTML for plain-text processing, analysis, or storage in a database that expects unencoded text.

Context Matters More Than Blanket Encoding

One persistent confusion about HTML encoding is that it is not a universal solution applied once. The correct encoding depends on the context where content appears in an HTML document. Content placed between HTML tags, in the body of a paragraph, is encoded with standard HTML entities. Content placed inside an HTML attribute value requires the same entities plus handling of whichever quote character delimits the attribute. Content placed inside a script tag or event handler requires JavaScript string encoding, not HTML entity encoding. Content placed inside a CSS style block requires CSS encoding.

Using the wrong encoding for the context does not prevent all attacks. A string HTML-entity-encoded and placed inside a JavaScript string literal can still contain JavaScript syntax that executes in the scripting context. OWASP maintains an XSS Prevention Cheat Sheet specifically because the right defense depends on where in the HTML document the user content is being placed.

Browser behavior also changed over time as the standards evolved. Pre-HTML5 browsers performed varying degrees of MIME sniffing and entity interpretation that modern browsers do not. Some older attacks exploited browser quirks where certain entity sequences were interpreted as executable code. Modern browsers enforce stricter separation, but the defense-in-depth principle argues for correct encoding regardless.

Conclusion

HTML entities began as a typographic workaround for an SGML inheritance and became a security mechanism when the web became interactive. The five special HTML characters, < > & " and ', require encoding whenever user-supplied content appears in an HTML context. The over 2,000 named references in the HTML5 specification handle typographic needs from accented characters to mathematical symbols. ToolHQ's HTML encoder and decoder handles both directions for any input you paste in, making it straightforward to verify what a set of entities resolves to or to prepare content for safe inclusion in an HTML document.

Frequently Asked Questions

Why do we need HTML encoding?

HTML encoding prevents special characters like < and > from being interpreted as markup. It also prevents cross-site scripting attacks when user-supplied content is rendered in a page.

What is the difference between &amp;lt; and &#60;?

&lt; is a named entity reference for the less-than sign. &#60; is the decimal numeric reference for the same character. Both render identically in browsers.

When was XSS first documented as a security vulnerability?

Cross-site scripting attacks emerged in the mid-1990s as web pages began accepting user input. OWASP listed XSS in their first Top 10 vulnerability document in 2003.

Try These Free Tools