RSTR-INJ-009 — Rails params[:x].constantize / .classify / .safe_constantize

Summary

A Rails handler resolves a class by calling .constantize, .safe_constantize, or .classify on a request parameter. An attacker who controls the string can instantiate any class in the autoload namespace — including ones whose initialize / _load / inherited hooks have dangerous side effects. The "mobile API" pattern of "deserialize whatever class the client names" historically led to RCE via gadget chains in several published Rails advisories.

Severity

High.

Languages

Ruby (Rails).

What rastray flags

model = params[:class].constantize                  # ← flagged
klass = params[:kind].safe_constantize              # ← flagged
model = params[:type].classify                      # ← flagged

What rastray deliberately does not flag

Allow-list resolution:

ALLOWED = { 'user' => User, 'admin' => AdminUser, 'guest' => GuestUser }
klass = ALLOWED.fetch(params[:kind]) { raise ActionController::BadRequest }
klass = case params[:kind]
        when 'user'  then User
        when 'admin' then AdminUser
        end

.constantize on a constant or a non-params source is also not flagged.

How to fix it

Resolve through an allow-list. The hash-with-fetch idiom above is the canonical pattern; the case-statement form is equally fine. Both ensure only classes the developer intended are reachable.

If the parameter is supposed to be one of a small fixed set, just do an explicit comparison rather than reflection:

if %w[user admin guest].include?(params[:kind])
  # safe to use params[:kind] in a query, but still construct
  # the class explicitly elsewhere
end

References