Skip to content

Linter Rule: Disallow unsafe ERB output inside <script> tags ​

Rule: erb-no-unsafe-script-interpolation

Description ​

ERB interpolation in <script> tags must call .to_json to safely serialize Ruby data into JavaScript. Without .to_json, user-controlled values can break out of string literals and execute arbitrary JavaScript.

Rationale ​

The main goal of this rule is to assert that Ruby data translates into JavaScript data, but never becomes JavaScript code. ERB output inside <script> tags is interpolated directly into the JavaScript context. Without proper serialization via .to_json, an attacker can inject arbitrary JavaScript by manipulating the interpolated value.

For example, consider:

erb
<script>
  var name = "<%= user.name %>";
Unsafe ERB output in `<script>` tag. Use `.to_json` to safely serialize values into JavaScript. (erb-no-unsafe-script-interpolation)
</script>

If user.name contains "; alert(1); ", the resulting JavaScript would execute arbitrary code. Using .to_json properly escapes the value and wraps it in quotes:

erb
<script>
  var name = <%= user.name.to_json %>;
</script>

Examples ​

✅ Good ​

erb
<script>
  var name = <%= user.name.to_json %>;
</script>
erb
<script>
  var data = <%== config.to_json %>;
</script>
erb
<script>
  <%= raw unsafe.to_json %>
</script>

🚫 Bad ​

erb
<script>
  var name = "<%= user.name %>";
Unsafe ERB output in `<script>` tag. Use `.to_json` to safely serialize values into JavaScript. (erb-no-unsafe-script-interpolation)
</script>
erb
<script>
  if (a < 1) { <%= unsafe %> }
Unsafe ERB output in `<script>` tag. Use `.to_json` to safely serialize values into JavaScript. (erb-no-unsafe-script-interpolation)
</script>
erb
<script>
  <%= @feature.html_safe %>
Unsafe ERB output in `<script>` tag. Use `.to_json` to safely serialize values into JavaScript. (erb-no-unsafe-script-interpolation)
</script>

References ​

Released under the MIT License.