VYPR
Moderate severityNVD Advisory· Published May 26, 2022· Updated Aug 3, 2024

CVE-2022-22577

CVE-2022-22577

Description

An XSS Vulnerability in Action Pack >= 5.2.0 and < 5.2.0 that could allow an attacker to bypass CSP for non HTML like responses.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

An XSS vulnerability in Action Pack allows CSP bypass for non-HTML responses, affecting Rails 5.2.0 through 7.0.2.3.

Vulnerability

An XSS vulnerability exists in Action Pack (the controller and routing layer of Ruby on Rails) that allows an attacker to bypass Content Security Policy (CSP) for responses with non-HTML content types, such as JSON or XML [1][4]. The issue affects Rails versions 5.2.0 to 5.2.7.0, 6.0.0 to 6.0.4.7, 6.1.0 to 6.1.5.0, and 7.0.0 to 7.0.2.3 [2]. The vulnerability occurs because the CSP header is not properly enforced when the response's Content-Type is not text/html, potentially allowing injected scripts to execute without the intended CSP restrictions.

Exploitation

An attacker must be able to inject malicious content into a non-HTML response, typically through user-supplied data that is reflected in the response body (e.g., a JSON API endpoint that echoes input). The attacker crafts a request that results in a response with a non-HTML content type containing embedded JavaScript. Because the CSP header may be missing or ineffective for such responses, the injected script can execute in the victim's browser when the response is processed [1][4]. No authentication or special network position is required if the vulnerable endpoint is publicly accessible.

Impact

Successful exploitation leads to cross-site scripting (XSS) attacks, allowing the attacker to execute arbitrary JavaScript in the context of the victim's session. This can result in data theft, session hijacking, defacement, or other malicious actions depending on the application's functionality and the victim's privileges [1][4].

Mitigation

The vulnerability is fixed in Rails versions 5.2.7.1, 6.0.4.8, 6.1.5.1, and 7.0.2.4, released on April 26, 2022 [2]. Users should upgrade to these versions or later. No workaround is documented; upgrading is the recommended action.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
actionpackRubyGems
>= 5.2.0, < 5.2.7.15.2.7.1
actionpackRubyGems
>= 6.0.0, < 6.0.4.86.0.4.8
actionpackRubyGems
>= 6.1.0, < 6.1.5.16.1.5.1
actionpackRubyGems
>= 7.0.0, < 7.0.2.47.0.2.4

Affected products

2

Patches

4
2b820a2a69fa

Merge pull request #44635 from imtayadeway/tjw/api-csp-i

https://github.com/rails/railsAaron PattersonMar 8, 2022via ghsa
3 files changed · +19 7
  • actionpack/CHANGELOG.md+4 0 modified
    @@ -1,3 +1,7 @@
    +*   Allow Content Security Policy DSL to generate for API responses.
    +
    +    *Tim Wade*
    +
     ## Rails 6.1.5 (March 09, 2022) ##
     
     *   Fix `content_security_policy` returning invalid directives.
    
  • actionpack/lib/action_dispatch/http/content_security_policy.rb+0 7 modified
    @@ -18,7 +18,6 @@ def call(env)
             request = ActionDispatch::Request.new env
             _, headers, _ = response = @app.call(env)
     
    -        return response unless html_response?(headers)
             return response if policy_present?(headers)
     
             if policy = request.content_security_policy
    @@ -32,12 +31,6 @@ def call(env)
           end
     
           private
    -        def html_response?(headers)
    -          if content_type = headers[CONTENT_TYPE]
    -            /html/.match?(content_type)
    -          end
    -        end
    -
             def header_name(request)
               if request.content_security_policy_report_only
                 POLICY_REPORT_ONLY
    
  • actionpack/test/dispatch/content_security_policy_test.rb+15 0 modified
    @@ -385,6 +385,11 @@ class PolicyController < ActionController::Base
     
         content_security_policy_report_only only: :report_only
     
    +    content_security_policy only: :api do |p|
    +      p.default_src :none
    +      p.frame_ancestors :none
    +    end
    +
         def index
           head :ok
         end
    @@ -413,6 +418,10 @@ def no_policy
           head :ok
         end
     
    +    def api
    +      render json: {}
    +    end
    +
         private
           def condition?
             params[:condition] == "true"
    @@ -429,6 +438,7 @@ def condition?
           get "/script-src", to: "policy#script_src"
           get "/style-src", to: "policy#style_src"
           get "/no-policy", to: "policy#no_policy"
    +      get "/api", to: "policy#api"
         end
       end
     
    @@ -500,6 +510,11 @@ def test_generates_no_content_security_policy
         assert_nil response.headers["Content-Security-Policy-Report-Only"]
       end
     
    +  def test_generates_api_security_policy
    +    get "/api"
    +    assert_policy "default-src 'none'; frame-ancestors 'none'"
    +  end
    +
       private
         def assert_policy(expected, report_only: false)
           assert_response :success
    
5299b57d596e

Merge pull request #44635 from imtayadeway/tjw/api-csp-i

https://github.com/rails/railsAaron PattersonMar 8, 2022via ghsa
3 files changed · +19 7
  • actionpack/CHANGELOG.md+4 0 modified
    @@ -1,3 +1,7 @@
    +*   Allow Content Security Policy DSL to generate for API responses.
    +
    +    *Tim Wade*
    +
     ## Rails 6.0.4.7 (March 08, 2022) ##
     
     *   No changes.
    
  • actionpack/lib/action_dispatch/http/content_security_policy.rb+0 7 modified
    @@ -17,7 +17,6 @@ def call(env)
             request = ActionDispatch::Request.new env
             _, headers, _ = response = @app.call(env)
     
    -        return response unless html_response?(headers)
             return response if policy_present?(headers)
     
             if policy = request.content_security_policy
    @@ -31,12 +30,6 @@ def call(env)
           end
     
           private
    -        def html_response?(headers)
    -          if content_type = headers[CONTENT_TYPE]
    -            content_type =~ /html/
    -          end
    -        end
    -
             def header_name(request)
               if request.content_security_policy_report_only
                 POLICY_REPORT_ONLY
    
  • actionpack/test/dispatch/content_security_policy_test.rb+15 0 modified
    @@ -353,6 +353,11 @@ class PolicyController < ActionController::Base
     
         content_security_policy_report_only only: :report_only
     
    +    content_security_policy only: :api do |p|
    +      p.default_src :none
    +      p.frame_ancestors :none
    +    end
    +
         def index
           head :ok
         end
    @@ -381,6 +386,10 @@ def no_policy
           head :ok
         end
     
    +    def api
    +      render json: {}
    +    end
    +
         private
           def condition?
             params[:condition] == "true"
    @@ -397,6 +406,7 @@ def condition?
           get "/script-src", to: "policy#script_src"
           get "/style-src", to: "policy#style_src"
           get "/no-policy", to: "policy#no_policy"
    +      get "/api", to: "policy#api"
         end
       end
     
    @@ -468,6 +478,11 @@ def test_generates_no_content_security_policy
         assert_nil response.headers["Content-Security-Policy-Report-Only"]
       end
     
    +  def test_generates_api_security_policy
    +    get "/api"
    +    assert_policy "default-src 'none'; frame-ancestors 'none'"
    +  end
    +
       private
         def assert_policy(expected, report_only: false)
           assert_response :success
    
8198d7c4acca

Merge pull request #44635 from imtayadeway/tjw/api-csp-i

https://github.com/rails/railsAaron PattersonMar 8, 2022via ghsa
3 files changed · +19 7
  • actionpack/CHANGELOG.md+4 0 modified
    @@ -1,3 +1,7 @@
    +*   Allow Content Security Policy DSL to generate for API responses.
    +
    +    *Tim Wade*
    +
     ## Rails 7.0.2.3 (March 08, 2022) ##
     
     *   No changes.
    
  • actionpack/lib/action_dispatch/http/content_security_policy.rb+0 7 modified
    @@ -17,7 +17,6 @@ def call(env)
             request = ActionDispatch::Request.new env
             _, headers, _ = response = @app.call(env)
     
    -        return response unless html_response?(headers)
             return response if policy_present?(headers)
     
             if policy = request.content_security_policy
    @@ -31,12 +30,6 @@ def call(env)
           end
     
           private
    -        def html_response?(headers)
    -          if content_type = headers[CONTENT_TYPE]
    -            /html/.match?(content_type)
    -          end
    -        end
    -
             def header_name(request)
               if request.content_security_policy_report_only
                 POLICY_REPORT_ONLY
    
  • actionpack/test/dispatch/content_security_policy_test.rb+15 0 modified
    @@ -395,6 +395,11 @@ class PolicyController < ActionController::Base
     
         content_security_policy_report_only only: :report_only
     
    +    content_security_policy only: :api do |p|
    +      p.default_src :none
    +      p.frame_ancestors :none
    +    end
    +
         def index
           head :ok
         end
    @@ -423,6 +428,10 @@ def no_policy
           head :ok
         end
     
    +    def api
    +      render json: {}
    +    end
    +
         private
           def condition?
             params[:condition] == "true"
    @@ -439,6 +448,7 @@ def condition?
           get "/script-src", to: "policy#script_src"
           get "/style-src", to: "policy#style_src"
           get "/no-policy", to: "policy#no_policy"
    +      get "/api", to: "policy#api"
         end
       end
     
    @@ -510,6 +520,11 @@ def test_generates_no_content_security_policy
         assert_nil response.headers["Content-Security-Policy-Report-Only"]
       end
     
    +  def test_generates_api_security_policy
    +    get "/api"
    +    assert_policy "default-src 'none'; frame-ancestors 'none'"
    +  end
    +
       private
         def assert_policy(expected, report_only: false)
           assert_response :success
    
d2253115ac2b

Merge pull request #44635 from imtayadeway/tjw/api-csp-i

https://github.com/rails/railsAaron PattersonMar 8, 2022via ghsa
3 files changed · +19 9
  • actionpack/CHANGELOG.md+4 1 modified
    @@ -1,8 +1,11 @@
    +*   Allow Content Security Policy DSL to generate for API responses.
    +
    +    *Tim Wade*
    +
     ## Rails 5.2.7 (March 10, 2022) ##
     
     *   No changes.
     
    -
     ## Rails 5.2.6.3 (March 08, 2022) ##
     
     *   No changes.
    
  • actionpack/lib/action_dispatch/http/content_security_policy.rb+0 8 modified
    @@ -17,7 +17,6 @@ def call(env)
             request = ActionDispatch::Request.new env
             _, headers, _ = response = @app.call(env)
     
    -        return response unless html_response?(headers)
             return response if policy_present?(headers)
     
             if policy = request.content_security_policy
    @@ -30,13 +29,6 @@ def call(env)
           end
     
           private
    -
    -        def html_response?(headers)
    -          if content_type = headers[CONTENT_TYPE]
    -            content_type =~ /html/
    -          end
    -        end
    -
             def header_name(request)
               if request.content_security_policy_report_only
                 POLICY_REPORT_ONLY
    
  • actionpack/test/dispatch/content_security_policy_test.rb+15 0 modified
    @@ -343,6 +343,11 @@ class PolicyController < ActionController::Base
     
         content_security_policy_report_only only: :report_only
     
    +    content_security_policy only: :api do |p|
    +      p.default_src :none
    +      p.frame_ancestors :none
    +    end
    +
         def index
           head :ok
         end
    @@ -367,6 +372,10 @@ def no_policy
           head :ok
         end
     
    +    def api
    +      render json: {}
    +    end
    +
         private
           def condition?
             params[:condition] == "true"
    @@ -382,6 +391,7 @@ def condition?
           get "/report-only", to: "policy#report_only"
           get "/script-src", to: "policy#script_src"
           get "/no-policy", to: "policy#no_policy"
    +      get "/api", to: "policy#api"
         end
       end
     
    @@ -448,6 +458,11 @@ def test_generates_no_content_security_policy
         assert_nil response.headers["Content-Security-Policy-Report-Only"]
       end
     
    +  def test_generates_api_security_policy
    +    get "/api"
    +    assert_policy "default-src 'none'; frame-ancestors 'none'"
    +  end
    +
       private
     
         def assert_policy(expected, report_only: false)
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

15

News mentions

0

No linked articles in our index yet.