Rails translation performance impact <%= raw t( vs. <%= t( - ruby-on-rails

I am building a multilingual application using rails-i18n Ruby on Rails.
Most of content (and DB entries) I have to translate is pure text, though part of it has some embedded html.
I was thinking of using <%= raw t('translation_key') %> instead of the straight <%= t('translation_key') %> to account for future changes that might include html.
If I adopt <%= raw t('translation_key') %> throughout the all website, am I going to get any (negative) impact when it comes to
website performance
website security

You just just append _html to your tag keys to handle HTML in translation tags:
en:
key_one: test text
key_one_html: <p>test text</p>
Then the standard code will work:
<%= t('key_one_html') %>

Performance aspect:
The performance impact should be negligible. Calling raw copies the parameter into a new string (an ActiveSupport::SafeBuffer to be precise) with its html_safe flag set to true. On the other hand there is no longer HTML escaping performed on that string.
Security aspect:
There are more substantial drawbacks to using raw everywhere.
You say your translations are read from the database. Can the user edit these translations? If so...
You risk HTML injections: A malicious user could just enter a <script> tag.
All your translations must to be HTML safe from now on. That means you have to manually escape all your translations, i.e. you have to replace <,>, and &.
Alternatives:
There are other options if you need to incorporate HTML into your translations:
Use the _html suffix judiciously to prevent automatic escaping
Use localized views and partials, i.e. index.en.html, _footer.de-DE.html to translate larger parts of your views.
To streamline translation of database entries, you try
Globalize
hstore_translate (PostgreSQL only)
Conclusion:
Using raw everywhere will lead to a lot of problems along the road. Save yourself a lot of trouble and just use it "as needed".

You could also use the globalize gem for bigger text / html sections of content.
https://github.com/globalize/globalize/blob/master/README.md
It also supports eager loading if you're worried about performance.

Related

Safe Rails HTML translations

Following the rails guides as per the posting title, the YAML local files were set in a Rails 6.1.3 application as follows:
authorisation_request: Payment to be authorised; </br>Final <b>exact charge</b> </br>will reflect <b>delivered goods</b>.
authorisation_request_html: Payment to be authorised; </br>Final <b>exact charge</b> </br>will reflect <b>delivered goods</b>.
In the view, three experiments were conducted:
<i><%= t('cart.authorisation_request').capitalize %></i>
<i><%= raw t('cart.authorisation_request_html').capitalize %></i>
<i><%= t('cart.authorisation_request_html').capitalize %></i>
The first one rendered the tags as expected straight text, the middle one rendered as expected both the break and bold tags.
But the last one was rendered identical to the first. What am I missing?
When a translation key has the _html suffix, you can call it as if it did not, and it will automatically treat the key as HTML safe.
The way you are displaying the translation key is not as intended, instead of doing:
<%= t('cart.authorisation_request_html').capitalize %>
You should be doing:
<%= t('cart.authorisation_request').capitalize %>
Then the I18n system will see that there is an _html-suffixed variant, and mark that as HTML safe to display as-is. The way you are doing it now, the system would be looking for a key named authorization_request_html_html (double suffixed) and not find it.
More info on Safe HTML Translations: https://guides.rubyonrails.org/i18n.html#using-safe-html-translations
As a side-note, you should probably be capitalizing your source translated text, and not modifying it afterwards with the .capitalize helper. If that text were translated to another language, the capitalization could probably look pretty strange in some languages.

Are there any better alternatives to Sanitize for a Ruby app?

I love Sanitize. It's an amazing utility. The only issue I have w/ it is the fact that it takes forever to prepare a development environment w/ it because it uses Nokogiri, which is a pain for compile time. Are there any programs that do what Sanitize does (if nothing else than mildly what it does) w/out using Nokogiri? This would help exponentially!
Rails has its own SanitizeHelper.
According to http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html, it will
This sanitize helper will html encode all tags and strip all attributes that aren’t specifically allowed.
It also strips href/src tags with invalid protocols, like javascript: especially. It does its best to counter any tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters. Check out the extensive test suite.
You can use it in a view like so
<%= sanitize #article.body %>
You can visit the link to see more customizing options like:
Custom Use (only the mentioned tags and attributes are allowed, nothing else)
<%= sanitize #article.body, tags: %w(table tr td), attributes: %w(id class style) %>

What are the benefits, if i use rails view form template?

Example, i made a form like this
<form name="register" method="post" enctype="multipart/form-data">
<p><h3>User check</h3></p>
<p>admin ID: <input type="text" name="userid"></p>
<p>admin Pass: <input type="password" name="password"></p>
<input type="submit" name="apply" value="Submit"></p>
<p> </p>
</form>
and my manager wants to change this form to rails form template like this,
<%= form_for(:model) do |form| %>
<p>
<%=form.label :input%>
<%=form.text_field :input, :placeholder => 'Enter text here...'%>
</p>
<%end%>
My question is, it works fine with html based front code. Why do i have to change this to rails code? I just want to keep my front-end code...I don't know why i have to change this :(. Also, I'm new on Ruby on Rails. That is the main reason. I dont' want to change the existing code, if it is working.
I really hate this job. I have to translate all the attributes to the rails code and that makes me really exhausted :(
Form builders are here to help
Form helpers are supposed to make your life simpler. They are quicker to write than their pure html alternative, provided you don't write pure html first.
They also provide a lot of easy implementations for difficult integration pieces, like :
displaying a date selection select group
mirroring the fact that a check box has been unchecked in POST params
automatically adding multipart param on form if you add a file input (not actually difficult to achieve, but easy to forget)
... and many more
Further development
All of this is about comfort, and you may think you could avoid it if you already have a perfectly working pure html implementation.
But what happen if someone later has to add a date select input in your form ? She will have to use the rails helper, since it saves a lot of time in controller part to set date in database. But she won't be able to leverage form builder, since you haven't used it.
Now, she has to choose between using a non builderdate_select tag mixed in pure html or ... to rewrite your form completely. As you may realize, mixing different styles is generally considered ugly, and we don't like ugly in ruby.
Security
Form tag helpers also provide an important security measure : CSRF protection. Every time you use a rails helper to create a <form> tag, it automatically adds an hidden input containing a secret key. That key has to be posted with form data to prove request originated from current website.
If you use plain html forms, you won't have this security. You could of course add the token manually using the correct method, but this would again be more time wasting than simply using form helpers.
Bottom line
The main problem is that you write pure html before using rails helpers - that is what is wasting time.
Some benefits of using Rails form helpers are:
Consistent naming of input elements names and ids
i18n support for labels
generated URL with form_for is less error prone
Better handling of checkboxes
Nice helpers like options_for_select
Less typing
That last ones might be my favourite: less typing.

Ruby/Rails - Parsing and Displaying HTML from a Models Attribute

I have a Rails Model called Events which has as field/attribute called :description.
I migrated it under the type t.text rather than t.string since I was going to be displaying a large amount of data.
So.... Now I'm at the point where I would like to display <%= #event.description %> in a neat way and would like to break up some of the sentences rather than one large block of information.
I was hoping I could insert <p> or other html codes to help with how the text is displayed.
The problem is inserting <p> into the field only prints <p> and the not desired action of the html command.
How can I add html styling to the text attribute?
You can use <%=raw #event.description %> to echo unescaped content. Be aware that this is a potential XSS security hole, if users can ever affect that content. I highly recommend using the sanitize helper to strip out any unwelcome markup before you write it out.
It strictly depends on how you print it. In particular, if you print with calling h function (<%= h my_text =>), output will be sanitized and html escaped.
It may also depend on your rails version: I've head in Rails 3 html is escaped by default, even if you don't use h.

Escaping HTML in Rails

What is the recommended way to escape HTML to prevent XSS vulnerabilities in Rails apps?
Should you allow the user to put any text into the database but escape it when displaying it? Should you add before_save filters to escape the input?
There are three basic approaches to this problem.
use h() in your views. The downside here is that if you forget, you get pwnd.
Use a plugin that escapes content when it is saved. My plugin xss_terminate does this. Then you don't have to use h() in your views (mostly). There are others that work on the controller level. The downsides here are (a) if there's a bug in the escaping code, you could get XSS in your database; and (b) There are corner cases where you'll still want to use h().
Use a plugin that escapes content when it is displayed. CrossSiteSniper is probably the best known of these. This aliases your attributes so that when you call foo.name it escapes the content. There's a way around it if you need the content unescaped. I like this plugin but I'm not wild about letting XSS into my database in the first place...
Then there are some hybrid approaches.
There's no reason why you can't use xss_terminate and CrossSiteSniper at the same time.
There's also a ERb implementation called Erubis that can be configured so that any call like <%= foo.name %> is escaped -- the equivalent of <%= h(foo.name) %>. Unfortunately, Erubis always seems to lag behind Rails and so using it can slow you down.
If you want to read more, I wrote a blog post (which Xavor kindly linked to) about using xss_terminate.
The h is an alias for html_escape, which is a utility method for escaping all HTML tag characters:
html_escape('<script src=http://ha.ckers.org/xss.js></script>')
# => <script src=http://ha.ckers.org/xss.js></script>
If you need more control, go with the sanitize method, which can be used as a white-list of tags and attributes to allow:
sanitize(#article.body, :tags => %w(table tr td), :attributes => %w(id class style))
I would allow the user to input anything, store it as-is in the database, and escape when displaying it. That way you don't lose any information entered. You can always tweak the escaping logic later...
Use the h method in your view template. Say you have a post object with a comment property:
<div class="comment">
<%= h post.comment %>
</div>
Or with this plugin - no need for h 8)
http://railspikes.com/2008/1/28/auto-escaping-html-with-rails
I've just released a plugin called ActsAsSanitiled using the Sanitize gem which can guarantee well-formedness as well being very configurable to what kind of HTML is allowed, all without munging user input or requiring anything to be remembered at the template level.

Resources