CVE-2022-27777 - How a Simple XSS Bug Slipped into Rails Action View Tag Helpers

Modern web frameworks are always evolving to help developers build apps faster and more safely. But even the best can sometimes miss something important. That’s exactly what happened with CVE-2022-27777, a cross-site scripting (XSS) vulnerability in Rails’ Action View tag helpers. Let’s break down how this bug works, see some code, and learn what it means for your Rails apps.

1. What is CVE-2022-27777?

CVE-2022-27777 is a vulnerability affecting Action View’s tag helper methods in Rails, specifically versions >= 5.2. and < 7..3.1. Due to insufficient escaping, an attacker who can control parts of your form inputs could inject malicious JavaScript—classic XSS.

Why is it Dangerous?

If your Rails app lets users supply values that are inserted into tag helper attributes, and those values aren’t properly sanitized, attackers can run scripts in your users’ browsers. That can steal cookies, hijack sessions, or deface pages.

2. Where Did the Bug Happen?

Action View’s tag helpers like tag, content_tag, and tag.* are utility methods that make writing HTML in Rails much easier. Here’s a common use-case:

# In a view .erb file
<%= tag.img(src: user_avatar_url, alt: "User avatar") %>

Under the hood, tag.img builds an HTML <img> tag with those given attributes.

The Problem:

If input like user_avatar_url here is provided by users, and you do something like

<%= tag.img(src: params[:src], alt: "User avatar") %>

If params[:src] is not sanitized, a crafted value can inject script.

Suppose you have a controller action

def avatar
  @src = params[:src]
end

In your view

<%= tag.img(src: @src, alt: "Profile picture") %>

Now, a malicious user could visit

/avatar?src=evil.jpg" onerror="alert('Gotcha!')"

The tag helper generates

<img src="evil.jpg" onerror="alert('Gotcha!')" alt="Profile picture">

When this image can’t load, the browser runs alert('Gotcha!').

4. Why Did This Happen?

Older versions of Action View did not strictly escape attribute values. So, any double quote (") or dangerous character in an attribute value could “break out” and insert new HTML attributes/events—like onerror.

From the rails security disclosure:

> “Certain previously considered ‘safe’ helpers in Action View could allow unescaped attributes to make it into forms.”

Upgrade Your Rails!

If your Rails is older than 5.2.6.3, 6..4.8, 6.1.7.2, or 7..3.1, you need to upgrade now.  
The patches tighten the escaping of attribute values.

Example of patched behavior:  
Passing quotes or special chars gets properly encoded.

tag.img(src: 'evil.jpg" onerror="alert(1)')
# => <img src="evil.jpg&quot; onerror=&quot;alert(1)" />

Escape Any User Input

Never, ever put user input directly into tag helpers without sanitization.

Sanitize input

<%= tag.img(src: ERB::Util.url_encode(@src), alt: "Profile picture") %>

Or, better yet, only allow valid image paths from the server.

Full Proof-of-Concept (Rails < 7..3.1)

# app/controllers/profile_controller.rb
def show
  @avatar = params[:avatar]
end
<!-- app/views/profile/show.html.erb -->
<%= tag.img(src: @avatar, alt: "User avatar") %>

Visiting

/profile/show?avatar=abc.jpg" onerror="alert('XSSed!')

- CVE-2022-27777 on NIST
- Patch in Rails codebase
- Rails security announcement
- OWASP XSS Prevention Cheat Sheet

8. Final Advice

All frameworks—even Rails—can have simple, sneaky security bugs. Keep your gems updated, don’t blindly trust any user input, and review your code for places where tag helpers use raw values from forms or URLs.

Check your Rails version today—and patch ASAP if you’re vulnerable to CVE-2022-27777!

Timeline

Published on: 05/26/2022 17:15:00 UTC
Last modified on: 06/07/2022 14:35:00 UTC