セキュリティ

PostgreSQLの脆弱性CVE-2024-10979とは?PL/Perlで任意コード実行に至る仕組みと影響バージョン・確認手順【2026年8月時点】

CVE-2024-10979は、PostgreSQLの手続き言語PL/Perlが持つ環境変数の制御不備です。データベース上の一般ユーザー権限しか持たない相手が、サーバプロセスのPATHなどを書き換えられてしまい、そこから任意のコード実行につながります。修正版は17.1・16.5・15.9・14.14・13.17・12.21の6系統で、いずれも2024年11月14日に公開されています。これらより前のマイナーバージョンはすべて影響を受けます。この記事では、CVSS 8.8というスコアが実際にどういう前提を指しているのか、自分の環境が影響下にあるかを確かめるSQL、そして2026年8月時点でこのCVEだけを見ていると何を取りこぼすのかまでを、PostgreSQL公式の記述に沿って整理します。

まとめ

論点 結論
脆弱性の内容 trusted PL/Perlから%ENVを書き換えられる(CWE-15/CWE-610)
CVSS 8.8 High・PR:L(認証済みの一般DBユーザーが前提。未認証ではない)
修正版 17.1・16.5・15.9・14.14・13.17・12.21(すべて2024-11-14公開)
影響の有無 plperl拡張が未導入なら、この経路での影響なし
暫定緩和 plperlのUSAGEをPUBLICから剥奪(公式記載。新規関数の作成のみ遮断)
2026年8月時点 17.1で止めた環境は17系で計21件のCVE修正が未適用(うち2026年の定例2回で14件)
最新マイナー 18.4・17.10・16.14・15.18・14.23(2026-05-14公開)

対応の優先順位はひとつです。まず自分のマイナーバージョンを確認し、修正版以降へ上げます。すぐに再起動できない環境では、PL/PerlのUSAGE権限をPUBLICから剥がして新規のPL/Perl関数を作れなくしたうえで、次の定例マイナーリリース(2026年8月13日)に合わせて計画します。

CVE-2024-10979の内容とCVSS 8.8の内訳

PostgreSQL公式のセキュリティアドバイザリは、この脆弱性を「PostgreSQL PL/Perl environment variable changes execute arbitrary code」と表現しています。原文の説明は、PL/Perlにおける環境変数の制御が不適切なため、権限を持たないデータベースユーザーがPATHのような重要なプロセス環境変数を変更でき、それは攻撃者がデータベースサーバのOSユーザーを持っていない場合でも任意コード実行を可能にするのに十分なことが多い、という趣旨です。報告者はCoby Abrams氏で、公式は同氏への謝辞を掲載しています。

影響バージョンと修正版の対応表

影響を受けるのは、下表の修正版より前のすべてのマイナーバージョンです。修正はすべて同日、2024年11月14日にリリースされました。

メジャー版 修正版 公開日 2026-08時点の状態
17 17.1 2024-11-14 サポート中(現行17.10)
16 16.5 2024-11-14 サポート中(現行16.14)
15 15.9 2024-11-14 サポート中(現行15.18)
14 14.14 2024-11-14 サポート中(2026-11-12でEOL)
13 13.17 2024-11-14 EOL済(2025-11-13・最終13.23)
12 12.21 2024-11-14 EOL済(2024-11-21・最終12.22)

PostgreSQL 12系が対象に含まれている点は見落とされがちです。12.21はEOL直前のリリースで、その1週間後の2024年11月21日に出た12.22が12系の最終版になりました。12系を今も動かしている環境は、このCVEに対する修正を受け取れる最後の機会がすでに過ぎています。

CVSS 8.8のベクトルが示す前提条件

ベクトルはAV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H、基本値は8.8(HIGH)です。postgresql.orgのアドバイザリページは見出しをCVSS 3.0としていますが、同じPostgreSQLがCNAとして登録したCVEレコードとNVDの評価はいずれもCVSS 3.1で、ベクトルも基本値も3者で一致します。CWEはPostgreSQL側がCWE-15(システム設定の外部制御)、NVD側がCWE-610(別の領域にあるリソースへの外部制御可能な参照)を割り当てています。

