Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Security/Open aware of URI.open #8894

Merged
merged 1 commit into from Oct 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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