-
-
Notifications
You must be signed in to change notification settings - Fork 204
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
Conversation
lib/rules/no-html-safe.js
Outdated
@@ -0,0 +1,37 @@ | |||
'use strict'; | |||
|
|||
const ERROR_MESSAGE = 'Do not use htmlSafe.'; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
1ba1ddf
to
8ca8858
Compare
import { htmlSafe } from '@ember/string'; | ||
``` | ||
|
||
## Alternatives |
There was a problem hiding this comment.
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.
lib/rules/no-html-safe.js
Outdated
(node.source.value === '@ember/string' || node.source.value === '@ember/template') && | ||
node.specifiers.some((s) => s.local.name === 'htmlSafe') | ||
) { | ||
context.report(node, ERROR_MESSAGE); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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".
lib/rules/no-html-safe.js
Outdated
@@ -0,0 +1,37 @@ | |||
'use strict'; | |||
|
|||
const ERROR_MESSAGE = 'Do not use htmlSafe.'; |
There was a problem hiding this comment.
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.
meta: { | ||
type: 'suggestion', | ||
docs: { | ||
description: 'disallow the use of htmlSafe', |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix in: #1080
0a8c1ac
to
8b98d82
Compare
8b98d82
to
a77650e
Compare
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'; |
There was a problem hiding this comment.
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. 🤔
There was a problem hiding this comment.
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
Thanks for all the help folks 🙇♂️ |
Closes #1041
Introduces a
no-html-safe
rule to prevent the usage of thehtmlSafe
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.