ここで注意したいのがPR:L、つまり必要な権限が「低」である点です。8.8という数字だけを見て「インターネットから誰でも攻撃できる」と受け取ると、対応の設計を誤ります。攻撃の起点はあくまで認証を通過したデータベースユーザーであり、未認証のリモート攻撃ではありません。逆に言えば、アプリケーション用の一般ロールしか持たないアカウントが漏れた場合や、複数テナントに同一インスタンスを貸している構成では、この条件が現実的に成立します。CVSSの各項目が何を表しているかは、脆弱性とは?種類・CVE/CVSSの仕組みと発見から修正までの実務を解説で整理しています。

trusted PL/Perlから任意コード実行に至る仕組み

この脆弱性を理解する鍵は、PostgreSQLが手続き言語を「trusted」と「untrusted」に分けている点にあります。

trusted plperlとuntrusted plperluの権限境界

システムカタログpg_languagelanpltrusted列について、公式ドキュメントは「trusted言語であればtrue。trusted言語とは、通常のSQL実行環境の外部へのアクセスを与えないと考えられている言語を意味する。untrusted言語で関数を作成できるのはスーパーユーザーだけである」と定義しています。

PL/Perlはこの分類でtrusted側に置かれており、ドキュメントは「したがって、権限を持たないあらゆるデータベースユーザーにこの言語の使用を許可してよい」と述べています。ファイル操作のような危険な処理はPerlのOpcodeモジュールで遮断される、という前提です。一方、フルのPerlが使えるuntrusted版はplperluという別名で導入され、そちらで関数を作れるのはスーパーユーザーに限られます。

つまりCVE-2024-10979は、「安全だから一般ユーザーに開放してよい」とされていたtrusted側の境界が破れていた、という構図です。だからこそPR:Lで成立します。

PostgreSQL 17.1で入った修正内容

17.1のリリースノートには「trusted PL/Perlコードによる環境変数の変更を防ぐ(Andrew Dunstan、Noah Misch)。PATHのようなプロセス環境変数を操作できることは攻撃者に任意コード実行の機会を与えるため、trustedなPLはその能力を提供してはならない。plperlを修正するにあたり、%ENVをtied hashに置き換え、いかなる変更の試みも警告とともに拒否するようにした。untrustedなplperluは環境を変更する能力を保持する」と記載されています。

修正後の挙動として押さえるべきは2点です。ひとつは、修正版でもplperluからは従来どおり環境変数を変更できること。これは仕様であり、plperluの関数を作れるスーパーユーザーはもともとサーバ上で何でもできる立場だからです。もうひとつは、修正がエラーではなく警告で拒否する形になっているため、%ENVへの代入を含む既存のtrusted plperl関数はアップデート後も動き続け、意図した環境変数の変更だけが効かなくなるという点です。環境変数の書き換えに依存したPL/Perl関数がある場合、壊れずに静かに機能だけを失います。

なお、17.1と同時にリリースされた16.5・15.9・14.14・13.17・12.21には、CVE-2024-10979を含め4件のCVE修正(CVE-2024-10976、CVE-2024-10977、CVE-2024-10978、CVE-2024-10979)がまとめて入っています。この回はPL/Perl単独の修正ではありません。

自環境が影響を受けるかの確認手順

「PostgreSQLを使っている」だけでは影響の有無は決まりません。確認すべきはマイナーバージョンと、plperlが実際に導入されているかの2点です。

稼働中サーバのマイナーバージョン確認

接続先サーバのバージョンは、psqlのクライアント側表示ではなくサーバ側の設定値で確認します。server_version_numは整数で返るため、バージョン比較を条件分岐で書くときに扱いやすくなります。

-- サーバのバージョン文字列とビルド情報
SELECT version();

-- サーバのバージョンだけを取得
SHOW server_version;

-- 整数表現(例: 17.10 なら 170010)
SHOW server_version_num;

公式ドキュメントはserver_versionを文字列型、server_version_numを整数型のプリセットパラメータと定義しており、いずれもビルド時のPG_VERSIONおよびPG_VERSION_NUMの値で決まると説明しています。パッケージ管理システム側のバージョン表示とサーバプロセスの実行バージョンは、アップデート後に再起動していない環境ではずれます。判断はこのSQLの結果で行ってください。

plperlの導入有無と利用権限の確認

plperlは既定で有効になっている拡張ではありません。導入されていなければ、この経路での影響は生じません。

-- plperl 系の拡張が導入されているか
SELECT extname, extversion
FROM pg_extension
WHERE extname LIKE 'plperl%';

-- 言語として登録されているか、trusted かどうか
SELECT lanname, lanpltrusted, lanacl
FROM pg_language
WHERE lanname LIKE 'plperl%';

