diff --git a/changelog/new_allow_http_protocol_to_bundler_insecure_protocol_source.md b/changelog/new_allow_http_protocol_to_bundler_insecure_protocol_source.md new file mode 100644 index 00000000000..85485359ada --- /dev/null +++ b/changelog/new_allow_http_protocol_to_bundler_insecure_protocol_source.md @@ -0,0 +1 @@ +* [#10103](https://github.com/rubocop/rubocop/issues/10103): Add `AllowHttpProtocol` option to `Bundler/InsecureProtocolSource`. ([@koic][]) diff --git a/config/default.yml b/config/default.yml index 02c9f49f55e..61823bc2713 100644 --- a/config/default.yml +++ b/config/default.yml @@ -209,6 +209,7 @@ Bundler/InsecureProtocolSource: 'https://rubygems.org' if possible, or 'http://rubygems.org' if not. Enabled: true VersionAdded: '0.50' + AllowHttpProtocol: true Include: - '**/*.gemfile' - '**/Gemfile' diff --git a/lib/rubocop/cop/bundler/insecure_protocol_source.rb b/lib/rubocop/cop/bundler/insecure_protocol_source.rb index 6a852c0a2f2..c7b24a879a0 100644 --- a/lib/rubocop/cop/bundler/insecure_protocol_source.rb +++ b/lib/rubocop/cop/bundler/insecure_protocol_source.rb @@ -16,6 +16,9 @@ module Bundler # However, you should strongly prefer `https://` where possible, as it is # more secure. # + # If you don't allow `http://`, please set `false` to `AllowHttpProtocol`. + # This option is `true` by default for safe autocorrection. + # # @example # # bad # source :gemcutter @@ -24,8 +27,17 @@ module Bundler # # # good # source 'https://rubygems.org' # strongly recommended + # + # @example AllowHttpProtocol: true (default) + # + # # good # source 'http://rubygems.org' # use only if HTTPS is unavailable # + # @example AllowHttpProtocol: false + # + # # bad + # source 'http://rubygems.org' + # class InsecureProtocolSource < Base include RangeHelp extend AutoCorrector @@ -34,29 +46,40 @@ class InsecureProtocolSource < Base 'are insecure. ' \ "Please change your source to 'https://rubygems.org' " \ "if possible, or 'http://rubygems.org' if not." + MSG_HTTP_PROTOCOL = 'Use `https://rubygems.org` instead of `http://rubygems.org`.' RESTRICT_ON_SEND = %i[source].freeze # @!method insecure_protocol_source?(node) def_node_matcher :insecure_protocol_source?, <<~PATTERN (send nil? :source - $(sym ${:gemcutter :rubygems :rubyforge})) + ${(sym :gemcutter) (sym :rubygems) (sym :rubyforge) (:str "http://rubygems.org")}) PATTERN def on_send(node) - insecure_protocol_source?(node) do |source_node, source| - message = format(MSG, source: source) - - add_offense( - source_node, - message: message - ) do |corrector| - corrector.replace( - source_node, "'https://rubygems.org'" - ) + insecure_protocol_source?(node) do |source_node| + source = source_node.value + use_http_protocol = source == 'http://rubygems.org' + + return if allow_http_protocol? && use_http_protocol + + message = if use_http_protocol + MSG_HTTP_PROTOCOL + else + format(MSG, source: source) + end + + add_offense(source_node, message: message) do |corrector| + corrector.replace(source_node, "'https://rubygems.org'") end end end + + private + + def allow_http_protocol? + cop_config.fetch('AllowHttpProtocol', true) + end end end end diff --git a/spec/rubocop/cop/bundler/insecure_protocol_source_spec.rb b/spec/rubocop/cop/bundler/insecure_protocol_source_spec.rb index 131c03c5887..b07a0e34df0 100644 --- a/spec/rubocop/cop/bundler/insecure_protocol_source_spec.rb +++ b/spec/rubocop/cop/bundler/insecure_protocol_source_spec.rb @@ -33,4 +33,35 @@ source 'https://rubygems.org' RUBY end + + it "does not register an offense when using `source 'https://rubygems.org'`" do + expect_no_offenses(<<~RUBY) + source 'https://rubygems.org' + RUBY + end + + context 'when `AllowHttpProtocol: true`' do + let(:cop_config) { { 'AllowHttpProtocol' => true } } + + it "does not register an offense when using `source 'http://rubygems.org'`" do + expect_no_offenses(<<~RUBY) + source 'http://rubygems.org' + RUBY + end + end + + context 'when `AllowHttpProtocol: false`' do + let(:cop_config) { { 'AllowHttpProtocol' => false } } + + it "registers an offense when using `source 'http://rubygems.org'`" do + expect_offense(<<~RUBY) + source 'http://rubygems.org' + ^^^^^^^^^^^^^^^^^^^^^ Use `https://rubygems.org` instead of `http://rubygems.org`. + RUBY + + expect_correction(<<~RUBY) + source 'https://rubygems.org' + RUBY + end + end end