Ruby and Rails secure coding¶
Rails provides useful security defaults, but raw SQL strings and explicit trust overrides can bypass them. This guide uses Ruby on Rails with Active Record to demonstrate safe query construction. It assumes the application has already authenticated the user and has a policy for which customer records that user may access.
Use structured query conditions¶
Assume name comes from a request and has passed the application's string and length checks.
Unsafe: interpolate into SQL.
customers = Customer.where("name = '#{name}'")
Safer: let Active Record build the condition.
customers = Customer.where(name: name)
The hash condition keeps the value out of the SQL structure. When an expression is necessary, use the framework's documented placeholder form, such as where("name = ?", name), rather than interpolating it. Rails documents these patterns in its security guide.
A safer query is still too broad if it searches every tenant. Begin with an authorized relation, for example one derived from the authenticated account, then apply the condition. Do not accept an account identifier from the request as proof of ownership. Likewise, Strong Parameters constrain permitted attributes for mass assignment; they do not establish permission to update a record.
Check the fix¶
In a Rails test database, create customers named O'Reilly and Demo Books. Force the relation to execute with to_a and assert that searching by either name returns only the expected record. Repeat the request under a different account and check that the authorized relation excludes it. Testing only relation construction can miss deferred database errors.
For views, keep automatic escaping enabled. Review uses of html_safe, raw, dynamic render paths and untrusted deserialization. These are separate boundaries from the query shown above. Avoid logging secrets when validation or database operations fail.
Continue with SQL injection, mass assignment, XSS and dynamic render paths. OWASP's SQL guidance describes the underlying code/data separation.
Native Ruby analysis and additional Rails analyzers can have different scopes and availability. Confirm the enabled checks for your deployment instead of assuming that one clean scan establishes complete Rails coverage.