Repository: rwjblue/ember-template-lint
Pull request #111 (2016-09-20 01:23:54)

Check for unsafe style concatenation
Ember has a runtime warning that says "Binding style attributes may introduce cross-site scripting vulnerabilities." It can only be avoided by always marking the bound value with `Ember.String.htmlSafe`. While we can't detect statically if you're always providing a safe string, we can detect cases common where it's impossible that you're doing so. 

Forbidden examples:

```hbs
<div style="{{make-background url}}">
<div style="background-style: url({{url}})">
```

Allowed examples:

```hbs
<div style={{make-background url}}>
<div style="background-image: url(/pretty.png)">
```


Patch:
diff --git a/README.md b/README.md
index c650324..2e574fc 100644
--- a/README.md
+++ b/README.md
@@ -322,6 +322,26 @@ This rule is configured with one boolean value:
 
   * boolean -- `true` for enabled / `false` for disabled
 
+#### style-concatentation
+
+Ember has a runtime warning that says "Binding style attributes may introduce cross-site scripting vulnerabilities." It can only be avoided by always marking the bound value with `Ember.String.htmlSafe`. While we can't detect statically if you're always providing a safe string, we can detect cases common where it's impossible that you're doing so. For example,
+
+```hbs
+<div style="background-style: url({{url}})">
+```
+
+is never safe because the implied string concatentation does not propagate `htmlSafe`. Any use of quotes is therefore forbidden. This is forbidden:
+
+```hbs
+<div style="{{make-background url}}">
+```
+
+whereas this is allowed:
+
+```hbs
+<div style={{make-background url}}>
+```
+
 ### Deprecations
 
 #### deprecated-each-syntax
diff --git a/lib/rules/index.js b/lib/rules/index.js
index a67c771..aa5c414 100644
--- a/lib/rules/index.js
+++ b/lib/rules/index.js
@@ -11,5 +11,6 @@ module.exports = {
   'nested-interactive': require('./lint-nested-interactive'),
   'inline-link-to': require('./lint-inline-link-to'),
   'deprecated-each-syntax': require('./deprecations/lint-deprecated-each-syntax'),
-  'invalid-interactive': require('./lint-invalid-interactive')
+  'invalid-interactive': require('./lint-invalid-interactive'),
+  'style-concatenation': require('./lint-style-concatenation')
 };
diff --git a/lib/rules/lint-style-concatenation.js b/lib/rules/lint-style-concatenation.js
new file mode 100644
index 0000000..bbb4129
--- /dev/null
+++ b/lib/rules/lint-style-concatenation.js
@@ -0,0 +1,26 @@
+'use strict';
+
+var AstNodeInfo = require('../helpers/ast-node-info');
+var buildPlugin = require('./base');
+
+module.exports = function(addonContext) {
+  var StyleConcat = buildPlugin(addonContext, 'style-concatenation');
+
+  StyleConcat.prototype.visitors = function() {
+    return {
+      ElementNode: function(node) {
+        var style = AstNodeInfo.findAttribute(node, 'style');
+        if (style && style.value.type === 'ConcatStatement') {
+          this.log({
+            message: 'You may not use string concatenation to build up styles',
+            line: style.loc && style.loc.start.line,
+            column: style.loc && style.loc.start.column,
+            source: this.sourceForNode(style)
+          });
+        }
+      }
+    };
+  };
+
+  return StyleConcat;
+};


Test patch:
diff --git a/test/unit/rules/lint-style-concatenation-test.js b/test/unit/rules/lint-style-concatenation-test.js
new file mode 100644
index 0000000..b64c57a
--- /dev/null
+++ b/test/unit/rules/lint-style-concatenation-test.js
@@ -0,0 +1,41 @@
+'use strict';
+
+var generateRuleTests = require('../../helpers/rule-test-harness');
+
+generateRuleTests({
+  name: 'style-concatenation',
+
+  config: true,
+
+  good: [
+    '<img style={{background-image url}}>',
+    '<img style="background-image: url(/foo.png)"}}>'
+  ],
+
+  bad: [
+    {
+      template: '<img style="background-image: {{url}}">',
+
+      result: {
+        rule: 'style-concatenation',
+        message: 'You may not use string concatenation to build up styles',
+        moduleId: 'layout.hbs',
+        source: 'style="background-image: {{url}}"',
+        line: 1,
+        column: 5
+      }
+    },
+    {
+      template: '<img style="{{background-image url}}">',
+
+      result: {
+        rule: 'style-concatenation',
+        message: 'You may not use string concatenation to build up styles',
+        moduleId: 'layout.hbs',
+        source: 'style="{{background-image url}}"',
+        line: 1,
+        column: 5
+      }
+    }
+  ]
+});