コンテンツへスキップ

最小権限の原則とは — ファイルパーミッション 600/644/755 がなぜ存在するか

SSH の秘密鍵を扱っていると、「600 にしてください」という指示によく出会います。逆に設定ファイルには 644、実行可能なスクリプトには 755 が使われる場面もあります。これらの3桁の数字は何を表していて、なぜファイルの種類によって使い分けられているのでしょうか。本稿では、Unix系OS(Mac/Linux)のパーミッション表記の仕組みから出発し、その背後にある「最小権限の原則」という考え方まで整理します。

パーミッションは「誰に」「何を」許可するかの2次元表

Unix系OSでは、ファイルへのアクセス権限を「誰に」(3種類)×「何を」(3種類)の掛け合わせで表現します。

「誰に」は、ファイルの所有者(owner)・所有者と同じグループに属するユーザー(group)・それ以外の全員(other)の3種類。「何を」は、読み取り(read)・書き込み(write)・実行(execute)の3種類です。

この3×3のマス目それぞれに許可・不許可を立てるのがパーミッション設定で、ls -l で見る -rw-r--r-- のような表記はこれを文字で表したものです。先頭の1文字を除いた9文字が、owner/group/other それぞれの rwx を3文字ずつ並べたもので、権限があれば対応する文字(r/w/x)、なければ - になります。

なぜ数字1桁で rwx を表せるのか

chmod 600 のような数字表記は、この rwx の組み合わせを8進数1桁に圧縮したものです。read=4、write=2、execute=1という2の累乗を割り当て、立っているビットを足し算します。

補足: 2の累乗を割り当てているのは、rwxそれぞれの有無をビット単位(0か1か)で管理し、その組み合わせを1つの数字に一意に対応させるため。4+2+1のどの足し算の組み合わせを取っても、元のrwxの組み合わせに一意に戻せる(例えば6は4+2=readとwriteだけ、他の組み合わせでは6にならない)。

  • 読み書き両方(rw-)なら 4+2 = 6
  • 読み取りのみ(r–)なら 4
  • 読み書き実行すべて(rwx)なら 4+2+1 = 7
  • 権限なし(—)なら 0

600 という3桁は、左から owner/group/other の順に、この1桁の値を並べたものです。600 は「owner だけ読み書き可・group と other は権限なし」を意味します。

具体的な数字が何を意味しているか

冒頭に挙げた代表的な数字を、この仕組みに沿って読み解くと以下のようになります。

数字 owner group other 典型的な用途
600 rw- 秘密鍵・パスワードを含む設定ファイル
644 rw- r– r– 一般的な設定ファイル・公開して問題ないデータ
700 rwx 個人用ディレクトリ(~/.ssh 等)
755 rwx r-x r-x 実行可能スクリプト・誰でも実行してよいプログラム

パターンを見ると、owner には常に必要な権限(読み書き、時に実行)が与えられ、group と other にはその時々で「読むことだけ許す」か「一切触らせない」かのどちらかが選ばれています。group や other に write 権限を与える組み合わせ(666 や 777 等)が定番として登場しないのは、それが「所有者以外の誰でもファイルを書き換えられる」状態を意味し、意図的にそうする必要がある場面がほとんどないためです。

最小権限の原則 — 「必要な分だけ」を数字で強制する

ここまでの数字の使い分けは、セキュリティ設計における「最小権限の原則」(principle of least privilege)を、OSのファイルシステムレベルで体現したものです。

補足: 最小権限の原則とは、あるユーザーやプロセスに与える権限は、その仕事を遂行するために本当に必要な最小限にとどめるべきだという設計原則。権限を多く持たせるほど、誤操作や乗っ取りが起きたときの被害範囲(ブラスト・レディウス)が広がるため。

秘密鍵に 600 を要求するのは、「この鍵を読む必要があるのは所有者本人だけであり、それ以外の誰にも読む理由がない」という前提に立っているからです。同じマシンを複数人が使っている環境(共用サーバーの /tmp 等)で group や other に read 権限が残っていると、他のユーザーが秘密鍵の中身を読み取れてしまいます。SSHクライアント(OpenSSH・paramiko 双方)は、この状態を検出すると鍵の読み込みそのものを拒否します。「読めてしまう可能性がある」時点で、実際に読まれたかどうかに関わらず安全とはみなさない、という厳格な立場です。