-- 導入可能な拡張として存在するか(未導入なら installed_version が NULL)
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name LIKE 'plperl%';

pg_available_extensionsinstalled_version列は、公式ドキュメントで「現在インストールされている拡張のバージョン、未インストールならNULL」と定義されています。ここがNULLであれば、パッケージとして配置されてはいるが有効化されていない状態です。

plperlが導入済みだった場合は、誰が使えるかを確認します。特定のロールに対する判定に使えるのがhas_language_privilege関数です。公式ドキュメントは、この関数で指定できる権限種別をUSAGEのみと定めています。

-- 特定ロールが plperl を使えるか
SELECT has_language_privilege('app_user', 'plperl', 'USAGE');

-- 既に作成済みの PL/Perl 関数を洗い出す
SELECT n.nspname AS schema, p.proname AS function, l.lanname AS language
FROM pg_proc p
JOIN pg_language l ON l.oid = p.prolang
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE l.lanname IN ('plperl', 'plperlu')
ORDER BY 1, 2;

2つ目のクエリの結果は、以降の判断で二度使います。アップデート後に挙動が変わる関数の洗い出しと、緩和策を選ぶときの前提確認です。

修正版へのアップデートと再起動できない場合の緩和策

マイナーアップデートの手順とダンプ不要の根拠

PostgreSQLのバージョニングポリシーは、マイナーリリースのアップグレードについて「ダンプとリストアは不要である。単純にデータベースサーバを停止し、更新されたバイナリをインストールし、サーバを再起動するだけでよい」と明記しています。同時に「そうしたアップグレードには追加の手順が必要な場合があるので、常に先にリリースノートを読むこと」とも付記されています。メジャーバージョンの移行はデータディレクトリの互換性が保てないためpg_upgradeまたはダンプとリロードが必要ですが、17.0から17.1のような移行はこれに当たりません。

# Debian / Ubuntu 系(例: PostgreSQL 17)
sudo systemctl stop postgresql
sudo apt-get update
sudo apt-get install --only-upgrade postgresql-17
sudo systemctl start postgresql

# RHEL 系(PGDG リポジトリ利用時)
sudo systemctl stop postgresql-17
sudo dnf update postgresql17-server
sudo systemctl start postgresql-17

# 反映確認(サーバプロセスの実行バージョン)
psql -c "SHOW server_version_num;"

停止時間が問題になる構成では、レプリカを先に更新してからスイッチオーバーする順序で影響を抑えられます。フェイルオーバーを含む構成管理はrepmgrとは?PostgreSQLのレプリケーション管理と自動フェイルオーバー構築を解説【2026年版】で扱っています。

再起動を待てない場合のUSAGE権限剥奪

変更凍結期間などで即座に再起動できない場合、攻撃面を先に閉じる選択があります。PL/Perlの公式ドキュメントには、Opcodeモジュールに依存したtrusted PL/Perlの安全性についての警告があり、そこに次の案内が置かれています。Perlはこのモジュールがtrusted PL/Perlの用途には有効でないと文書化している、その警告に含まれる不確実性がセキュリティ要件と両立しないなら、REVOKE USAGE ON LANGUAGE plperl FROM PUBLICの実行を検討せよ、というものです。

-- PUBLIC から plperl の USAGE を剥奪する
REVOKE USAGE ON LANGUAGE plperl FROM PUBLIC;

-- 必要なロールにだけ明示的に付与し直す
GRANT USAGE ON LANGUAGE plperl TO batch_role;

-- 剥奪後の状態を確認(lanacl に PUBLIC の USAGE が残っていないこと)
SELECT lanname, lanacl FROM pg_language WHERE lanname = 'plperl';

ここで正確に押さえておきたいのは、この操作が塞ぐ範囲です。公式ドキュメントの権限一覧は、手続き言語に対するUSAGEを「その言語で関数を作成するために言語を使用することを許可する」と定義しており、関数の呼び出しに効くのはEXECUTEのほうです。つまりUSAGEの剥奪で止まるのは新規のPL/Perl関数とDOブロックの作成であって、すでに存在するplperl関数は引き続き呼び出せます。本CVEの悪用には攻撃者自身がPerlコードを書き込む必要があるため実務上はこれで足りますが、前掲の棚卸しクエリで既存関数の中身を確認しておくべきなのはこのためです。

