カテゴリ: Rails 更新日: 2026/02/02

RailsのStrong Parametersでやってはいけない書き方!初心者でもわかるpermit!の危険と安全な書き方

Strong Parametersアンチパターン:permit!の危険と安全な代替
Strong Parametersアンチパターン:permit!の危険と安全な代替

先生と生徒の会話形式で理解しよう

生徒

「Railsでフォームの値を受け取るときに、Strong Parametersって使うみたいですが、permit!って書いたら全部許可できるって聞きました。」

先生

「確かにpermit!はすべてのパラメータを許可する強力な方法ですが、とても危険な使い方なんですよ。」

生徒

「危険なんですか?書き方が楽だから便利だと思ったのに……」

先生

「便利そうに見えて、セキュリティ上の大きなリスクがあるんです。今日はその理由と、安全な書き方を丁寧に解説していきましょう。」

1. Strong Parametersとは?

1. Strong Parametersとは?
1. Strong Parametersとは?

Strong Parameters(ストロングパラメータ)とは、Railsのコントローラで受け取る値を明示的に指定する仕組みです。

これにより、想定外の値が勝手に保存されるのを防ぐことができ、セキュリティを強化できます。

例えば、ブログ記事を保存する場合、次のようにparamsから許可するキーを指定します。


def post_params
  params.require(:post).permit(:title, :body)
end

:title:bodyだけを受け取るようにし、それ以外の項目はすべて無視されます。

2. permit!とは?なぜ使ってはいけない?

2. permit!とは?なぜ使ってはいけない?
2. permit!とは?なぜ使ってはいけない?

permit!は、すべてのパラメータを無条件で許可するメソッドです。

次のように書くと、送られてきた全データを一気に許可してしまいます。


def post_params
  params.require(:post).permit!
end

これは非常に危険なコードです。たとえば、悪意のあるユーザーが管理者フラグ(admin)や、他人のuser_idを勝手に含めて送ってきたとしても、それらがそのまま保存されてしまいます。

3. permit!の危険性を具体例で確認

3. permit!の危険性を具体例で確認
3. permit!の危険性を具体例で確認

たとえば、次のようなユーザー更新フォームがあるとします。


<form action="/users/1" method="post">
  <input name="user[name]" value="山田太郎" />
  <input name="user[admin]" value="true" />
</form>

そして、コントローラ側でpermit!を使っていた場合、


def user_params
  params.require(:user).permit!
end

悪意のあるユーザーが管理者になれてしまうという、大変な問題が起きます。

4. 安全なStrong Parametersの書き方

4. 安全なStrong Parametersの書き方
4. 安全なStrong Parametersの書き方

permit明示的に受け取る項目を一つひとつ指定するのが基本です。


def user_params
  params.require(:user).permit(:name, :email)
end

このようにしておけば、:name:emailしか保存されないので、予期せぬ項目が登録される心配はありません

5. ネストされたデータを扱う場合もpermitを使おう

5. ネストされたデータを扱う場合もpermitを使おう
5. ネストされたデータを扱う場合もpermitを使おう

たとえば、投稿と一緒にタグの情報を送るといった、ネストされたパラメータも、安全に扱うことができます。


def post_params
  params.require(:post).permit(:title, :body, tags: [])
end

tags: []のように配列として許可することで、指定されたデータだけが保存されるようになります。

6. 管理者だけ許可したい項目はコントローラ側で分岐

6. 管理者だけ許可したい項目はコントローラ側で分岐
6. 管理者だけ許可したい項目はコントローラ側で分岐

「管理者だけが:adminを更新できるようにしたい」といった場合は、条件分岐で対処します。


def user_params
  if current_user.admin?
    params.require(:user).permit(:name, :email, :admin)
  else
    params.require(:user).permit(:name, :email)
  end
end

このようにすることで、一般ユーザーにはadmin項目が反映されないように防止できます。

7. Strong ParametersはRailsセキュリティの基本

7. Strong ParametersはRailsセキュリティの基本
7. Strong ParametersはRailsセキュリティの基本

Strong Parametersは、Railsで安全にデータを扱うための基本的なセキュリティ機構です。

面倒だからといってpermit!を使ってしまうと、アプリケーション全体が乗っ取られる危険性もあります。

初心者のうちから、明示的に項目を許可する癖をつけることで、安全なWebアプリを作る力が身につきます。

まとめ

まとめ
まとめ

ここまで、Ruby on RailsにおけるStrong Parameters(ストロングパラメータ)の重要性と、安易にpermit!メソッドを使用することの危険性について詳しく解説してきました。Webアプリケーション開発において、ユーザーから送られてくるデータは「常に悪意があるかもしれない」という前提で扱う必要があります。Strong Parametersは、いわばアプリケーションの入り口に立つ「門番」のような役割を果たしており、許可されたデータのみを内部へ通すことで、データベースを不正な更新から守ってくれます。

Strong Parametersの核心:なぜ明示が必要なのか

Railsの設計思想には「設定より規約(CoC)」という言葉がありますが、セキュリティに関しては「規約」に甘えるのではなく、開発者が意図を持って「設定」することが求められます。permit!を使ってしまうと、その門番が不在の状態になり、どのようなデータも素通りさせてしまいます。これは、家の鍵をかけずに外出するのと同じくらい無防備な状態です。

具体的に、データベースの運用イメージを見てみましょう。例えば、ユーザー情報を管理するusersテーブルがあるとします。


id | name     | email              | admin
---+----------+--------------------+-------
1  | 佐藤健太 | sato@example.com   | false
2  | 鈴木美咲 | suzuki@example.com | false
3  | 高橋裕二 | taka@example.com   | true

