Skip to content

Latest commit

 

History

History
115 lines (80 loc) · 3.72 KB

no-html-safe.md

File metadata and controls

115 lines (80 loc) · 3.72 KB

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:

import { htmlSafe } from '@ember/template';
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 <h1>Joe Bloggs</h1>. This is then rendered directly into the template.

// components/my-component.js
import { htmlSafe } from '@ember/template';

class MyComponent extends Component {
  get myContent() {
    return htmlSafe(this.args.userContent);
  }
}
{{!-- 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.

{{!-- components/my-component.hbs --}}
<h1>{{@userContent}}</h1>

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. 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.

// app/lib/sanitized-content.js
import { htmlSafe } from '@ember/template';

export function sanitizedContent(content) {
  const sanitized = someSanitizationLibrary(content);
  return htmlSafe(sanitized);
}
// app/components/my-component.js
import { sanitizedContent } from 'my-app/lib/sanitized-content';

class MyComponent extends Component {
  get myContent() {
    return sanitizedContent(this.args.userContent);
  }
}
{{!-- 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.

// 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);
{{!-- components/my-component.hbs --}}
{{sanitize @userContent}}

Related Rules

  • ember-template-lint has a no-triple-curlies rule for the template equivalent of this rule.

References