cat posts/%e4%bb%8a%e9%80%b1%e3%81%ae%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e8%80%83%e5%af%9f%ef%bc%9a%e3%80%8c%e6%9b%b8%e3%81%8f%e3%81%a0%e3%81%91%e3%80%8d%e3%81%8c%e5%ae%9f%e8%a1%8c%e3%81%be.md

今週のセキュリティ考察:「書ける」が「動かせる」になった——Gitea Git フック RCE(CVE-2026-60004)

自分のサーバーで動かす Git サービス Gitea に、リポジトリへの書き込み権限だけでサーバー上のコマンドを実行できる脆弱性 CVE-2026-60004(CVSS 9.8)が見つかり、1.27.1 で修正された[1][2][3][4]。

PART 1解説

3行でわかる要点

  • 仕組み:差分(パッチ)を適用する API に同じパッチを2回送ると、一時的なリポジトリの hooks フォルダに実行ファイルが置かれ、Git フックとして動く[4]。
  • 権限:コマンドは Gitea を動かす OS アカウントの権限で動く。環境によっては秘密情報、データベース、内部のサービスにまで届く[4]。
  • 外部の人でも:Gitea は既定で誰でもアカウントを登録できるため、設定を変えていない環境では、外部の人がアカウントを作って悪用できる[4]。

前提:Gitea と Git フック

Gitea は、GitHub のようなソースコード管理のサービスを、自社のサーバーで動かすためのソフトウェアです。Git には、コミットやプッシュなどの操作に合わせてスクリプトを自動実行する「フック」という仕組みがあり、テストの起動や通知に使われます。

フックはサーバー上で実際に実行されるプログラムなので、本来は管理者だけが置けるべきものです。リポジトリに「書ける」ことと、サーバー上で「プログラムを動かせる」ことは、権限としてまったく別物です。この2つが混ざると、今回のような問題になります。

まず押さえる用語

用語ひとことでもっと詳しく
CVE / CVSS脆弱性の世界共通の番号と、深刻度を 0.0〜10.0 で表す指標。IPA「共通脆弱性評価システムCVSS概説」
Git フックコミットやプッシュなど Git の操作のタイミングで自動実行されるスクリプト。CI の起動や通知に使われる正規の機能。Git「githooks」
ベアリポジトリ作業用のファイルを持たず、履歴だけを持つリポジトリ。サーバー側でよく使われる。Git「gitglossary」
RCERemote Code Execution。遠隔から任意のプログラムを実行されること。—

本来の仕組みと、どこが破られたか

パッチ適用 API の正常時と攻撃時正常時パッチを送信一時リポジトリに適用変更を記録結果を返す攻撃時同じパッチを2回送信衝突時の退避処理フック置き場の保護コマンドを実行
図1 パッチの内容が、一時リポジトリのフックの置き場所に書き込まれた(Gitea のアドバイザリと The Hacker News の記述をもとにした概念図)

Gitea の diffpatch API は、送られたパッチを一時的な「ベア」リポジトリに適用します。ベアリポジトリでは、リポジトリの一番上が Git の管理用フォルダそのものです[4]。

同じパッチを2回送ると「同じファイルを二重に追加した」衝突が起き、その退避処理でファイルが実際に書き出されます。書き出し先に hooks/post-index-change を指定しておくと、それが Git フックとして登録され、Git が索引を更新するときに実行されます[4]。図1の赤い破線は、フックの置き場所が守られていなかったことを示します。

攻撃の流れ

sequenceDiagram
    autonumber
    participant A as 攻撃者
    participant G as Gitea
    participant H as Gitフック
    participant S as サーバー
    A->>G: 細工したパッチを2回送信(書き込み権限のみ)
    G->>G: 衝突の退避処理でフックを配置
    G->>H: 索引の更新時にフックが起動
    H->>S: GiteaのOSアカウント権限でコマンド実行
    H->>G: 結果をブランチに保存し攻撃者が取得
  • 悪用には、書き込み権限、Git 2.32 以降、diffpatch の経路が有効なこと、実行可能な一時ファイル置き場が必要[4]。
  • 公開された実証コードは外部への通信を使わず、結果を Git のブランチに保存して取り出す[4]。

バグではなく、信頼の境目の見落とし(考察)

  • Git フックは正規の機能として正しく動いた。問題は、パッチの中身がフックの置き場所に届く経路が確かめられていなかったこと。「書き込める」と「サーバーで動かせる」が分かれていなかった。
  • 修正はリリースノートで SECURITY ではなく MISC の「refactor: git patch apply」として載っていた[4]。変更履歴だけを見ていると見落とす。
  • 同じ構造は GitHub Actions のワークフロー、GitLab CI の設定、自前の Webhook などにもある。リポジトリに書ける人がサーバー側の処理を起動できる構成はどこにでもある。

いま確認すること

  • 【Gitea を使っている】1.27.1 に更新する[1][2]。すぐに更新できない場合、誰でも登録できる設定を止めると外部からの経路は減らせるが、既存の利用者による悪用は防げない[4]。
  • 【Gitea を使っている】サーバー上の Git フックに、予期しない pre-receive / post-receive / update / post-index-change がないか確かめる。
  • 【全員】プルリクエストを出せる人が、ワークフローやフックを書き換えられる構成になっていないか確かめる。
# サーバー上の Git フックを確認する
ls .git/hooks/
# GitHub Actions:PR の差分でワークフローが変更されていないか確認する
git diff main...feature -- .github/workflows/

出典・参考リンク

一次情報

  1. Gitea Security Advisory GHSA-rcr6-4jqh-j84m
  2. Gitea Blog — Release of 1.27.1
  3. NVD — CVE-2026-60004

報道・解説

  1. The Hacker News — New Gitea RCE Lets Repository Writers Plant a Git Hook

PART 2問題(情報処理安全確保支援士 試験形式)

問1 午前II形式(4択)

Gitea の CVE-2026-60004 の本質的な原因として、最も適切なものはどれか。

  • ア Git フック機能そのものに、メモリ破壊のバグがあった
  • イ リポジトリへの書き込み権限で送れるパッチが、サーバー上で動くフックの置き場所に書き込めた
  • ウ 管理者パスワードが初期値のまま公開されていた
  • エ 通信が暗号化されておらず、送信したパッチが盗聴された
解答・解説を表示

解答:イ

Git フックは正規の機能として正しく動いており、問題はパッチの中身がフックの置き場所に届く経路が守られていなかったこと、つまり信頼の境目の見落とし。アは「誤作動ではない」という説明と矛盾する。ウとエは報告にない。

↑ Part 1「本来の仕組みと、どこが破られたか」を読み直す

問2 午後形式(記述)

A社は GitHub Actions で CI を運用しており、コントリビュータ権限をもつメンバーは誰でもプルリクエストを作成できる。CI のワークフローファイルはリポジトリ内の .github/workflows/ に置かれている。Gitea の CVE-2026-60004 の報道を受けて、B さんは①自社でも「書ける」と「動かせる」が分かれているかを確認すべきだと提案した。

設問 本文中の下線①について、A社で具体的に確認すべきことを40字以内で述べよ。

解答・解説を表示

解答例:プルリクエストでワークフローファイルを変更できる人と、その変更が審査されるか(38字)

リポジトリに書ける人がサーバー側の処理を起動できる構成は、GitHub Actions、GitLab CI、自前の Webhook などどこにでもある。PR の差分でワークフローの変更を確かめる。「GitHub のパスワードを変更する」は権限の分離とは関係がない。

↑ Part 1「バグではなく、信頼の境目の見落とし」を読み直す