34969


## 質問内容

最後に改めて記載しますが、最初に質問を記載します。

以下の2点について、ご教授いただきたいです。

  * そもそも実装方法が適切か 
    * Gemを使うのがスタンダード、コードがおかしい、など
  * XSS脆弱性に対処できているか

## やりたいこと

現在、Railsで掲示板を作成しています。

Twitterなど多くのサイトで使われているような、ユーザーが投稿するテキストにURLがある場合はtarget="_blank"を付けてリンク化して表示する機能を実装したいです。

また、テキスト内の改行を反映させたいため、Railsが用意しているビューヘルパーのsimple_formatを使用します。

実装に際して検索をかけてみたところ、以下の2つのGemが出てきたのですが、どちらのGemもネットに存在する情報が少ないことから、Gemを使った実装方法がスタンダードなのか分からないため、Gemを使わずに実装する形にしました。

  * tenderlove/rails_autolink

<https://github.com/tenderlove/rails_autolink>

  * vmg/rinku

<https://github.com/vmg/rinku>

## 参考にしたURL

以下が実装時に参考にしたURLです。

  * テキスト内のURLをリンク化して表示するため

[[Ruby][Rails]テキスト内のURLをaタグに書き換える -
Qiita](http://qiita.com/satoken0417/items/df4098a122d05d69a3e6)

  * simple_formatをそのまま使用するとtarget="_blank"が消えるのに対処するため

[ruby on rails - simple_format is stripping out target _blank - Stack
Overflow](https://stackoverflow.com/questions/34400711/simple-format-is-
stripping-out-target-blank)

## 環境

Rails 5.0.0.1  
Ruby 2.3.1

## コード

以下で、ユーザーが投稿したテキストにURLが含まれていれば、その部分をリンクにするtext_url_to_linkメソッドを定義しています。

app/helpers/application_helper.rb

[code]

    module ApplicationHelper
      require "uri"
    
      def text_url_to_link(text)
        URI.extract(text, ['http', 'https']).uniq.each do |url|
          sub_text = ""
          sub_text << "<a href=" << url << " target=\"_blank\">" << url << "</a>"
          text.gsub!(url, sub_text)
        end
        return text
      end
    end
    
[/code]

以下で、ユーザーが投稿したテキストを表示しています。

前提としまして、Discussionsテーブルにtext型のcontentカラムがある状況です。

質問したいコードをdivで囲ってidを設定しているのはAjaxでDiscussionのcontentを編集するためです。

app/views/discussions/index.html.erb

[code]

    <% @discussions.each do |discussion| %>
      <div id="discussion-content-<%= discussion.id %>" class="discussion-content">
        <!-- 以下が質問をしたいコード -->
        <%= simple_format(text_url_to_link(h(discussion.content)), {}, sanitize: false) %>
      </div>
    <% end %>
    
[/code]

上記のviewファイル内の質問したいコードの流れは以下のようになっていると認識しています。

  * discussion.contentでユーザーが投稿したテキストを取得
  * hメソッドでタグをエスケープ
  * 自分で定義したtext_url_to_linkメソッドによりURL形式の文字列をaタグで囲む
  * simple_formatメソッドをそのまま使用すると、target="_blank"が効かなくなるので、オプションでsanitize: falseを指定
  * 最終的にテキスト内のURL形式の文字列がリンクで表示される

上記のコードを書いた状況で

[code]

    <script>alert('hoge')</script>
    
[/code]

と自分が作っている掲示板に投稿したところ、エスケープされて表示されました。

## 質問内容

改めて、質問内容を記載致します。以下の2点になります。

  * そもそも実装方法が適切か 
    * Gemを使うのがスタンダード、コードがおかしい、など
  * XSS脆弱性に対処できているか

初心者のため、内容に至らない点もあるかもしれませんが、ご教授いただけますと幸いです。よろしくお願いいたします。


CC BY-SA 3.0
2017-05-23T07:14:41.107
34957
2017-05-23T19:25:55.730
2017-05-23T15:54:07.210
23290
23290
question
ruby-on-rails ruby xss
Railsでユーザーが投稿したテキストにURLがあればリンクとして表示した時のXSS対策について


セキュリティは専門でないため、あくまでも私の経験上の話ですが、XSSについて問題がないかどうかは実際にそれに該当するであろうデータを処理させてみて確認した方が間違いないと思います。身も蓋もない答えかもしれませんが、例えば
URIに`javascript://`を許すかどうか、といったことは実際に自分で確かめるか、gemに自動テストが付いているなら、そのコードを見て実行させて確認するかしないと、本当の意味では危険性の判断はできないかなと思います。

次にgemを使うべきかどうかは、他プラットフォームのプログラミングをするときとも共通した性質があると思います。

自分が使うサードパーティライブラリが実際に用途に適した動作をするっぽい、と確信できるなら使えばよいでしょうが、やはり実質的にポピュラーなものである方が安心はできるでしょう。前述のセキュリティ周りの問題等についてもポピュラーなものの方がユーザーも多いので、きちんと対処されているのではという期待もある程度できるためです。

その他、gemの更新頻度や問題対処に対するメンテナーの人々の素早さは、できるのであれば確認したほうが良いです。  
githubでissueやプルリクエストがやたら溜まっていたり、最終更新日が1年以上経過していた場合、問題があると分かっても対処してもらえないリスクはどうしても高くなってしまいがちです。  
この観点から見ると、rails_autolink の方はissueやプルリクエストが溜まったまま放置されているのが気になるといえば気になります。

結局他人の書いたものなので、gemを入れれば入れるほど、プログラムの外部依存性はどんどん高まってしまいます。ですので、そのgemのメンテナンス性に疑問があったり、絶対に自分自身が制御を保証したい場合は、あえて自分で実装するという選択もあり得ると思います。


CC BY-SA 3.0
2017-05-23T18:47:58.113
34969
2017-05-23T19:25:55.730
2017-05-23T19:25:55.730
9403
9403
34957
answer