3 The Ruby programming language is large and complex and there are many security
4 pitfalls often encountered by newcomers and experienced Rubyists alike.
6 This document aims to discuss many of these pitfalls and provide more secure
7 alternatives where applicable.
9 Please check the full list of publicly known CVEs and how to correctly report a
10 security vulnerability, at: https://www.ruby-lang.org/en/security/
11 Japanese version is here: https://www.ruby-lang.org/ja/security/
13 Security vulnerabilities should be reported via an email to
14 mailto:security@ruby-lang.org ({the PGP public
15 key}[https://www.ruby-lang.org/security.asc]), which is a private mailing list.
16 Reported problems will be published after fixes.
20 Ruby's +Marshal+ module provides methods for serializing and deserializing Ruby
21 object trees to and from a binary data format.
23 Never use +Marshal.load+ to deserialize untrusted or user supplied data.
24 Because +Marshal+ can deserialize to almost any Ruby object and has full
25 control over instance variables, it is possible to craft a malicious payload
26 that executes code shortly after deserialization.
28 If you need to deserialize untrusted data, you should use JSON as it is only
29 capable of returning 'primitive' types such as strings, arrays, hashes, numbers
30 and nil. If you need to deserialize other classes, you should handle this
31 manually. Never deserialize to a user specified class.
35 YAML is a popular human readable data serialization format used by many Ruby
36 programs for configuration and database persistence of Ruby object trees.
38 Similar to +Marshal+, it is able to deserialize into arbitrary Ruby classes.
39 For example, the following YAML data will create an +ERB+ object when
45 Because of this, many of the security considerations applying to Marshal are
46 also applicable to YAML. Do not use YAML to deserialize untrusted data.
50 Symbols are often seen as syntax sugar for simple strings, but they play a much
51 more crucial role. The MRI Ruby implementation uses Symbols internally for
52 method, variable and constant names. The reason for this is that symbols are
53 simply integers with names attached to them, so they are faster to look up in
56 Starting in version 2.2, most symbols can be garbage collected; these are
57 called <i>mortal</i> symbols. Most symbols you create (e.g. by calling
60 <i>Immortal</i> symbols on the other hand will never be garbage collected.
61 They are created when modifying code:
62 * defining a method (e.g. with +define_method+),
63 * setting an instance variable (e.g. with +instance_variable_set+),
64 * creating a variable or constant (e.g. with +const_set+)
65 C extensions that have not been updated and are still calling `SYM2ID`
66 will create immortal symbols.
67 Bugs in 2.2.0: +send+ and +__send__+ also created immortal symbols,
68 and calling methods with keyword arguments could also create some.
70 Don't create immortal symbols from user inputs. Otherwise, this would
71 allow a user to mount a denial of service attack against your application by
72 flooding it with unique strings, which will cause memory to grow indefinitely
73 until the Ruby process is killed or causes the system to slow to a halt.
75 While it might not be a good idea to call these with user inputs, methods that
76 used to be vulnerable such as +to_sym+, +respond_to?+,
77 +method+, +instance_variable_get+, +const_get+, etc. are no longer a threat.
79 == Regular expressions
81 Ruby's regular expression syntax has some minor differences when compared to
82 other languages. In Ruby, the <code>^</code> and <code>$</code> anchors do not
83 refer to the beginning and end of the string, rather the beginning and end of a
86 This means that if you're using a regular expression like
87 <code>/^[a-z]+$/</code> to restrict a string to only letters, an attacker can
88 bypass this check by passing a string containing a letter, then a newline, then
89 any string of their choosing.
91 If you want to match the beginning and end of the entire string in Ruby, use
92 the anchors +\A+ and +\z+.
96 Never pass untrusted or user controlled input to +eval+.
98 Unless you are implementing a REPL like +irb+ or +pry+, +eval+ is almost
99 certainly not what you want. Do not attempt to filter user input before passing
100 it to +eval+ - this approach is fraught with danger and will most likely open
101 your application up to a serious remote code execution vulnerability.
105 'Global functions' in Ruby (+puts+, +exit+, etc.) are actually private instance
106 methods on +Object+. This means it is possible to invoke these methods with
107 +send+, even if the call to +send+ has an explicit receiver.
109 For example, the following code snippet writes "Hello world" to the terminal:
111 1.send(:puts, "Hello world")
113 You should never call +send+ with user supplied input as the first parameter.
114 Doing so can introduce a denial of service vulnerability:
116 foo.send(params[:bar]) # params[:bar] is "exit!"
118 If an attacker can control the first two arguments to +send+, remote code
119 execution is possible:
121 # params is { :a => "eval", :b => "...ruby code to be executed..." }
122 foo.send(params[:a], params[:b])
124 When dispatching a method call based on user input, carefully verify that the
125 method name. If possible, check it against a whitelist of safe method names.
127 Note that the use of +public_send+ is also dangerous, as +send+ itself is
130 1.public_send("send", "eval", "...ruby code to be executed...")
134 As DRb allows remote clients to invoke arbitrary methods, it is not suitable to
135 expose to untrusted clients.
137 When using DRb, try to avoid exposing it over the network if possible. If this
138 isn't possible and you need to expose DRb to the world, you *must* configure an
139 appropriate security policy with <code>DRb::ACL</code>.