Skip to content
Securitywarn by defaultastro-doctor/no-set-html

no-set-html

Avoid set:html to prevent cross-site scripting (XSS) vulnerabilities.

Why

set:html injects raw HTML into the DOM without escaping. Any user-controlled or third-party content rendered this way is an XSS vector. Use Astro's JSX interpolation, which escapes by default. JSON-LD data scripts are accepted when they use type="application/ld+json".

Examples

Incorrect

Unsanitized HTML injection

astro
---
const userContent = await fetchUserBio()
---
<div set:html={userContent} />

Correct

Escaped interpolation or JSON-LD data

astro
---
const structuredData = JSON.stringify({
  '@context': 'https://schema.org',
  '@type': 'WebSite',
  name: 'Example',
}).replace(/</g, '\u003c')
---
{/* Escaped by default */}
<p>{plainTextContent}</p>

{/* Non-executable structured data */}
<script type="application/ld+json" set:html={structuredData}></script>

Configuration

Override the default severity in your ESLint config:

javascripteslint.config.js
// eslint.config.js
import astroDoctorPlugin from '@santi020k/eslint-plugin-astro-doctor'

export default [
  astroDoctorPlugin.configs.recommended,
  {
    rules: {
      'astro-doctor/no-set-html': 'error',   // or 'warn' or 'off'
    },
  },
]

Or in your doctor.config.ts:

typescriptdoctor.config.ts
export default {
  rules: {
    'astro-doctor/no-set-html': 'error',
  },
}

All rules