そして、これはあくまで暫定策であって修正の代替ではありません。plperlは1つの経路にすぎず、同じPR:Lの前提で成立する他のCVEはこの操作では塞がらないからです。plperlを業務で使っていない環境であれば、USAGEを剥奪するのではなくDROP EXTENSION plperlで外してしまうほうが運用は単純になります(前掲のクエリでplperl関数がゼロであることを確認してから実行してください。関数が残っていると依存エラーで失敗します)。

2026年8月時点でPostgreSQL 17.1のまま止めてはいけない理由

このCVEに対応するために17.1へ上げ、そのまま運用を続けている環境は、対応済みではありません。CVE単位で追う運用は、この時点で破綻しています。

17.1以降に17系へ入ったCVE修正21件の内訳

17.1から現行の17.10までに、17系には21件のCVE修正が入っています。内訳は2025年が7件(CVE-2025-1094、CVE-2025-4207、CVE-2025-8713、CVE-2025-8714、CVE-2025-8715、CVE-2025-12817、CVE-2025-12818)、2026年が14件で、2026年分は2月12日の17.8で4件、5月14日の17.10で10件です。17.1のままの環境は、この21件すべてが未適用ということになります。

CVE CVSS v3 ベクトルの前提 内容 修正版
CVE-2024-10979 8.8 PR:L PL/Perlの環境変数制御不備 17.1(2024-11-14)
CVE-2026-2004 8.8 PR:L intarrayの選択性推定への入力型の検証漏れ 17.8(2026-02-12)
CVE-2026-2005 8.8 PR:L pgcryptoのヒープバッファオーバーフロー 17.8(2026-02-12)
CVE-2026-2006 8.8 PR:L マルチバイト文字長の検証漏れ 17.8(2026-02-12)
CVE-2026-6473 8.8 PR:L 整数の桁あふれによる確保サイズ不足 17.10(2026-05-14)
CVE-2026-6637 8.8 PR:L refintのスタックバッファオーバーフローとSQLインジェクション 17.10(2026-05-14)

並べてみると同じ形が見えます。上記6件はいずれもCVSS基本値8.8で、ベクトルもAV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hで完全に一致します。CVE-2024-10979が特別に危険なのではありません。「認証済みの一般DBユーザーから任意コード実行に至る」というまったく同じ形の欠陥が、2026年だけで5件見つかり、そのつどマイナーリリースで塞がれているというのが実態です。追うべき単位はCVEではなく、マイナーリリースです。

なお表のうちCVE-2026-2004(intarray)、CVE-2026-2005(pgcrypto)、CVE-2026-6637(refint)はcontribモジュールの欠陥です。contribはソースからのインストールでは既定で入りませんが、ディストリビューションのバイナリパッケージでは同梱されることがある、と公式のセキュリティ一覧に注記されています。pgcryptoは暗号化関数として業務システムで使われる頻度が高く、「拡張は入れていないつもり」の環境ほど確認が要ります。

修正そのものが後続リリースで直された2つの実例

「CVEを1件つぶせば終わり」という運用が成り立たない理由は、PostgreSQL自身の履歴に残っています。17系だけで2回、セキュリティ修正のあとに是正リリースが出ています。

1つ目は、この記事の主題であるCVE-2024-10979を修正した17.1の直後です。1週間後の2024年11月21日に出た17.2のリリースノートには、先週のマイナーリリースがtimescaledbほかいくつかの拡張とのバイナリ互換性を意図せず壊したため、影響を受けた構造体を以前のサイズに戻して拡張の再ビルドを不要にした、と記載されています。同じ17.2では、CVE-2024-10978の修正が非対話的な経路から与えられたロール設定を適用しなくする不具合を招いていた点も直っています。CVE-2024-10979に対応して17.1を当てた環境は、その時点では17.2まで進む必要がありました。

2つ目は2026年です。17.8のCVE-2026-2006修正について、2026年2月26日の17.9のリリースノートは、その修正が過剰であり、実際には妥当なケースでも不完全な文字に関するエラーを発生させることがあった、と記載しています。17.8を当てただけの環境は17.9以降へ上げる必要があります。定例日程の外にもリリースが出るのは、こうした場合です。

PostgreSQL 13・12のEOLとマイナー修正の打ち切り

PostgreSQLはメジャーバージョンを初回リリースから5年間サポートし、その後は最終マイナーバージョンを出して終了します。2026年8月時点のサポート状況は次のとおりです。

