Error Codes

Estimated reading time: 4 minutes

The XSS detection engine emits four diagnostic codes. Each code links to a specific kind of safety issue with a defined fix.

TS88601 Error

Content may introduce an XSS vulnerability and must be marked with the safe attribute.


An expression with type string or any is used as a child of a native element without the safe attribute.

const 
const html: JSX.Element
html
= <
JSX.IntrinsicElements.div: JSX.HtmlTag
div
>{username}</
JSX.IntrinsicElements.div: JSX.HtmlTag
div
>
Content may introduce an XSS vulnerability and must be marked with the `safe` attribute. See https://html.kitajs.org/TS88601
<div>Arthur</div>

Variables prefixed with safe are exempt from this rule, as are expressions with safe types (numbers, booleans, string literals...).

Fix

Add the safe attribute to escape the content

const 
const html: JSX.Element
html
= <
JSX.IntrinsicElements.div: JSX.HtmlTag
div
JSX.HtmlTag.safe?: boolean | undefined

When set to true, all inner content (html or not) of this tag will be escaped when evaluated.

Warning: This will escape even inner jsx tags. You should only use this in the most inner tag of the html tree.

@example
<div>{'<script />'}</div>
'<div><script /></div>'
<div safe>{'<script />'}</div>
'<div><script /></div>'
<div><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'

// Escapes even inner jsx tags
<div safe><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
@defaultfalse@seehttps ://github.com/kitajs/html/tree/master/packages/html#sanitization
safe
>{
let username: string
username
}</
JSX.IntrinsicElements.div: JSX.HtmlTag
div
>
<div>Arthur</div>

TS88602 Error

The safe attribute causes this content to be escaped more than once.


Severity: error. The safe attribute is applied to an element whose children include JSX elements. This would escape the HTML output of those child components, corrupting their markup.

const 
const html: JSX.Element
html
= (
<
JSX.IntrinsicElements.div: JSX.HtmlTag
div
safe>
The `safe` attribute causes this content to be escaped more than once. See https://html.kitajs.org/TS88602
{
const user: {
    name: string;
    badgeUrl: string;
}
user
.
name: string
name
}
<
function UserBadge(props: {
    url: string;
}): JSX.Element
UserBadge
url: string
url
={
const user: {
    name: string;
    badgeUrl: string;
}
user
.
badgeUrl: string
badgeUrl
} />
</
JSX.IntrinsicElements.div: JSX.HtmlTag
div
>
)
<div>
  Arthur&lt;div class=&#34;badge&#34;>&lt;img
  src=&#34;https://example.com/badge.png&#34; alt=&#34;User
  badge&#34;/>&lt;/div>
</div>

You can also wrap inner components inside fragments or use escapeHtml() manually to avoid the double escaping.

Fix

Remove safe from the parent element. You can use Fragment to apply safe to a group of children without affecting nested components, since fragments don't render actual HTML elements.

import { 
function Fragment(props: PropsWithChildren<Pick<JSX.HtmlTag, "safe">>): JSX.Element

A JSX Fragment is used to return multiple elements from a component.

@example
// renders <div>1</div> and <div>2</div> without needing a wrapper element
const html = <><div>1</div><div>2</div></>

// Html.Fragment is the same as <>...</>
const html = <Html.Fragment><div>1</div><div>2</div></Html.Fragment>
Fragment
} from '@kitajs/html'
const
const html: JSX.Element
html
= (
<
JSX.IntrinsicElements.div: JSX.HtmlTag
div
>
<
function Fragment(props: PropsWithChildren<Pick<JSX.HtmlTag, "safe">>): JSX.Element

A JSX Fragment is used to return multiple elements from a component.

@example
// renders <div>1</div> and <div>2</div> without needing a wrapper element
const html = <><div>1</div><div>2</div></>

// Html.Fragment is the same as <>...</>
const html = <Html.Fragment><div>1</div><div>2</div></Html.Fragment>
Fragment
safe?: boolean | undefined

When set to true, all inner content (html or not) of this tag will be escaped when evaluated.

Warning: This will escape even inner jsx tags. You should only use this in the most inner tag of the html tree.

@example
<div>{'<script />'}</div>
'<div><script /></div>'
<div safe>{'<script />'}</div>
'<div><script /></div>'
<div><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'

// Escapes even inner jsx tags
<div safe><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
@defaultfalse@seehttps ://github.com/kitajs/html/tree/master/packages/html#sanitization
safe
>{
const user: {
    name: string;
    badgeUrl: string;
}
user
.
name: string
name
}</
function Fragment(props: PropsWithChildren<Pick<JSX.HtmlTag, "safe">>): JSX.Element

A JSX Fragment is used to return multiple elements from a component.

@example
// renders <div>1</div> and <div>2</div> without needing a wrapper element
const html = <><div>1</div><div>2</div></>

// Html.Fragment is the same as <>...</>
const html = <Html.Fragment><div>1</div><div>2</div></Html.Fragment>
Fragment
>
<
function UserBadge(props: {
    url: string;
}): JSX.Element
UserBadge
url: string
url
={
const user: {
    name: string;
    badgeUrl: string;
}
user
.
badgeUrl: string
badgeUrl
} />
</
JSX.IntrinsicElements.div: JSX.HtmlTag
div
>
)
<div>
  Arthur
  <div class="badge">
    <img src="https://example.com/badge.png" alt="User badge" />
  </div>
