Skip to content

Commit

Permalink
Merge pull request #8894 from koic/fix_a_false_negative_for_security_…
Browse files Browse the repository at this point in the history
…open

Make `Security/Open` aware of `URI.open`
  • Loading branch information
koic committed Oct 16, 2020
2 parents eeb00eb + 7da3629 commit be8b179
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -16,6 +16,7 @@
* [#7966](https://github.com/rubocop-hq/rubocop/issues/7966): **(Breaking)** Enable all pending cops for RuboCop 1.0. ([@koic][])
* [#8490](https://github.com/rubocop-hq/rubocop/pull/8490): **(Breaking)** Change logic for cop department name computation. Cops inside deep namespaces (5 or more levels deep) now belong to departments with names that are calculated by joining module names starting from the third one with slashes as separators. For example, cop `Rubocop::Cop::Foo::Bar::Baz` now belongs to `Foo/Bar` department (previously it was `Bar`). ([@dsavochkin][])
* [#8692](https://github.com/rubocop-hq/rubocop/pull/8692): Default changed to disallow `Layout/TrailingWhitespace` in heredoc. ([@marcandre][])
* [#8894](https://github.com/rubocop-hq/rubocop/issues/8894): Make `Security/Open` aware of `URI.open`. ([@koic][])

## 0.93.1 (2020-10-12)

Expand Down
3 changes: 2 additions & 1 deletion config/default.yml
Expand Up @@ -2415,9 +2415,10 @@ Security/MarshalLoad:
VersionAdded: '0.47'

Security/Open:
Description: 'The use of Kernel#open represents a serious security risk.'
Description: 'The use of `Kernel#open` and `URI.open` represent a serious security risk.'
Enabled: true
VersionAdded: '0.53'
VersionChanged: '0.94'
Safe: false

Security/YAMLLoad:
Expand Down
15 changes: 8 additions & 7 deletions docs/modules/ROOT/pages/cops_security.adoc
Expand Up @@ -117,23 +117,24 @@ Marshal.load(Marshal.dump({}))
| No
| No
| 0.53
| -
| 0.94
|===

This cop checks for the use of `Kernel#open`.
This cop checks for the use of `Kernel#open` and `URI.open`.

`Kernel#open` enables not only file access but also process invocation
by prefixing a pipe symbol (e.g., `open("| ls")`). So, it may lead to
a serious security risk by using variable input to the argument of
`Kernel#open`. It would be better to use `File.open`, `IO.popen` or
`URI#open` explicitly.
`Kernel#open` and `URI.open` enable not only file access but also process
invocation by prefixing a pipe symbol (e.g., `open("| ls")`).
So, it may lead to a serious security risk by using variable input to
the argument of `Kernel#open` and `URI.open`. It would be better to use
`File.open`, `IO.popen` or `URI.parse#open` explicitly.

=== Examples

[source,ruby]
----
# bad
open(something)
URI.open(something)
# good
File.open(something)
Expand Down
22 changes: 12 additions & 10 deletions lib/rubocop/cop/security/open.rb
Expand Up @@ -3,35 +3,37 @@
module RuboCop
module Cop
module Security
# This cop checks for the use of `Kernel#open`.
# This cop checks for the use of `Kernel#open` and `URI.open`.
#
# `Kernel#open` enables not only file access but also process invocation
# by prefixing a pipe symbol (e.g., `open("| ls")`). So, it may lead to
# a serious security risk by using variable input to the argument of
# `Kernel#open`. It would be better to use `File.open`, `IO.popen` or
# `URI#open` explicitly.
# `Kernel#open` and `URI.open` enable not only file access but also process
# invocation by prefixing a pipe symbol (e.g., `open("| ls")`).
# So, it may lead to a serious security risk by using variable input to
# the argument of `Kernel#open` and `URI.open`. It would be better to use
# `File.open`, `IO.popen` or `URI.parse#open` explicitly.
#
# @example
# # bad
# open(something)
# URI.open(something)
#
# # good
# File.open(something)
# IO.popen(something)
# URI.parse(something).open
class Open < Base
MSG = 'The use of `Kernel#open` is a serious security risk.'
MSG = 'The use of `%<receiver>sopen` is a serious security risk.'
RESTRICT_ON_SEND = %i[open].freeze

def_node_matcher :open?, <<~PATTERN
(send nil? :open $!str ...)
(send ${nil? (const {nil? cbase} :URI)} :open $!str ...)
PATTERN

def on_send(node)
open?(node) do |code|
open?(node) do |receiver, code|
return if safe?(code)

add_offense(node.loc.selector)
message = format(MSG, receiver: receiver ? "#{receiver.source}." : 'Kernel#')
add_offense(node.loc.selector, message: message)
end
end

Expand Down
14 changes: 14 additions & 0 deletions spec/rubocop/cop/security/open_spec.rb
Expand Up @@ -31,6 +31,20 @@
RUBY
end

it 'registers an offense for `URI.open` with string that starts with a pipe' do
expect_offense(<<~'RUBY')
URI.open("| #{foo}")
^^^^ The use of `URI.open` is a serious security risk.
RUBY
end

it 'registers an offense for `::URI.open` with string that starts with a pipe' do
expect_offense(<<~'RUBY')
::URI.open("| #{foo}")
^^^^ The use of `::URI.open` is a serious security risk.
RUBY
end

it 'accepts open as variable' do
expect_no_offenses('open = something')
end
Expand Down

0 comments on commit be8b179

Please sign in to comment.