Using the safe attribute
Estimated reading time: 4 minutesEvery child expression in Kita Html renders without escaping by default. To escape user
input, apply the safe attribute to the nearest native element wrapping the expression.
Native elements
Add safe to the element that directly contains the dynamic content. The runtime passes
all children through HTML entity escaping before concatenation.
safe={true} is equivalent to safe. kita-html check only trusts these two forms;
safe={false} and dynamic values such as safe={escape} are checked as if the attribute
were missing, because the check cannot prove they are true at runtime.
Without safe, malicious input executes. Consider a user profile where the description
field contains
</div><script>fetch('/steal', {method: 'POST', body: document.cookie})</script>.
Rendering this without escaping closes the container early, injects a script tag, and runs
arbitrary code. The safe attribute converts < to < (along with &, ", and
'), so the payload renders as text.
Place safe on the innermost element that holds the untrusted value. Do not add it to a
parent wrapper, as that would escape the HTML of child components too.
Component children
The safe attribute only applies to native elements and Fragment. If you pass an unsafe
value as a child to a component, you must either escape it manually or wrap it in a
Fragment with the safe attribute, which escapes it. This prevents components from
accidentally rendering unescaped HTML when they receive dynamic content as children.
Safety rules
The XSS tooling classifies JSX child expressions by TypeScript type. These types are safe without escaping:
These types need safe, explicit escaping, or a justified suppression:
Union types are safe only when every member is safe. For example, number | boolean is
safe, but string | number is unsafe because one branch may contain dynamic text. Content
inside <script> elements is exempt from analysis because script content is intended to
be executable and is not subject to HTML escaping rules.
Template literal helper
e is a tagged template alias of escape(). It escapes the entire resulting string,
including the literal parts, so use it for plain text outside of JSX.
Suppression conventions
When kita-html check flags a value that you know is safe, you can suppress the warning
without adding safe to the element, which would escape all children and potentially
break components.
Suppressing warnings is dangerous because it allows unescaped HTML to slip through. Only use these techniques when you have a guarantee of safety.
Prefix the variable name with safe. The check treats identifiers named safe, or
starting with safe followed by a non-lowercase character (such as safeContent or
safe_html), as pre-escaped. Names like safety are still checked.
Following the same logic, prefixing a variable with unsafe explicitly marks it as
unescaped and triggers error TS88601 if used in JSX.
Manual casts and naming conventions are not enforced by the compiler. They rely on developer discipline and code reviews to ensure safety. Use them judiciously and document the rationale for any exceptions.
Cast the expression to 'safe' inline. kita-html check then skips that specific usage
and does not warn about possible XSS vulnerabilities.