开发者

html_safe and gsub

In my CMS application I use gsub to replace parts of a user supplied html template (string) with dynamic code from the application (such as a comment from a user, or page content). I'm upgrading from Rails 2.3.5 to 2.3.12 in preparation for a move to Rails 3 and have installed the rails_xss gem to try and get my strings sorted.

I'm wondering if there's a way to gsub strings into another string (the template), treating the incoming string as unsafe, but the template sections as safe?

I already sense that I'm going to have to rethink this and perhaps split the template around my areas of concern and insert my dynamic bits in the gap, passing the whole thing out as an array of various safe and unsafe strings to be rendered. Does that sound like the sane way to go.

UPDATE

Here is an example of what I currently do. It's in a helper that gets called from a layout. The theme is fetched from the database. It's just a string with specific HTML Comments that we're looking to replace with the actual content:

final_theme.gsub!('<body>', '<body>' + (render '/user_bars/user_bar'))
final_theme.gsub!('</body>', (render '/theme/google_analytics') + '</body>') if SiteSetting.first.google_analytics_code.present?
final_theme.gsub!('<!--THEME_MetaTitle-->', (render '/theme/meta_title'))
final_theme.gsub!('<!--THEME_Breadcrumbs-->', (render '/theme/breadcrumbs'))
final_theme.gsub!('<!--THEME_Footer-->', (render '/theme/footer'))
final_theme.gsub!('<!--THEME_Body-->', (render '/theme/body'))

Those are simple cases, I also have 开发者_开发技巧comments that have actual parameters in them (for example to specify how many levels deep to draw an index bar, of which there could be many on a page). I use scan to find the details and then gsub again to replace the comment with the actual indexbar code.

I'm totally open to any refactoring advice as this is an area of my code that doesn't satisfy me at all.


After installing the latest plugin from rails/rails_xss (rather than NZKoz's one) I started getting errors saying gsubing a SafeBuffer was not allowed. Fair enough :)

I've come up with this as an alternative and will accept this as the correct answer if someone can vouch for its correctness:

final_theme = final_theme.html_safe

final_theme = final_theme.split('<!--THEME_Breadcrumbs-->').inject do |output, piece| 
  output + render('/theme/breadcrumbs') + piece
end

That's just an extract but we're basically marking the original theme as safe (because it is) and then splitting on the piece of interest, injecting our new code into the mix by concatenating the strings together, thus ensuring html_safeness!


I believe (although I can't find the commit right now) there one of the recent releases of rails 3 (3.0.7 or 3.0.8 I think) fixed a number of security issues around this very issue.

Gsubbing user input feels like a bit of a code smell, perhaps you can provide some code and we can look at refactoring it?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