Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new rule no-html-safe #1079

Merged
merged 1 commit into from
Jan 30, 2021
Merged

Conversation

patocallaghan
Copy link
Contributor

Closes #1041

Introduces a no-html-safe rule to prevent the usage of the htmlSafe utility.

htmlSafe marks a string as safe for unescaped output with Ember templates so you can render it as HTML. 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.

@@ -0,0 +1,37 @@
'use strict';

const ERROR_MESSAGE = 'Do not use htmlSafe.';
Copy link
Contributor Author

@patocallaghan patocallaghan Jan 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message is a bit dry. Would it better to do something like the following?

Do not use htmlSafe. It can open you up to XSS vulnerabilities.

Copy link
Member

@bmish bmish Jan 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I normally like to use the format Use X instead of Y for error messages, but there doesn't seem to be one single preferred fix for this violation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I like doing similar but not sure we could fit any actionable advice in the error. How about linking to rule .md file?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not link to the documentation in the error message because the rule already includes the documentation link in its meta data and many IDEs will already provide a link to the documentation directly on the highlighted rule violation.

import { htmlSafe } from '@ember/string';
```

## Alternatives
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no exact alternatives to using htmlSafe so I put together this Alternatives section which outlines some ways you can minimise your usage of htmlSafe. Happy for feedback whether this is suitable or not.

(node.source.value === '@ember/string' || node.source.value === '@ember/template') &&
node.specifiers.some((s) => s.local.name === 'htmlSafe')
) {
context.report(node, ERROR_MESSAGE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to report the specific specifier htmlSafe instead of the entire import statement. We don't want to flag other specifiers that might be imported in the same statement.

<h1>{{@userContent}}</h1>
```

### Alternative 2: Define your own trusted sanitizing helper
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding alternatives 2 and 3, I'm unclear why it would be better to define a custom sanitizing helper. In fact, encouraging custom sanitizing helpers sound like a dangerous anti-pattern, as they would be much more likely to have bugs / security vulnerabilities versus using a published/trusted helper like htmlSafe from Ember.

Copy link
Contributor Author

@patocallaghan patocallaghan Jan 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So htmlSafe doesn't do any sanitization which is why it can easily become a XSS vector. With a name like htmlSafe I've been caught out and reviewed many PRs where people assume it is doing sanitization. All it does is takes the string with the HTML in it and says "yep you can render this string in a template as html", even if the string has XSSs in it.

React has a similar helper to htmlSafe but it's called dangerouslySetInnerHTML which is a lot more obvious you shouldn't be using it. They even have a similar lint rule.

For 2 and 3, I'm advocating if you have to use htmlSafe always sanitize the content first that you are going to mark safe. I'd recommend a sanitizer like DOMPurify but wasn't sure whether I'd call it out.

Happy to get further feedback though. Even happy to cut back the section altogether if you think it will just add to confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tweaked the opening paragraph mentioning that htmlSafe doesn't perform sanitization, and also added updated alternative to mention DOMPurify.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah my bad. I knew htmlSafe doesn't do any sanitizing but it's easy get confused about it due to its poor name as you mention.

This plan sounds good:

  • Updating the doc to help people avoid that confusion
  • Suggesting something like DOMPurify so people don't think they need to write a custom sanitizer with their own string parsing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, the name really is unfortunate. It is trying to be the developer saying "hey this is html safe", but most people read it as "hey please make this html safe for me".

@@ -0,0 +1,37 @@
'use strict';

const ERROR_MESSAGE = 'Do not use htmlSafe.';
Copy link
Member

@bmish bmish Jan 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I normally like to use the format Use X instead of Y for error messages, but there doesn't seem to be one single preferred fix for this violation.

@bmish bmish requested a review from rwjblue January 29, 2021 00:43
@bmish bmish changed the title Add no-html-safe rule Add new rule no-html-safe Jan 29, 2021
meta: {
type: 'suggestion',
docs: {
description: 'disallow the use of htmlSafe',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put htmlSafe in backticks to make it clear it's a function name?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this isn't done yet. You will need to run yarn update after updating the message.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix in: #1080

@patocallaghan
Copy link
Contributor Author

Thanks @bmish 🙇‍♂️ I've updated the error message with backticks and just squashed all my commits.

Examples of **incorrect** code for this rule:

```js
import { htmlSafe } from '@ember/template';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would vaguely prefer to fail at the usage site, not the import site. 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this so I am updating the location where the violation is flagged in a follow-up PR: #1080

@bmish bmish merged commit e9459ea into ember-cli:master Jan 30, 2021
@patocallaghan patocallaghan deleted the patoc/no-html-safe branch January 30, 2021 20:08
@patocallaghan
Copy link
Contributor Author

Thanks for all the help folks 🙇‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New rule: Prevent usage of htmlSafe
3 participants