一方で設定ファイルの多くが 644(group・other は read のみ)で運用されるのは、「他のユーザーが中身を見ても実害がない」情報だからです。実行可能スクリプトの 755 も同様で、「誰でも実行してよいが、書き換えてよいのは所有者だけ」という要件をそのまま数字に落とし込んだ形です。パーミッションの数字は、単なる慣習ではなく「このファイルは誰にどこまで触らせてよいか」という設計判断の表現そのものです。

実装例 — core/key_perms.py の group/other ビットチェック

このアプリのSSH鍵パーミッション診断ロジック(core/key_perms.py::_diagnose_posix())は、この最小権限の考え方をそのままコードに落とし込んでいます。

mode = stat.S_IMODE(st.st_mode)
mode_str = oct(mode)[-3:].zfill(3)
# group (070) / other (007) に何らかのビットが立っていれば NG
group_other_bits = mode & 0o077
ok = (group_other_bits == 0)

ここでのポイントは、mode == 0o600 のような厳密一致ではなく、mode & 0o077 というビット単位のマスク演算で判定している点です。0o077 は2進数で 000 111 111(owner のビットはすべて0・group と other のビットはすべて1)を表しており、この値と mode の論理積(AND)を取ると、owner 側のビットは強制的に0になり、group・other 側のビットだけが残ります。結果が0であれば「group・other にはどんな権限も一切与えられていない」ことが確定します。

この判定方式なら、600(rw——-)だけでなく 400(r——–・読み取り専用)も等しく合格と扱えます。owner の権限が何であるかは問わず、「group と other に何も渡していないか」だけを見る設計です。逆に owner の権限を厳密に固定してしまうと、chmod 400 で運用したい人(読み取り専用にして誤って上書きするのを防ぎたいケース)まで弾いてしまい、最小権限の原則が本来求めている「group/other への露出を断つ」という目的から外れた過剰なチェックになってしまいます。

Windows には8進数のパーミッションがない

ここまでの数字表記(600・644 等)は POSIX(Unix系OS)に固有の仕組みで、Windows のファイルシステム(NTFS)には存在しません。Windows は代わりに ACL(アクセス制御リスト)という、アカウントごとに個別の権限エントリを積み重ねる方式を使います。

core/key_perms.py::_diagnose_windows() では、icacls コマンドの出力から BUILTIN\UsersEveryone のような「特定の個人ではないアカウント」への権限付与が残っていないかを確認しています。仕組みは POSIX の group/other チェックとまったく違いますが、狙っているのは同じことです。「鍵の所有者本人以外の誰にもアクセスさせない」という最小権限の原則を、ACL という別の語彙で表現しているに過ぎません。実装の形は OS ごとに変わっても、そこにある設計原則は共通しています。

V11 記事との違い

以前の記事「「Permissions are too open」を内側から解く」では、パーミッション不備を検出したときに、アプリがユーザーの同意を得た上で自動修正する UX 設計(診断→同意確認→修正という Phase 1/2 のハイブリッド、起動時の無断書き換えは不採用にした判断)を扱いました。本稿はその一段手前、「そもそもなぜ 600 という数字が要求され、なぜそれで安全とみなせるのか」という、パーミッション表記そのものの仕組みを扱っています。V11 が「壊れたパーミッションをどう直すか」の設計判断だとすれば、本稿は「パーミッションの数字が何を意味しているか」という前提知識にあたります。

まとめ

600644700755 といったパーミッション数値は、owner/group/other という3種類の対象に read/write/execute の3種類の権限を割り当て、各行の合計を8進数1桁で表したものです。その使い分けの根底にあるのは、「そのファイルに触れる必要がある相手にだけ、必要な権限だけを与える」という最小権限の原則です。秘密鍵に group/other の権限が一切残っていないことをビットマスクで確認する core/key_perms.py の実装は、この原則をコードの形で機械的に強制する具体例です。数字の意味を理解しておくと、「なぜ 644 では鍵が拒否されるのか」がエラーメッセージを読むだけでなく、その根拠から納得できるようになります。