もし、コントローラで次のような危険なコードを書いていた場合、どのようなことが起こるでしょうか。


# 危険な実装例
def update
  @user = User.find(params[:id])
  if @user.update(user_params)
    redirect_to @user, notice: '更新しました'
  else
    render :edit
  end
end

private

def user_params
  # 全てのパラメータを無条件で許可してしまう
  params.require(:user).permit!
end

悪意のあるユーザーが、ブラウザの開発者ツールなどを使い、リクエストにuser[admin]=trueという値を忍び込ませて送信したとします。すると、SQLは以下のように実行され、本来一般ユーザーであるはずの「佐藤健太」さんが管理者になってしまいます。


-- permit! によって admin フラグまで更新されてしまう
UPDATE users
SET name = '佐藤健太', admin = true, updated_at = '2026-01-30 17:00:00'
WHERE id = 1;

実行後のテーブルの状態は以下の通りです。


id | name     | email              | admin
---+----------+--------------------+-------
1  | 佐藤健太 | sato@example.com   | true  (←勝手に管理者に!)
2  | 鈴木美咲 | suzuki@example.com | false
3  | 高橋裕二 | taka@example.com   | true

これを防ぐためには、記事の中で説明した通り、許可する項目を絞り込む必要があります。


# 安全な実装例
def user_params
  params.require(:user).permit(:name, :email)
end

このように記述することで、たとえadmin=trueというデータが送られてきても、Rails側で無視され、データベースには反映されません。

配列やネストされた構造への対応

実務では、単一の値だけでなく、チェックボックスの選択値(配列)や、関連するモデルのデータ(ネストされたパラメータ)を同時に保存するケースも多々あります。その際も、permitの書き方を工夫するだけで安全性を保てます。


# 複数の役割(roles)を配列で受け取り、さらにプロフィール情報も許可する場合
def complex_user_params
  params.require(:user).permit(
    :name, 
    :email, 
    roles: [], 
    profile_attributes: [:address, :phone_number]
  )
end

このように、データ構造に合わせて正確に許可リストを作成することが、プロのエンジニアへの第一歩です。デバッグ中に「値が保存されない!」と悩んだときは、まずこのStrong Parametersで許可し忘れていないかを確認する癖をつけましょう。ログ(development.log)を見れば、Unpermitted parameterという警告が出ているはずです。

先生と生徒の振り返り会話

生徒

「先生、ありがとうございました!permit!がどれだけ怖いものか、具体的なテーブルの変化を見てゾッとしました。楽をしようとして、セキュリティホールを作ってしまうところでした。」

先生

「その気づきはとても大切ですよ。プログラミングにおいて『短いコードが良いコード』とされる場面は多いですが、セキュリティに関しては『明示的であること』が何よりも優先されます。Railsがわざわざ面倒な手続きを求めているのには、それだけの理由があるんです。」

生徒

「確かにそうですね。でも、開発の初期段階でカラムが頻繁に増えるとき、いちいちpermitを書き直すのが少し手間に感じてしまいます……。何かコツはありますか?」

先生

「気持ちは分かります(笑)。でも、それこそが『今、自分は何を保存しようとしているのか』を再確認する良い機会になります。もしカラムを増やしたのに画面から保存できないときは、ブラウザのコンソールではなく、Railsのサーバーログを見てください。どのパラメータがブロックされたか教えてくれるので、修正は簡単ですよ。」

生徒

「サーバーログですね。Unpermitted parameterというメッセージ、見たことがあります!あれはエラーではなく、Railsが守ってくれていた証拠だったんですね。これからはログを味方につけて、安全なコードを書けるように頑張ります!」

先生

「その意気です。管理権限の分岐なども含めて、Strong Parametersを使いこなせるようになれば、Railsエンジニアとしての信頼度はぐっと上がりますよ。次は、バリデーションについても学んで、さらに堅牢なアプリを目指しましょう!」

関連記事:
カテゴリの一覧へ
新着記事
New1
Ruby
“すべてはオブジェクト”を体感!初心者向けRubyのオブジェクト指向入門【irbで学ぶ】
New2
Ruby
Rubyの標準入出力を完全ガイド!puts・print・pの違いとデバッグ活用法
New3
Ruby
Gemとは?RubyGemsとBundlerを初心者向けに完全解説!依存関係管理も図解でわかりやすく理解
New4
Ruby
Rubyの文字エンコーディング入門!UTF-8・マジックコメント・外部/内部エンコーディングを完全解説
人気記事
No.1
Java&Spring記事人気No1
Ruby
Rubyのreduceとinject入門!合計計算や集計を初心者向けに分かりやすく解説
No.2
Java&Spring記事人気No2
Ruby
Rubyの文字列エンコーディング完全ガイド!Encoding・force_encoding・encodeを初心者向け解説
No.3
Java&Spring記事人気No3
Ruby
Rubyの始め方ガイド:インストールから最初のHello Worldまで(Windows/Mac/Linux)
No.4
Java&Spring記事人気No4
データベース
PostgreSQLのWHERE句を徹底解説!初心者でもわかるSQLデータ抽出の基本
No.5
Java&Spring記事人気No5
Ruby
Rubyのfind/detect/find_indexを徹底解説!目的のデータを素早く探す方法
No.6
Java&Spring記事人気No6
Ruby
Rubyで比較演算子を完全解説!==・===・<=>・eql? の使い分け
No.7
Java&Spring記事人気No7
Ruby
Rubyのselect/reject/filterの使い方を完全解説!初心者向けの条件抽出レシピ
No.8
Java&Spring記事人気No8
データベース
PostgreSQLで順位付け!ROW_NUMBER関数の使い方を初心者向けに徹底解説