Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-54163

CVE-2026-54163: secure_headers CSP Injection XSS Flaw

CVE-2026-54163 is a Content Security Policy injection vulnerability in secure_headers that enables XSS attacks through improper input sanitization. This article covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-54163 Overview

CVE-2026-54163 is a Content Security Policy (CSP) directive injection vulnerability in the secure_headers Ruby gem maintained by GitHub. Versions prior to 7.3.0 fail to scrub ;, \r, and \n characters when building the sandbox, plugin-types, and report-to directives. Attackers who control input passed to SecureHeaders.override_content_security_policy_directives or the corresponding append APIs can inject arbitrary CSP directives. The injection enables cross-site scripting (XSS) [CWE-79] reachability or exfiltration of CSP violation reports to attacker-controlled endpoints. The issue is fixed in version 7.3.0.

Critical Impact

An attacker can prepend a permissive directive such as script-src 'unsafe-inline' * before the legitimate script-src, neutralizing the protections that secure_headers is intended to enforce.

Affected Products

  • secure_headers Ruby gem versions prior to 7.3.0
  • Ruby and Rails applications that pass untrusted input to CSP override/append APIs
  • Applications using the :sandbox, :plugin_types, or :report_to directives with dynamic values

Discovery Timeline

  • 2026-07-17 - CVE-2026-54163 published to NVD
  • 2026-07-23 - Last updated in NVD database

Technical Details for CVE-2026-54163

Vulnerability Analysis

The secure_headers library constructs the Content-Security-Policy header by joining directives with ; separators. The helper functions build_sandbox_list_directive, build_media_type_list_directive, and build_report_to_directive interpolate caller-supplied strings directly into the header value. Because these builders never remove or encode CSP delimiter characters, an input containing ; terminates the current directive and begins a new one under attacker control.

The practical consequence is CSP downgrade. An injected script-src 'unsafe-inline' * directive appears before the legitimate policy and, per CSP precedence rules, becomes the enforced policy for scripts. Applications that relied on secure_headers to block inline JavaScript lose that protection, restoring XSS reachability in the served pages. Attackers can also inject a report-uri or report-to target to exfiltrate CSP violation data.

Root Cause

The root cause is missing input sanitization in the directive builder functions. Values reaching build_sandbox_list_directive, build_media_type_list_directive, and build_report_to_directive are joined and emitted without checking for the header delimiters (;, \r, \n) that separate CSP directives and HTTP headers.

Attack Vector

Exploitation requires that attacker-controllable input flows into one of the vulnerable append or override APIs for the :sandbox, :plugin_types, or :report_to directives. The attacker supplies a value containing ; followed by a permissive directive. User interaction is required to trigger the resulting XSS through a browser rendering the downgraded CSP.

ruby
# Patch from lib/secure_headers/headers/content_security_policy.rb
# Source: https://github.com/github/secure_headers/commit/286a79dea80c6a9be4ca93e0f284c923cf77e539
       elsif sandbox_list && sandbox_list.any?
         [
           symbol_to_hyphen_case(directive),
-          sandbox_list.uniq
+          scrub_directive_value(directive, sandbox_list.uniq.join(" "))
         ].join(" ")
       end
     end

The fix routes joined directive values through scrub_directive_value, which strips characters that would break out of the current directive context. See the GitHub Security Advisory GHSA-rqq5-2gf9-4w4q for full details.

Detection Methods for CVE-2026-54163

Indicators of Compromise

  • Content-Security-Policy response headers containing duplicated directives such as two script-src entries
  • CSP header values with unexpected 'unsafe-inline', 'unsafe-eval', or wildcard * sources in policies that should not include them
  • CSP report-uri or report-to targets pointing to domains outside the organization's telemetry infrastructure
  • Unexpected inline scripts executing on pages that previously blocked them

Detection Strategies

  • Inventory Ruby applications and compare the secure_headers gem version in Gemfile.lock against the fixed version 7.3.0
  • Perform static analysis to trace user-controlled input into override_content_security_policy_directives, append_content_security_policy_directives, and related APIs targeting :sandbox, :plugin_types, or :report_to
  • Run automated HTTP response scanners that parse the CSP header and flag multiple occurrences of the same directive
  • Fuzz test endpoints that build CSP dynamically with payloads containing ;, \r, and \n

Monitoring Recommendations

  • Log outbound CSP report submissions and alert on report endpoints outside allowlisted domains
  • Monitor HTTP response headers at the edge (WAF, CDN, or reverse proxy) and alert on CSP structural anomalies
  • Track deployment inventories for outdated versions of secure_headers across all Ruby services

How to Mitigate CVE-2026-54163

Immediate Actions Required

  • Upgrade secure_headers to version 7.3.0 or later in all Ruby applications
  • Audit all call sites of override_content_security_policy_directives and append APIs for untrusted input reaching :sandbox, :plugin_types, or :report_to
  • Validate and allowlist user-supplied values before passing them to any CSP builder API
  • Re-review CSP policies to confirm they still enforce the intended restrictions post-patch

Patch Information

The fix ships in secure_headers 7.3.0. The patch introduces scrub_directive_value and applies it to the sandbox, media-type, and report-to directive builders. See the GitHub Secure Headers Release v7.3.0 and the patch commit 286a79d.

Workarounds

  • Reject or strip ;, \r, and \n characters from any user input before it is passed to secure_headers CSP APIs
  • Avoid using dynamic values for the :sandbox, :plugin_types, and :report_to directives and use a static allowlist instead
  • Deploy an edge proxy rule that rewrites or drops CSP headers containing duplicate directives until the gem is upgraded
bash
# Update the gem to the fixed version
bundle update secure_headers --strict
grep secure_headers Gemfile.lock
# Confirm output shows: secure_headers (7.3.0) or later

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.