Ruby 2.7 removes taint checking mechanism


Taint Checking is a mechanism that was used by Ruby to prevent malicious commands from being executed on a host machine.

As per taint checking, any input that originated or can be modified by an external user (such as a form field), is considered tainted. If this tainted object is used in an expression to evaluate another object, then that gets tainted as well.

While running in a safe mode, if the program tries to execute a potentially dangerous method using any tainted object, then it will raise a SecurityError.


The $SAFE global variable

Ruby security level is set and accessed by the $SAFE global variable. The possible values for this variable ranges from 0 to 4, 4 being the maximum security level.

More info about the $SAFE variable can be found here.


Why is taint checking being removed?

Taint checking features were used extensively in the age of CGI programs. But in recent times, most input libraries don’t support this mechanism. E.g., Rack.

In addition to that, there have been multiple vulnerabilities around the $SAFE variable and the taint mechanism altogether. Source.


Ruby 2.7

In Ruby 2.7, the taint checking mechanism has been removed. This means all objects by default are deemed untainted.

Accessing and setting the value of $SAFE variable will always result in a warning.

Also, Object#taint, Object#trust, Object#untaint, Object#untrust and related functions in the C-API have been made no-op methods. It means they do nothing and just return self. Their usage will result in a verbose warning (warned only in verbose mode).

Complete removal plan

As per the feature ticket Feature #16131, the decided removal plan for taint checking is as follows:

Ruby 3.0:
- $SAFE will become a normal global variable and there will be no warning on its access or assignment.
- Usage of Object#taint, Object#trust, Object#untaint, Object#untrust and the C functions will result in a non-verbose warning (warned in both regular and verbose mode).

Ruby 3.2:
- Object#taint, Object#trust, Object#untaint, Object#untrust and the C functions will be completely removed.