メジャー版 現行マイナー サポート 初回リリース 最終リリース
18 18.4 あり 2025-09-25 2030-11-14
17 17.10 あり 2024-09-26 2029-11-08
16 16.14 あり 2023-09-14 2028-11-09
15 15.18 あり 2022-10-13 2027-11-11
14 14.23 あり 2021-09-30 2026-11-12
13 13.23 なし 2020-09-24 2025-11-13
12 12.22 なし 2019-10-03 2024-11-21

13系は2025年11月13日の13.23で、12系は2024年11月21日の12.22で終わっています。この2系統では、2026年に見つかった上記のCVEに対する修正マイナーが出ません。CVE-2024-10979への対応として13.17や12.21へ上げた環境は、その1件については修正済みですが、以降に積み上がった欠陥はそのまま残ります。EOL済みの系統に留まる限り、この差は時間とともに開く一方です。

次に期限を迎えるのは14系で、2026年11月12日です。3か月後に迫っています。14系で動かしているシステムは、CVE-2024-10979の確認と同じタイミングでメジャーアップグレードの計画に着手すべき段階に来ています。

定例マイナーリリースの日程と追随の運用

PostgreSQLプロジェクトは四半期に最低1回のマイナーリリースを予定日つきで実施しており、対象日は原則として2月・5月・8月・11月の第2木曜日です。公表されている今後の日程は、2026年8月13日、2026年11月12日、2027年2月11日、2027年5月13日です。重大なバグやセキュリティ問題があればこの間にも追加リリースが行われるため、この一覧は下限として扱う旨がロードマップに明記されています。次のメジャーリリースはPostgreSQL 19で、2026年9月が予定時期です(2026年7月16日にBeta 2が公開済み)。

運用に落とすなら、年4回の予定日をカレンダーに固定し、リリース当日ではなくリリースノートを読んだうえで数日以内に検証環境へ適用する、という周期を作るのが現実的です。CVEが報道されてから慌てて調べる進め方は、PR:Lの脆弱性が年に何件も出る以上、必ず後手に回ります。導入済みパッケージの脆弱性を継続的に検出する仕組みについてはOSV-Scannerとは?Google製OSS脆弱性スキャナの使い方とTrivyとの違いが参考になります。

よくある質問

PostgreSQL 12のサポート期限はいつですか?

2024年11月21日で終了しています。最終マイナーバージョンは12.22です。CVE-2024-10979の修正版12.21はその1週間前の2024年11月14日に出ており、12系がセキュリティ修正を受け取れた最後の時期にあたります。12系を稼働させている場合、2025年以降に公表されたPostgreSQLのCVEに対する修正は提供されません。

自分のPostgreSQLのバージョンはどう確認しますか?

接続したうえでSHOW server_version_num;またはSELECT version();を実行します。server_version_numは整数で返り、17.10であれば170010となります。パッケージ管理システムの表示やpsqlのクライアントバージョンは、更新後に再起動していない環境では実際に動いているサーバのバージョンと一致しません。判断はサーバ側の値で行ってください。

マイナーバージョンアップにダンプとリストアは必要ですか?

不要です。PostgreSQL公式のバージョニングポリシーは、マイナーリリースのアップグレードはダンプとリストアを必要とせず、サーバを停止し、更新されたバイナリをインストールし、再起動するだけでよいと記載しています。ただし追加の手順が必要な場合があるため、対象バージョンのリリースノートを先に読むよう併せて案内されています。ダンプとリロードまたはpg_upgradeが必要なのはメジャーバージョンの移行です。

CVSS 8.8ということは、未認証でもインターネットから攻撃されますか?

されません。ベクトルのPR:Lは攻撃に低い権限が必要であることを示しており、この脆弱性の起点は認証を通過したデータベースユーザーです。ただし、アプリケーション用ロールの認証情報が漏れた場合や、複数の利用者に同一インスタンスを開放している構成では条件が成立します。攻撃面が外部ネットワークではなくDBアカウントの管理にある、と読み替えて対策の優先度を決めてください。

2026年8月時点でPostgreSQLの最新バージョンはどれですか?

メジャーバージョンは18で、現行マイナーは18.4です。サポート中の各系統の現行マイナーは18.4・17.10・16.14・15.18・14.23で、いずれも2026年5月14日にリリースされました。次の定例マイナーリリースは2026年8月13日に予定されています。マイナーバージョンは四半期ごとに更新されるため、実際に適用する前にPostgreSQL公式のバージョニングポリシーのページで最新の値を確認してください。

関連記事

資料請求

RELATED POSTS 関連記事