-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11140 from Bo98/io-read-cop
Add cop for IO.read usage
- Loading branch information
Showing
6 changed files
with
117 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# typed: true | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Homebrew | ||
# This cop restricts usage of IO.read functions for security reasons. | ||
# | ||
# @api private | ||
class IORead < Base | ||
MSG = "The use of `IO.%<method>s` is a security risk." | ||
RESTRICT_ON_SEND = [:read, :readlines].freeze | ||
|
||
def on_send(node) | ||
return if node.receiver != s(:const, nil, :IO) | ||
return if safe?(node.arguments.first) | ||
|
||
add_offense(node, message: format(MSG, method: node.method_name)) | ||
end | ||
|
||
private | ||
|
||
def safe?(node) | ||
if node.str_type? | ||
!node.str_content.empty? && !node.str_content.start_with?("|") | ||
elsif node.dstr_type? || (node.send_type? && node.method?(:+)) | ||
safe?(node.children.first) | ||
else | ||
false | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# typed: false | ||
# frozen_string_literal: true | ||
|
||
require "rubocops/io_read" | ||
|
||
describe RuboCop::Cop::Homebrew::IORead do | ||
subject(:cop) { described_class.new } | ||
|
||
it "reports an offense when `IO.read` is used with a pipe character" do | ||
expect_offense(<<~RUBY) | ||
IO.read("|echo test") | ||
^^^^^^^^^^^^^^^^^^^^^ The use of `IO.read` is a security risk. | ||
RUBY | ||
end | ||
|
||
it "does not report an offense when `IO.read` is used without a pipe character" do | ||
expect_no_offenses(<<~RUBY) | ||
IO.read("file.txt") | ||
RUBY | ||
end | ||
|
||
it "reports an offense when `IO.read` is used with untrustworthy input" do | ||
expect_offense(<<~RUBY) | ||
input = "input value from an unknown source" | ||
IO.read(input) | ||
^^^^^^^^^^^^^^ The use of `IO.read` is a security risk. | ||
RUBY | ||
end | ||
|
||
it "reports an offense when `IO.read` is used with a dynamic string starting with a pipe character" do | ||
expect_offense(<<~'RUBY') | ||
input = "test" | ||
IO.read("|echo #{input}") | ||
^^^^^^^^^^^^^^^^^^^^^^^^^ The use of `IO.read` is a security risk. | ||
RUBY | ||
end | ||
|
||
it "reports an offense when `IO.read` is used with a dynamic string at the start" do | ||
expect_offense(<<~'RUBY') | ||
input = "|echo test" | ||
IO.read("#{input}.txt") | ||
^^^^^^^^^^^^^^^^^^^^^^^ The use of `IO.read` is a security risk. | ||
RUBY | ||
end | ||
|
||
it "does not report an offense when `IO.read` is used with a dynamic string safely" do | ||
expect_no_offenses(<<~'RUBY') | ||
input = "test" | ||
IO.read("somefile#{input}.txt") | ||
RUBY | ||
end | ||
|
||
it "reports an offense when `IO.read` is used with a concatenated string starting with a pipe character" do | ||
expect_offense(<<~'RUBY') | ||
input = "|echo test" | ||
IO.read("|echo " + input) | ||
^^^^^^^^^^^^^^^^^^^^^^^^^ The use of `IO.read` is a security risk. | ||
RUBY | ||
end | ||
|
||
it "reports an offense when `IO.read` is used with a concatenated string starting with untrustworthy input" do | ||
expect_offense(<<~'RUBY') | ||
input = "|echo test" | ||
IO.read(input + ".txt") | ||
^^^^^^^^^^^^^^^^^^^^^^^ The use of `IO.read` is a security risk. | ||
RUBY | ||
end | ||
|
||
it "does not report an offense when `IO.read` is used with a concatenated string safely" do | ||
expect_no_offenses(<<~'RUBY') | ||
input = "test" | ||
IO.read("somefile" + input + ".txt") | ||
RUBY | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters