Ruby-dev summary 19878-19943

Hi all,

This is a summary of ruby-dev ML in these days.
Range: [ruby-dev:19878] … [ruby-dev:19943]

[ruby-dev:19865] dl in $SAFE=4
[ruby-list:37370] writing insecure programs

TANAKA Akira reported some additional vulnerabilities (refer
ChangeLog for details). At the same time, we re-confirmed
the security model of Ruby. Here is a short summary:

== Bases

Ruby’s security model is thread based.
Safe level (global variable $SAFE) is thread local.

== Safe level
==== Level 0
Normal state.

==== Level 1
Ruby prohibits dangerous operations using tainted objects.
Characteristic situations are CGI programs.
(handling untrusted DATA)

==== Level 2
Ruby prohibits changing global (process/environment) state.
e.g. chdir, chroot, mkdir, rmdir, stat, lstat, chmod, lchmod …
This level is not so useful.

==== Level 3
Ruby prohibits untainting objects.
Newly created objects are tainted.
You should use this level to set up environment for Level 4.

==== Level 4
Ruby prohibits all dangerous operations.
Level 4 programs also cannot modify untainted objects.
Characteristic situations are Ruby applets/plugins.
(handling untrusted CODE)

== Author’s perspective: Ruby extensions

If you are author of Ruby extensions, note following points:

* Check untrusted values by SafeStringValue().
  e.g.

    static VALUE
    dangerous_operation(VALUE self, VALUE arg)
    {
        SafeStringValue(arg);
        /* SafeStringValue() implicitly calls rb_secure(4) */

* Check untrusted code by rb_secure(4).
  e.g.

    static VALUE
    dangerous_operation2(VALUE self)
    {
        rb_secure(4);

* Call rb_secure_update(obj) before updating OBJ, if OBJ is
  under your control (ruby cannot handle it).
  e.g.

    static VALUE
    update_local_state(VALUE self)
    {
        rb_secure_update(self);
        GET_POINTER(self)->idx = INT2FIX(3);

* Transit object infection by OBJ_INFECT()/rb_obj_infect().
  e.g.

    static VALUE
    normal_operation(VALUE self, VALUE str)
    {
        StringValue(str);
        ....
        /* transit infection from STR to the created string */
        return rb_obj_infect(rb_str_new(RSTRING(str)->ptr, len), str);
    }

=== Security related C APIs

VALUE OBJ_INFECT(dest, src); /* Macro */
Taints DEST if SRC is tainted.

VALUE rb_obj_infect(dest, src); /* 1.8 only */
Taints DEST if SRC is tainted.

void SafeStringValue(VALUE lval); /* Macro, 1.8 only */
Converts LVAL into String and check if LVAL is dangerous.
If $SAFE>=4, raises SecurityError.
If LVAL is tainted and $SAFE>=1, raises SecurityError.

void rb_secure(int level);
Raises SecurityError if $SAFE>=level.

void rb_secure_update(obj); /* 1.8 only */
Raises SecurityError if $SAFE>=4 and OBJ is not tainted.

Finally, DO NOT TRUST Ruby’s safe level.
Ruby’s security model and its implementation is not mature.
There must be other hidden vulnerabilities.

[ruby-dev:19891] zlib (Re: dl in $SAFE=4)

UENO Katsuhiro imported Ruby/zlib into the main trunk.
You can get it from the cvs.ruby-lang.org:

$ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login
Password: (anonymous)
$ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src co ruby

And Ruby/zlib is in the ext/zlib directory.

[ruby-dev:19912] Regular expression warning (Re: [Oniguruma] Version 1.8.4)

Ruby 1.8 warns about the bare ‘-’ in the character class:

% ruby-1.8.0 -e 're = /[-a-z]/'
-e:1: warning: character class has `-' without escape

TAKAHASHI Masayoshi suggested to suppress this warning,
if ‘-’ is the first/last character of the character class.

– Minero Aoki