escapeInject
Environment: server.
The escapeInject
string template tag sanitizes HTML to prevent security risks commonly called XSS injections.
If you use a UI framework Vike extension
vike-react
/vike-vue
/vike-solid
, then you don't need to useescapeInject
yourself asvike-react
/vike-vue
/vike-solid
already sanitizes its HTML.
It's usually used by the onRenderHtml()
hook.
// +onRenderHtml.js
// Environment: server
export { onRenderHtml }
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
async function onRenderHtml() {
const title = 'Hello<script src="https://devil.org/evil-code"></script>'
// This HTML is safe thanks to `escapeInject` which sanitizes `title`
return escapeInject`<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
</head>
<body>
<!-- ... ->
</body>
</html>`
}
All strings, e.g. title
above, are automatically sanitized (technically speaking: HTML-escaped)
so that we can safely include untrusted strings
such as user-generated text.
The dangerouslySkipEscape(str)
function injects the string str
as-is without sanitizing.
We should use dangerouslySkipEscape()
with a lot of caution and
only for HTML strings that are guaranteed to be already sanitized.
We usually use dangerouslySkipEscape()
for including HTML generated by UI frameworks (React/Vue/...) as these are already sanitized.
If we find ourselves using dangerouslySkipEscape()
in other situations, we should be extra careful as we run into the risk of creating a security breach.
HTML Fragments
We can assemble the overall HTML document from several HTML fragments. For example, if we want some HTML parts to be included only for certain pages:
// +onRenderHtml.js
// Environment: server
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
import { renderToHtml } from 'some-ui-framework'
export { onRenderHtml }
async function onRenderHtml(pageContext) {
const description = pageContext.config.description
const descriptionTag = !description ?
'' :
// We use `escapeInject` for an HTML fragment
escapeInject`<meta name="description" content="${description}">`
// We use `escapeInject` again for the overall HTML
return escapeInject`<html>
<head>
${descriptionTag}
</head>
<body>
<div id="root">
${dangerouslySkipEscape(await renderToHtml(pageContext.Page))}
</div>
</body>
</html>`
}
pageContext.config.description
is a custom setting, see API >meta
> Example:title
anddescription
.
Example: