Python パッケージを PyPI に公開する経路に、別々の脆弱性が2件出た。GitHub Actions の定番 pypi-publish(pypa/gh-action-pypi-publish)が失効対象の emSign ルートCAを同梱していた問題(1.14.3 で除去・CVSS v4 9.3)と、npm の @sigstore/oci が認証情報を別ホストへ送りうる問題(CVE-2026-118763・0.7.2 で修正)だ。別物だが、どちらも PyPI の Trusted Publishing と Sigstore 署名の“信頼の土台”に関わる。この記事は GHSA を一次に、pypi-publish 脆弱性を含む2件の中身と更新手順を整理する。攻撃の再現手順(PoC)は扱わない。まず確かめることは、自分の公開ワークフローがこの2つの部品を使っているか、使っているなら修正版以上かだ。

WHAT HAPPENEDPyPI公開まわりの信頼と資格情報

CIの公開経路に2つの別々の穴

  1. ① 信頼ストアに失効CA

    pypa/gh-action-pypi-publish が emSign ルートCAを certifi 経由で同梱。eMudhra の失効対象。1.14.3 で除去(Critical・CVSS v4 9.3)

  2. ② 資格情報のcross-host漏れ

    @sigstore/oci が Authorization ヘッダを、応答の Location(別ホスト)にそのまま送る。CVE-2026-118763・0.7.2 で修正(High 7.4)

  3. 共通テーマ

    どちらも PyPI の Trusted Publishing と Sigstore 署名の『信頼の土台』の問題。別々の脆弱性だが同じ公開経路に乗る

  4. やることは更新

    pypi-publish は 1.14.3、@sigstore/oci は 0.7.2 へ。ワークフローの固定(pin)先も確認

出典: GHSA-5xjx-3w67-w9x9 / GHSA-j63v-mwhm-56jx(2026-11-02 確認)。公開2026-10-21/26

30秒でわかる(2026-11-02確認)

  • ・PyPI の公開経路に別々の2件。どちらも「使っているなら修正版へ上げる」。
  • ・① pypi-publish が失効CAを同梱(emSign ルートCA・CWE-295)。1.14.3 で除去(Critical・v4 9.3)。
  • ・② @sigstore/oci が認証情報を別ホストへ(応答 Location を無検査でPUT・CWE-522)。0.7.2 で修正(CVE-2026-118763・High 7.4)。
  • ・9.3 は「即RCE」ではない。①は信頼ストアの衛生、②は悪意あるレジストリが前提。それでも土台の話なので早めに。

供給網攻撃の全体像はサプライチェーン攻撃とは|手口・防御ツール比較・npm 12の新機構まで実践解説に、CA 側の背景はMSRC『今すぐパッチを』|PHP2Shell・Brotli・eMudhraにまとめている。今回はその「公開(publish)の瞬間」に絞った2件だ。

何が起きたのか:信頼ストアと、認証情報の送信先

背景を一つ押さえておくと、2件の意味が通りやすい。PyPI の Trusted Publishing は、長命の API トークンを CI に置く代わりに、GitHub などの OIDC で短命の資格情報を得て公開する仕組みで、Sigstore による署名(Digital Attestations)で「誰がどのワークフローから出したか」を証明する。狙いは、盗まれると致命的な公開トークンを手元から無くすことだ。ところがこの方式では、安全の重心が「署名と証明書チェーンの信頼」に移る。だから、信頼ストアに紛れた失効CA(①)や、レジストリとのやり取りで漏れる認証情報(②)は、トークンレス化で得たはずの安心をそのまま崩しかねない。トークンを無くした代わりに、信頼の土台そのものを堅く保つことが要になる、という話だ。

2件は原因も場所も別だが、どちらも「正しく公開したはずの成果物が、信頼の土台から崩れる」タイプだ。まず性格の違いを押さえる。

TWO ISSUES何が問題か

失効CAの同梱/認証情報の送信先

① pypi-publish の CA (CWE-295)

② @sigstore/oci の資格情報 (CWE-522)

① pypi-publish の CA (CWE-295): certifi 経由で emSign ルートCAを信頼ストアに同梱

② @sigstore/oci の資格情報 (CWE-522): Authorization を共有クライアントの既定ヘッダに設定

① pypi-publish の CA (CWE-295): そのCAは eMudhra 絡みで失効対象=信頼すべきでない

② @sigstore/oci の資格情報 (CWE-522): 応答の Location のホスト/スキームを検査せずPUT

① pypi-publish の CA (CWE-295): 不正な証明書チェーンを受け入れる恐れ(1.14.3で除去)

② @sigstore/oci の資格情報 (CWE-522): 別ホストへユーザー名/パスワードやトークンが漏れる

出典: 両GHSAの説明(2026-11-02 確認)。②はソース精査ベースで実push/通信捕捉は未実施とされる
  ① pypi-publish の失効CA ② @sigstore/oci の資格情報漏れ
対象 pypa/gh-action-pypi-publish(GitHub Actions) npm @sigstore/oci(sigstore-js)
種類 証明書検証の不備(CWE-295) 認証情報の保護不足(CWE-522)
深刻度 Critical・CVSS v4 9.3 High・CVSS 3.1 7.4(CVE-2026-118763)
影響版 → 修正版 ≤ 1.14.2 → 1.14.3 ≤ 0.7.1 → 0.7.2
何が問題 失効対象の emSign ルートCAを信頼ストアに同梱 応答 Location(別ホスト)へ認証情報ごとPUT

① pypi-publish の失効CA。 pypa/gh-action-pypi-publish は、PyPI の Trusted Publishing(OIDC で鍵を持たずに公開する仕組み)と Digital Attestations で Sigstore を使い、その証明書チェーンの検証に certifi の信頼ストアを用いる。その中に、eMudhra 絡みで失効対象となった emSign のルートCAが同梱されていた。信頼ストアに「信頼すべきでないCA」が残っていると、本来弾くべき証明書チェーンを受け入れてしまう恐れがある(CWE-295)。1.14.3 で、このCAが取り除かれた。

② @sigstore/oci の資格情報漏れ(CVE-2026-118763)。 OCI レジストリへ署名やattestationをpushする経路の問題だ。signIn() が Authorization ヘッダを共有クライアントの既定ヘッダとして設定し、uploadBlob() がレジストリ応答の Location ヘッダが指すURLへPUTする。ここで Location のホストやスキームがレジストリと一致するか検査しないため、悪意ある(または侵害された)レジストリが別ホストの絶対URLを返すと、Basic のユーザー名/パスワード、Bearer のトークン、カスタム認証ヘッダがそのホストへ送られてしまう。内部のリダイレクト追従はホストが変われば Authorization を外すが、この PUT は明示的な新規リクエストなので保護が効かなかった。0.7.2 で修正されている。

なぜ「9.3」を鵜呑みにしないか

①の CVSS v4 9.3 は高いが、性格は「危険なコードが動く」ではない。信頼すべきでないCAが信頼ストアに残っていた、という証明書検証の不備だ。実際に害が出るには、「その失効CAで発行された証明書を使ったなりすまし」といった条件が要る。だから「9.3=即侵害」と読むのは正確でない。とはいえ、信頼の土台(どのCAを信じるか)の問題であり、公開物の真正性に関わるので、放置してよい種類でもない。更新して危険なCAを外すのが筋だ。

②も、悪意あるレジストリ(または侵害・なりすまし)に自分からpushすることが前提で、UI:R(利用者操作が要る)だ。社内の信頼できるレジストリだけを相手にしているなら当面の実害は小さい。だが、サードパーティのレジストリやミラー、設定ミスで向き先が変わるケースを考えると、認証情報が一度でも別ホストに渡ればトークンの悪用に直結する。開発基盤を狙う供給網攻撃の近接事例はKubeflow Pipelines の2件やCursor 改ざん拡張のSSHバックドアも参考になる。

自分のCIを確認し、更新する

やることは「使っているか」を見て、使っていれば版を上げることだ。まず GitHub Actions のワークフローで pypi-publish の固定(pin)先を確認する。

# .github/workflows/*.yml の該当行を確認(1.14.2 以前は失効CAを同梱)
#   uses: pypa/gh-action-pypi-publish@release/v1   ← majorピンは実解決版の確認を
#   uses: pypa/[email protected]       ← 1.14.3 以上に
# SHAピンなら、1.14.3 のコミットSHAへ更新する

@release/v1 や @v1 のようなメジャー/フローティング指定だと、実際に解決されるバージョンが 1.14.3 以上かは別途確認が要る(キャッシュや固定で古いままのこともある)。②の @sigstore/oci は、OCI レジストリへ署名/attestationをpushする経路で使っている場合に関係する。依存を 0.7.2 以上へ上げる。

# @sigstore/oci を使っているか・版はいくつかを確認
npm ls @sigstore/oci 2>/dev/null || true
# 0.7.2 以上へ更新(直接依存なら)
npm install @sigstore/oci@^0.7.2

※これらは使用の有無と版の確認であって、この表示だけでは、過去に失効CAを信頼して検証が通ってしまっていたか・認証情報がすでに渡ってしまったかまでは判断できない。心配があれば、②はレジストリのアクセストークンのローテーションも検討する。

CHECK & FIX確認と対策

2つを更新し、固定先と関連を確認

  1. 1.pypi-publish を 1.14.3 へ

    GitHub Actions ワークフローの uses: pypa/gh-action-pypi-publish のピン(タグ/SHA)を 1.14.3 以上へ。1.14.2 以前は失効CAを同梱

  2. 2.@sigstore/oci を 0.7.2 へ

    OCIレジストリへ署名/attestationをpushする経路で使うなら 0.7.2 以上へ。0.7.1 以前は資格情報のcross-host漏れ

  3. 3.固定(pin)先を実際に確認

    @vX や major ピンだと自動で上がらないことがある。解決される実バージョンを確認。SHAピンなら更新コミットに追従

  4. 4.関連の過去advisoryも

    ②は @sigstore/oci の CVE-2026-59891 の続きで、別経路が未修正だった件。CAの失効は eMudhra の一連と地続き

出典: 両GHSAの対策欄・修正版(2026-11-02 確認)。CVE-2026-118763 は PR #1762 で修正

影響範囲と結論

①が関係するのは GitHub Actions で PyPI に公開しているプロジェクト、②が関係するのは @sigstore/oci で OCI レジストリへ署名/attestationをpushしているプロジェクトだ。多くのリポジトリは①に該当する一方、②はより限られた経路で使われる。とくに①は、pypi-publish が PyPI 公開の事実上の標準アクションで、数行の uses: で取り込まれているぶん対象が非常に広い。普段ワークフローを触らないリポジトリほど、古いバージョンにピンしたまま気づいていないことが多い。この機会に一度、公開系ワークフローを横断で点検しておきたい。どちらも修正版が出ているので、公開ワークフローの棚卸しの機会に、使っている部品のピンを修正版へ寄せておくのが確実だ。

この記事の結論

  • ・PyPI の公開経路に別々の2件。①pypi-publish が失効 emSign CAを同梱(1.14.3 で除去・CVSS v4 9.3・CWE-295)、②@sigstore/oci が認証情報を別ホストへ(CVE-2026-118763・0.7.2・CWE-522・7.4)。
  • ・①は信頼ストアの衛生(即RCEではない)、②は悪意あるレジストリが前提(UI:R)。どちらも「信頼・資格情報の土台」の話。
  • ・対策は更新:pypi-publish → 1.14.3、@sigstore/oci → 0.7.2。固定(pin)先が実際にその版以上かまで確認。
  • ・②は CVE-2026-59891 の続き、①は eMudhra/emSign の一連と地続き。心配なら②はトークンのローテーションも。

参照ソース