PIYO - Tech & Life -

Railsで"invalid byte sequence in UTF-8"

Ruby Rails Rack

これ面白かったので紹介。

Rack/Ruby on Rails: ArgumentError: invalid byte sequence in UTF-8 | Running with Rails - Dev Blog not only for Rails fanatics!

RailsアプリケーションのURLにこのパラメータ=>?%28t%B3odei%29をつけるとエラーになることがあるよということらしいです。セキュリティのような大きな問題にはつながらないはず。変なリクエストをされると場合によっては500が返るよってことでしょうか。

元記事を読むと基本的にはRails4のバグっぽい?ですね。Rails3で作ったサービスでは起こりませんでした。くれぐれもRailsで動いていると思われるサービスで試さないように。

このバグを踏んでいる場合は、Rackミドルウェアを書いてパラメータをちょっといじれば回避できるようになります。多分置き場所はapp/middleware/sanitizer.rbとかで大丈夫です。

class Utf8Sanitizer
  SANITIZE_ENV_KEYS = %w(
    HTTP_REFERER
    PATH_INFO
    REQUEST_URI
    REQUEST_PATH
    QUERY_STRING
  )

  def initialize(app)
    @app = app
  end

  def call(env)
    SANITIZE_ENV_KEYS.each do |key|
      string = env[key].to_s
      valid = URI.decode(string).force_encoding('UTF-8').valid_encoding?
      # Don't accept requests with invalid byte sequence
      return [ 400, { }, [ 'Bad request' ] ] unless valid
    end

    @app.call(env)
  end
end

で、上のミドルウェアを使うようにすれば一応リクエストが悪いよーということで返すことができるようになるわけです。

# in config/application.rb
module AppName
  class Application < Rails::Application
    config.middleware.use "Utf8Sanitizer"
  end
end