</div>

TS88603 Error

Content inside a Component must be escaped using escapeHtml().


An expression with type string or any is passed as a child to a component (uppercase tag name). Unlike native elements, components cannot use the safe attribute directly on children.

const 
const html: JSX.Element
html
= <
function Card({ children }: {
    children: string;
}): JSX.Element
Card
>{userName}</
function Card({ children }: {
    children: string;
}): JSX.Element
Card
>
Content inside a Component must be escaped using escapeHtml(). See https://html.kitajs.org/TS88603
<div>Arthur</div>

Components cannot apply the safe attribute directly to their children. You must either escape the content before passing it, or wrap it in a Fragment with the safe attribute.

Fix

Escape manually using Html.escapeHtml()

const 
const html: JSX.Element
html
= <
function Card({ children }: {
    children: string;
}): JSX.Element
Card
>{
import Html
Html
.
let escapeHtml: (this: void, value: any) => string

Escapes a string for safe use as HTML text content. If the value is not a string, it is coerced to one with its own toString() method.

If the {@linkcode Bun } runtime is available, this function will be swapped out to

{@linkcode Bun.escapeHTML } .

@paramvalue The value to escape.@returnsThe escaped string.
escapeHtml
(
let userName: string
userName
)}</
function Card({ children }: {
    children: string;
}): JSX.Element
Card
>
<div>Arthur</div>

Or wrap the content in a Fragment with safe

const 
const html: JSX.Element
html
= (
<
function Card({ children }: {
    children: JSX.Element;
}): JSX.Element
Card
>
<
function Fragment(props: PropsWithChildren<Pick<JSX.HtmlTag, "safe">>): JSX.Element

A JSX Fragment is used to return multiple elements from a component.

@example
// renders <div>1</div> and <div>2</div> without needing a wrapper element
const html = <><div>1</div><div>2</div></>

// Html.Fragment is the same as <>...</>
const html = <Html.Fragment><div>1</div><div>2</div></Html.Fragment>
Fragment
safe?: boolean | undefined

When set to true, all inner content (html or not) of this tag will be escaped when evaluated.

Warning: This will escape even inner jsx tags. You should only use this in the most inner tag of the html tree.

@example
<div>{'<script />'}</div>
'<div><script /></div>'
<div safe>{'<script />'}</div>
'<div><script /></div>'
<div><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'

// Escapes even inner jsx tags
<div safe><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
@defaultfalse@seehttps ://github.com/kitajs/html/tree/master/packages/html#sanitization
safe
>{
let userName: string
userName
}</
function Fragment(props: PropsWithChildren<Pick<JSX.HtmlTag, "safe">>): JSX.Element

A JSX Fragment is used to return multiple elements from a component.

@example
// renders <div>1</div> and <div>2</div> without needing a wrapper element
const html = <><div>1</div><div>2</div></>

// Html.Fragment is the same as <>...</>
const html = <Html.Fragment><div>1</div><div>2</div></Html.Fragment>
Fragment
>
</
function Card({ children }: {
    children: JSX.Element;
}): JSX.Element
Card
>
)
<div>Arthur</div>

TS88604 Warning

The safe attribute is unused in this context.


The safe attribute is applied to an element whose children are already safe types (numbers, booleans, JSX.Element, etc.). The escaping is redundant and can be removed.

const 
const html: JSX.Element
html
= <
JSX.IntrinsicElements.span: JSX.HtmlTag
span
safe>{
const count: 42
count
}</
JSX.IntrinsicElements.span: JSX.HtmlTag
span
>
The `safe` attribute is unused in this context. See https://html.kitajs.org/TS88604
<span>42</span>

Numbers, booleans, bigints, string literals, and JSX.Element types are already safe and cannot introduce XSS vulnerabilities. The safe attribute has no effect on these types.

Fix

Remove the safe attribute since numbers are already safe

const 
const html: JSX.Element
html
= <
JSX.IntrinsicElements.span: JSX.HtmlTag
span
>{
const count: 42
count
}</
JSX.IntrinsicElements.span: JSX.HtmlTag
span
>
<span>42</span>