背景
userの情報を返すAPIを実装する際、render json: user
とするとuserモデルのすべてのフィールドを含むJSONを返してしまい危険です。パスワードはハッシュ化されているものの、deviseが提供するフィールドlast_sign_in_ip
などクライアントに返してはならない個人情報が含まれており、情報漏えいにつながってしまうためです。
こちらの記事も参考にしてください。
上述のような危険な実装をコードレビューのみに頼らずに、Rubyの静的コード解析ツールであるRuboCopで機械的にチェックする方法を、当ページでは記載します。
手順
基本的には公式ドキュメントの手順通りです。
rubocop gemはインストール済みの前提で記載します。
チェック対象のコード
以下の4行目をエラーとすることを目標にします。
# some_controller.rb class SomeController < ApplicationController def some_method user = User.first render json: user, status: 200 # これを検知したい。statusパラメータは省略可能 end end
ASTの出力
rubocop gemを入れていれば使えるruby-parse
というコマンドでASTを出力します。
$ ruby-parse some_controller.rb (class (const nil :SomeController) (const nil :ApplicationController) (def :some_method (args) (begin (lvasgn :user (send (const nil :User) :first)) (send nil :render (kwargs (pair (sym :json) (lvar :user)) (pair (sym :status) (int 200)))))))
検知したいのは、この
(send nil :render (kwargs (pair (sym :json) (lvar :user)) (pair (sym :status) (int 200))))))
の部分です。また、renderメソッドの第二引数のstatusは省略可能な引数ですので、第二引数の有無にかかわらず検知できるようにしたいです。
カスタムルールの作成
上記パターンにマッチするようにマッチャを記述します。_
や ...
はワイルドカードです。詳細はドキュメントをご確認ください。
- renderメソッドを呼び出していて
- その引数にはjsonという名前付き引数を指定しており
- 第二引数以降は問わない
というマッチャを記述しlib/custom_cops/dangerous_render_json.rb
として配置します。
module CustomCops class DangerousRenderJson < RuboCop::Cop::Cop # キーワード引数jsonを第一引数にしているrenderメソッド def_node_matcher :render_json_call?, <<~PATTERN (send ... :render (hash (:pair (:sym :json) (_ ...) ) ... ) ) PATTERN MSG = 'Do not use render json.' def on_send(node) return unless node.method_name == :render add_offense(node) if tojson_call?(node) end end end
次に、.rubocop.yml
にて、今作ったカスタムルールを読み込む設定を追記します。
require: - rubocop-rails - rubocop-rspec - ./lib/custom_cops/dangerous_render_json
動作確認
rubocopコマンドを実行して動作確認をします。
うまくいけば、以下のように、エラーとして検知できます。
% bundle exec rubocop ・・・中略・・・ app/controllers/some_controller.rb:4:5: C: CustomCops/DangerousRenderJson: Do not use render json. render json: user, status: 200 # これを検知したい。statusパラメータは省略可能 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
本サイトの更新情報は、X(旧Twitter)の株式会社プレセナ・ストラテジック・パートナーズエンジニア公式で発信しています。ご確認ください。