I was developing a specific filter when I ran into the following question:
input_from_user = Arel::Nodes::Quoted.new(input_from_user.split('.').second)
separator = Arel::Nodes::Quoted.new('.')
Model.where(Arel::Nodes::NamedFunction.new('split_part', [input_from_user, separator, 2]).eq('random_value'))
This works, but I am not sure if this is really secure, I know that 'Arel.sql' or 'Literal' would not garantee any security, 'Quoted' node seems to handle injection, but I am not 100% into injection security, is there any other way to write this? (which does not involves creating fields on the database) if not, is this safe?
CodePudding user response:
TL;DR:
Yes these will be escaped accordingly, just as they would be for higher level AR query methods.
Explanation:
So here is how Nodes::NamedFunction will work in SQL compilation (in a nut shell):
- visit the
Nodes::NamedFunction(Source) - Visit each expression (your Array argument) (Source)
- Since they are
Nodes::Quotedvisit those expressions (Source) - Use
quotemethod (Source) - Use Postgres Adapter
quotemethod (Source) - Use Abstract Adapter
quotemethod because these areStrings (Source) - Use Postgres Adapter
quote_stringto escape strings (Source) - Use Postgres connection
escapemethod (from thepggem) (Source or Docs because they are easier to read)
The result will be split_part('input_from_user','.',2).
Additional Notes:
- Your only other issue is that your
wheredoes not have an queryable expression (no predication) of any kind so you would need to modify this to something like the following (which will generate anArel::Nodes::Equalityobject)
Model.where(
Arel::Nodes::NamedFunction.new(
'split_part',
[input_from_user, separator, 2]
).eq('sub string'))
Arel::Nodesprovides a convenience method (build_quoted) that reads a little nicer. e.g.
input_from_user = Arel::Nodes.build_quoted(input_from_user.split('.').second)
separator = Arel::Nodes.build_quoted('.')
Model.where(
Arel::Nodes::NamedFunction.new(
'split_part',
[input_from_user, separator, 2]
).eq('sub string'))
