////
  Do NOT edit this file by hand directly, as it is automatically generated.

  Please make any necessary changes to the cop documentation within the source files themselves.
////

= Security

[#securitycompoundhash]
== Security/CompoundHash

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| No
| No
| 1.28
| 1.51
|===

Checks for implementations of the `hash` method which combine
values using custom logic instead of delegating to `Array#hash`.

Manually combining hashes is error prone and hard to follow, especially
when there are many values. Poor implementations may also introduce
performance or security concerns if they are prone to collisions.
Delegating to `Array#hash` is clearer and safer, although it might be slower
depending on the use case.

[#safety-securitycompoundhash]
=== Safety

This cop may be unsafe if the application logic depends on the hash
value, however this is inadvisable anyway.

[#examples-securitycompoundhash]
=== Examples

[source,ruby]
----
# bad
def hash
  @foo ^ @bar
end

# good
def hash
  [@foo, @bar].hash
end
----

[#securityeval]
== Security/Eval

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.47
| -
|===

Checks for the use of `Kernel#eval` and `Binding#eval` with
dynamic strings as arguments. Evaluating non-literal strings
can enable code injection attacks and makes it difficult to
reason about what code will actually be executed.

Calls to `eval` with literal strings are not flagged by this cop,
as they do not pose the same injection risk.

[#examples-securityeval]
=== Examples

[source,ruby]
----
# bad
eval(something)
binding.eval(something)
Kernel.eval(something)

# good - use safer alternatives
obj.public_send(method_name)
obj.send(method_name, *args)

# good - literal strings are allowed
eval("1 + 1")
binding.eval("foo")
----

[#securityiomethods]
== Security/IoMethods

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| No
| Always (Unsafe)
| 1.22
| -
|===

Checks for the first argument to `IO.read`, `IO.binread`, `IO.write`, `IO.binwrite`,
`IO.foreach`, and `IO.readlines`.

If argument starts with a pipe character (`'|'`) and the receiver is the `IO` class,
a subprocess is created in the same way as `Kernel#open`, and its output is returned.
`Kernel#open` may allow unintentional command injection, which is the reason these
`IO` methods are a security risk.
Consider using `File.read` to disable the behavior of subprocess invocation.

[#safety-securityiomethods]
=== Safety

This cop is unsafe because false positive will occur if the variable passed as
the first argument is a command that is not a file path.

[#examples-securityiomethods]
=== Examples

[source,ruby]
----
# bad
IO.read(path)
IO.read('path')

# good
File.read(path)
File.read('path')
IO.read('| command') # Allow intentional command invocation.
----

[#securityjsonload]
== Security/JSONLoad

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.43
| 1.22
|===

Checks for the use of JSON class methods which have potential
security issues.

`JSON.load` and similar methods allow deserialization of arbitrary ruby objects:

[source,ruby]
----
require 'json/add/string'
result = JSON.load('{ "json_class": "String", "raw": [72, 101, 108, 108, 111] }')
pp result # => "Hello"
----

Never use `JSON.load` for untrusted user input. Prefer `JSON.parse` unless you have
a concrete use-case for `JSON.load`.

NOTE: Starting with `json` gem version 2.8.0, triggering this behavior without explicitly
passing the `create_additions` keyword argument emits a deprecation warning, with the
goal of being secure by default in the next major version 3.0.0.

[#safety-securityjsonload]
=== Safety

This cop's autocorrection is unsafe because it's potentially dangerous.
If using a stream, like `JSON.load(open('file'))`, you will need to call
`#read` manually, like `JSON.parse(open('file').read)`.
Other similar issues may apply.

[#examples-securityjsonload]
=== Examples

[source,ruby]
----
# bad
JSON.load('{}')
JSON.restore('{}')

# good
JSON.parse('{}')
JSON.unsafe_load('{}')

# good - explicit use of `create_additions` option
JSON.load('{}', create_additions: true)
JSON.load('{}', create_additions: false)
----

[#references-securityjsonload]
=== References

* https://ruby-doc.org/stdlib-2.7.0/libdoc/json/rdoc/JSON.html#method-i-load
* https://bugs.ruby-lang.org/issues/19528

[#securitymarshalload]
== Security/MarshalLoad

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| No
| 0.47
| -
|===

Checks for the use of Marshal class methods which have
potential security issues leading to remote code execution when
loading from an untrusted source.

[#examples-securitymarshalload]
=== Examples

[source,ruby]
----
# bad
Marshal.load("{}")
Marshal.restore("{}")

# good
Marshal.dump("{}")

# okish - deep copy hack
Marshal.load(Marshal.dump({}))
----

[#references-securitymarshalload]
=== References

* https://ruby-doc.org/core-2.7.0/Marshal.html#module-Marshal-label-Security+considerations

[#securityopen]
== Security/Open

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| No
| No
| 0.53
| 1.0
|===

Checks for the use of `Kernel#open` and `URI.open` with dynamic
data.

`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.

NOTE: `open` and `URI.open` with literal strings are not flagged by this
cop.

[#safety-securityopen]
=== Safety

This cop could register false positives if `open` is redefined
in a class and then used without a receiver in that class.

[#examples-securityopen]
=== Examples

[source,ruby]
----
# bad
open(something)
open("| #{something}")
open("| foo")
URI.open(something)

# good
File.open(something)
IO.popen(something)
URI.parse(something).open

# good (literal strings)
open("foo.text")
URI.open("http://example.com")
URI.parse(url).open
----

[#securityyamlload]
== Security/YAMLLoad

NOTE: Requires Ruby version <= 3.0

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Enabled
| Yes
| Always (Unsafe)
| 0.47
| -
|===

Checks for the use of YAML class methods which have
potential security issues leading to remote code execution when
loading from an untrusted source.

NOTE: Ruby 3.1+ (Psych 4) uses `Psych.load` as `Psych.safe_load` by default.

[#safety-securityyamlload]
=== Safety

The behavior of the code might change depending on what was
in the YAML payload, since `YAML.safe_load` is more restrictive.

[#examples-securityyamlload]
=== Examples

[source,ruby]
----
# bad
YAML.load("--- !ruby/object:Foo {}") # Psych 3 is unsafe by default

# good
YAML.safe_load("--- !ruby/object:Foo {}", [Foo])                    # Ruby 2.5  (Psych 3)
YAML.safe_load("--- !ruby/object:Foo {}", permitted_classes: [Foo]) # Ruby 3.0- (Psych 3)
YAML.load("--- !ruby/object:Foo {}", permitted_classes: [Foo])      # Ruby 3.1+ (Psych 4)
YAML.dump(foo)
----

[#references-securityyamlload]
=== References

* https://ruby-doc.org/stdlib-2.7.0/libdoc/yaml/rdoc/YAML.html#module-YAML-label-Security
