# ember/no-html-safe
`htmlSafe` marks a string as safe for unescaped output with Ember templates so you can render it as HTML. `htmlSafe` does **not** perform input sanitization. While useful this can inadvertently open you up to Cross-site Scripting (XSS) vulnerabilities, especially if the string was generated from user input or some other untrusted source. **You should only ever use `htmlSafe` with trusted or sanitized input**.
Note: this rule is not in the `recommended` configuration because there are legitimate usages of `htmlSafe`.
## Rule Details
This rule prevents importing the `htmlSafe` utillity from `@ember/template` (or `@ember/string` for older Ember versions);
## Examples
Examples of **incorrect** code for this rule:
```js
import { htmlSafe } from '@ember/template';
```
```js
import { htmlSafe } from '@ember/string';
```
## Alternatives
There are a few alternative strategies to using `htmlSafe`.
### Scenario
In this example we have a property `userContent` which contains a user-generated string of HTML. For example, something like `
Joe Bloggs
`. This is then rendered directly into the template.
```js
// components/my-component.js
import { htmlSafe } from '@ember/template';
class MyComponent extends Component {
get myContent() {
return htmlSafe(this.args.userContent);
}
}
```
```hbs
{{! components/my-component.hbs }}
{{this.myContent}}
```
### Alternative 1: Render the HTML yourself
While not as flexible, if you can control the content generated by the user you should only let the user enter plaintext and render the HTML yourself.
```hbs
{{! components/my-component.hbs }}
{{@userContent}}
```
### Alternative 2: Define your own trusted sanitizing helper
If you _have_ to render user generated HTML, you should protect yourself by always sanitizing the input first. One strategy is to, rather than have usage of `htmlSafe` proliferated throughout your app, isolate it to a single location and combine it with a sanitization library, e.g. [DOMPurify](https://github.com/cure53/DOMPurify). Then require all HTML strings go through this helper. If this helper is in the same codebase where the `no-html-safe` lint rule is enabled, you can disable the rule for this single location.
```js
// app/lib/sanitized-content.js
import { htmlSafe } from '@ember/template';
export function sanitizedContent(content) {
const sanitized = someSanitizationLibrary(content);
return htmlSafe(sanitized);
}
```
```js
// app/components/my-component.js
import { sanitizedContent } from 'my-app/lib/sanitized-content';
class MyComponent extends Component {
get myContent() {
return sanitizedContent(this.args.userContent);
}
}
```
```hbs
{{! components/my-component.hbs }}
{{this.myContent}}
```
### Alternative 3: Define your own trusted sanitizing Handlebars helper
This is similar to the previous example but in this case you could create a Handlebars helper which sanitizes your input.
```js
// app/helpers/sanitize.js
import { htmlSafe } from '@ember/template';
import { helper } from '@ember/component/helper';
function sanitize([content]) {
const sanitized = someSanitizationLibrary(content);
return htmlSafe(sanitized);
}
export default helper(substring);
```
```hbs
{{! components/my-component.hbs }}
{{sanitize @userContent}}
```
## Related Rules
- ember-template-lint has a [no-triple-curlies](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-triple-curlies.md) rule for the template equivalent of this rule.
## References
- [Ember's `htmlSafe` API documentation](https://api.emberjs.com/ember/release/functions/@ember%2Ftemplate/htmlSafe)
- [MDN's Cross-site Scripting (XSS) documentation](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting)