Sha256: d88a2566828d3aa3a53e06ea3811bc27ec92f54db1796800ab8d57b29710538c

Contents?: true

Size: 1.78 KB

Versions: 13

Compression:

Stored size: 1.78 KB

Contents

# frozen_string_literal: true

require 'rack/protection'

module Rack
  module Protection
    ##
    # Prevented attack::   CSRF
    # Supported browsers:: all
    # More infos::         http://flask.pocoo.org/docs/0.10/security/#json-security
    #                      http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
    #
    # JSON GET APIs are vulnerable to being embedded as JavaScript when the
    # Array prototype has been patched to track data. Checks the referrer
    # even on GET requests if the content type is JSON.
    #
    # If request includes Origin HTTP header, defers to HttpOrigin to determine
    # if the request is safe. Please refer to the documentation for more info.
    #
    # The `:allow_if` option can be set to a proc to use custom allow/deny logic.
    class JsonCsrf < Base
      default_options allow_if: nil

      alias react deny

      def call(env)
        request               = Request.new(env)
        status, headers, body = app.call(env)

        if has_vector?(request, headers)
          warn env, "attack prevented by #{self.class}"

          react_and_close(env, body) or [status, headers, body]
        else
          [status, headers, body]
        end
      end

      def has_vector?(request, headers)
        return false if request.xhr?
        return false if options[:allow_if]&.call(request.env)
        return false unless headers['Content-Type'].to_s.split(';', 2).first =~ %r{^\s*application/json\s*$}

        origin(request.env).nil? and referrer(request.env) != request.host
      end

      def react_and_close(env, body)
        reaction = react(env)

        close_body(body) if reaction

        reaction
      end

      def close_body(body)
        body.close if body.respond_to?(:close)
      end
    end
  end
end

Version data entries

13 entries across 13 versions & 2 rubygems

Version Path
rack-protection-3.2.0 lib/rack/protection/json_csrf.rb
rack-protection-3.1.0 lib/rack/protection/json_csrf.rb
rubypitaya-3.12.5 ./lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.5/lib/rack/protection/json_csrf.rb
rack-protection-3.0.6 lib/rack/protection/json_csrf.rb
rubypitaya-3.12.4 ./lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.5/lib/rack/protection/json_csrf.rb
rubypitaya-3.12.3 ./lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.5/lib/rack/protection/json_csrf.rb
rubypitaya-3.12.2 ./lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rack-protection-3.0.5/lib/rack/protection/json_csrf.rb
rack-protection-3.0.5 lib/rack/protection/json_csrf.rb
rack-protection-3.0.4 lib/rack/protection/json_csrf.rb
rack-protection-3.0.3 lib/rack/protection/json_csrf.rb
rack-protection-3.0.2 lib/rack/protection/json_csrf.rb
rack-protection-3.0.1 lib/rack/protection/json_csrf.rb
rack-protection-3.0.0 lib/rack/protection/json_csrf.rb