3 ms·
You can easily see if you are vulnerable to this by opening up rails console and iterating over your models and seeing if the model's table name is a column nam
by rubiquity 13y ago
You can easily see if you are vulnerable to this by opening up rails console and iterating over your models and seeing if the model's table name is a column name:
Dir.glob(File.join(Rails.root, 'app/models/**/*.rb')).each { |file| require file }
ActiveRecord::Base.descendants.select do |model|
model.column_names.include? model.table_name
end
EDIT: As rosser points out below, the code above doesn't cover the case of doing a join between two tables where one table has a column named the same as the joining table name. Below you can find any table that has a column name from another table. From there you can check to make sure you aren't joining this table with the table sharing the same name as the column.
ActiveRecord::Base.descendants.select do |model|
shared = model.column_names & ActiveRecord::Base.descendants.map(&:table_name)
if shared.any?
puts "#{model.to_s} has potentially dangerous columns: #{shared.join(' ')}"
true
end
end
- joevandyk 13y agomake sure to have eager loading turned on before you do this.
- rubiquity 13y agoGood catch, I'll update the snippet to load all the models first.
- rosser 13y agoDoesn't that only capture the first of the two vulnerable cases (a table that has a column with the same name as the table itself)? What about the second case, where you have a column on one table that has the same name as another table? Queries (PostgreSQL-specific) I whipped up investigating our stack this morning for this issue that appear to catch both cases (corrections or improvements welcome): Case 1: select c.relname , a.attname from pg_class c join pg_attribute a on a.attrelid = c.oid where c.relname = a.attname; Case 2: select c2.relname , c1.relname || '.' || a.attname from pg_class c1 join pg_attribute a on a.attrelid = c1.oid join pg_namespace n on c1.relnamespace = n.oid left join pg_class c2 on c2.relname = a.attname where c2.relname is not null and n.nspname not in ('pg_catalog', 'information_schema');
- rubiquity 13y agoI think case 2 is only for when you're doing joins, less likely but still possible.
- rosser 13y agoMy query for that case may also yield some false positives, as we appear to have a couple of cases where one table has a column that shares its name with a completely unrelated table.
- rubiquity 13y agoYup, I updated my reply above. You can get the list but then you still have to manually go through your codebase to make sure you aren't joining the table with the potentially dangerous column name with that exact table.