CVE-2026-54498
Summary
ViewComponent::Base#around_render can return HTML-unsafe strings that bypass the escaping behavior applied to normal #call return values. This creates an XSS risk when downstream applications use around_render to wrap, replace, instrument, or conditionally return content that includes user-controlled data.
The issue is especially dangerous in collection rendering because ViewComponent::Collection#render_in joins the per-item results and marks the entire output as html_safe, converting raw unsafe output into a trusted ActiveSupport::SafeBuffer.
Affected Code
Validated against:
- Repository commit: eea79445
- Ruby: 3.4.9
Relevant locations:
- lib/view_component/base.rb
- render_in
- around_render
- __vc_maybe_escape_html
- lib/view_component/template.rb
- InlineCall#safe_method_name_call
- lib/view_component/collection.rb
- Collection#render_in
Key code paths:
lib/view_component/base.rb
around_render do
render_template_for(@__vc_requested_details).to_s
end
lib/view_component/template.rb
proc do
__vc_maybe_escape_html(send(m)) do
Kernel.warn(...)
end
end
lib/view_component/collection.rb
components.map do |component|
component.render_in(view_context, &block)
end.join(rendered_spacer(view_context)).html_safe
Root Cause
Normal inline #call output is passed through __vc_maybe_escape_html, which escapes HTML-unsafe strings. However, when around_render itself returns a string, the returned value becomes the component render result without being passed through the same HTML-safety boundary.
This creates two different output-safety behaviors:
- #call returning unsafe string: escaped
- #around_render returning unsafe string: raw
Collection rendering then amplifies the issue by calling .html_safe on the joined result.
Proof of Concept
Run from the repository root:
$LOAD_PATH.unshift File.expand_path("lib", Dir.pwd)
require "action_controller/railtie"
require "rack/mock"
require "view_component/base"
class PocController < ActionController::Base; end
d
⚡ Watch CVE-2026-54498
Get an email if CVE-2026-54498 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.
Exploitation outlook
- Low exploitation risk0.31% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 24% of all EPSS-scored CVEs.
Advisory coverage (2)
External references
Embed the live status
— this badge updates automatically when the KEV or exploit status changes. How to embed it →
[](https://www.csirts.com/cve/CVE-2026-54498)