Skip to main content

elementary-dataのPyPIパッケージに悪意あるリリース、データエンジニアのクラウド認証情報を窃取

著者
blog feature toolkit

2026年4月27日

0 分で読めます

月間100万回以上ダウンロードされているPyPI上のPythonパッケージelementary-dataが、GitHub Actionsを攻撃経路とするサプライチェーン攻撃を受けました。

要点

アドバイザリ

深刻度

重大(CVSS v4.0: 9.3)

影響を受けるパッケージ

elementary-data==0.23.3

安全なバージョン

0.23.3を除くすべてのバージョン。0.23.4にアップグレードしてください

攻撃の種類

サプライチェーン(GitHub Actions CI/CDへのインジェクション、その後、認証情報を窃取するパッケージを公開)

窃取された認証情報

dbtプロファイル、Snowflake/BigQuery/Redshiftの認証情報、AWS/GCP/Azureのキー、APIトークン、SSHキー、.envファイル

影響範囲

PyPI CLIパッケージとDockerイメージが侵害されました。Elementary CloudとElementary dbtパッケージは影響を受けていません

検出マーカー

$TMPDIR/.trinny-security-update(Linux/macOS)、%TEMP%\.trinny-security-update(Windows)

公表日

2026年4月25~26日

elementary-dataとは?

elementary-dataは、データエンジニアやアナリティクスエンジニアが、Snowflake、BigQuery、Redshift、Databricksなどのデータウェアハウス全体でパイプラインの健全性を監視し、異常を検出し、テストの失敗を追跡するために使う、dbtネイティブのデータオブザーバビリティCLIツールです。このパッケージは週に約28万回、月に110万回以上ダウンロードされており、広く採用されているデータツールの一つです。

このパッケージは主要なクラウドデータプラットフォームの大半と連携できます。その点こそが、攻撃者にとって魅力的な標的となった理由です。CI/CD実行時にSnowflake、BigQuery、AWSへの接続を日常的に扱うツールは、多くの価値ある認証情報のすぐそばに存在します。

攻撃の経緯

侵害は2段階で発生しました。まず公開パイプラインが侵害され、その後、さらなる認証情報を窃取する悪意あるコンテンツが公開されました。elementary-dataパッケージの今回のセキュリティインシデントは、TeamPCPやその他の脅威アクターが最近悪用した、特に注目度の高い攻撃経路の一つです。

ステージ1:GitHub Actionsのスクリプトインジェクション

2026年4月24日22:10 UTC、作成から2日しか経っていないGitHubアカウント(realtungtungtungsahur)を使う攻撃者が、elementary-dataリポジトリのPR #2147に細工したコメントを投稿しました。このコメントは、IssueやPRのコメントイベントを処理するワークフロー.github/workflows/update_pylon_issue.ymlのスクリプトインジェクションの欠陥を悪用しました。

脆弱なrun:ブロックは、bashによる解析前に${{ github.event.comment.body }}をシェルスクリプトへ直接埋め込んでいました。この式は文字列引数としてサニタイズされるのではなく、ワークフローテンプレートの処理時に展開されるため、コメント本文にシェルのメタ文字やサブコマンドを注入すると、ランナー上で任意のコードを実行できます。ワークフローが起動すると、攻撃者のペイロードはリポジトリのGITHUB_TOKENにアクセスできる状態で実行されました。

重要なのは、攻撃者がリポジトリへの直接の書き込み権限を必要としなかったことです。ランナーが利用できるGITHUB_TOKENには、コミットの作成、タグのプッシュ、他のワークフローの起動に十分な権限がありました。インジェクションされたhandle_commentジョブは2時間46分にわたって有効で、攻撃者は後続の各段階を準備するための長い時間を得ました。

攻撃者は盗んだトークンを使い、ハッシュb1e4b1f3aad0d489ab0e9208031c67402bbb8480のリリースコミットを偽造しました。このコミットは自動生成された公式のものに見えるよう構成されていました。どのブランチからも到達できない孤立コミットで、作成者はgithub-actions[bot]、偽造された「Verified」PGP署名付き、コミットメッセージは9日前にマージされた正規のPRからそのままコピーしたrelease/v0.23.2 (#2188)でした。攻撃者はこの孤立コミットにv0.23.3タグを付け、リポジトリ独自のRelease packageワークフローをtag=v0.23.3を入力として起動しました。このワークフローのチェックアウト手順はref: ${{ inputs.tag || github.ref }}を使用していたため、masterには触れず、悪意ある孤立コミットから直接ビルドされました。正規のCI/CDパイプラインによって、悪意あるコードがパッケージ化され公開されました。22:20 UTCまでにelementary-data==0.23.3がPyPIで公開されました。侵害されたDockerイメージ(ghcr.io/elementary-data/elementary:0.23.3および:latest、ダイジェストsha256:31ecc5939de6d24cf60c50d4ca26cf7a8c322db82a8ce4bd122ebd89cf634255)も、その4分後に公開されました。

この攻撃経路は、PyPIエコシステムで繰り返し確認されています。2024年12月のUltralyticsのサプライチェーン攻撃では、同じpull_request_targetインジェクションの手口で認証情報を盗み、4つの悪意あるバージョンが公開されました。2026年初頭のLiteLLMの侵害では、侵害されたサードパーティ製GitHub Actionを使うというやや異なる手口でしたが、結果は同じでした。盗まれたPyPIトークンを使って、認証情報窃取パッケージが公開されたのです。

ステージ2:悪意あるパッケージ

攻撃者はelementary.pthというファイルに悪意あるペイロードを埋め込み、パッケージのsite-packagesディレクトリに含めました。

.pthファイルはPythonのパス設定ファイルです。Pythonの起動モジュールであるsite.pyが、インタープリターの起動時に自動処理します。.pthファイル内でimportから始まる行は、独自のコードが実行される前に、Pythonコードとしてインタープリターの起動時に実行されます。つまり、ユーザーが明示的にelementaryをインポートする場合だけでなく、pip installの実行中など、影響を受けたシステムでPythonを起動するたびにマルウェアが有効になります。

この手法は、LiteLLM v1.82.8の侵害でも使われました。被害者が汚染されたパッケージをインポートする必要がないため、__init__.pyに悪意あるコードを埋め込む方法よりも持続性が高く、検出も困難です。インストールするだけで実行されます。

ペイロードの中身:マルウェアの動作

elementary.pthに埋め込まれたコードは、3段階の暗号化を施した認証情報窃取プログラムでした。まず外側をBase64でラップし、MD5キーストリーム(シード:swabag)を鍵とするXOR暗号化を行い、さらに2段階目のXOR復号レイヤーを重ねています。現代のマルウェアとしては高度な難読化ではありませんが、単純な文字列ベースのペイロード検出を回避し、パッケージの実際の動作を分析するまでの時間を延ばす意図的なものです。

影響を受けたマシンでPythonが起動すると、復号されたペイロードは次の動作を行います。

1. ファイルシステム全体から幅広いデータを対象に、認証情報とシークレットを収集しました。

  • dbtプロファイル(~/.dbt/profiles.yml)とデータウェアハウスの認証情報(Snowflake、BigQuery、Redshift、Databricks)。

  • クラウドプロバイダーの認証情報:AWSの~/.aws/credentialsに加え、IMDSv2メタデータエンドポイントから取得する有効なロール認証情報(AWS Secrets ManagerとSSM Parameter StoreへのSigV4署名付き直接呼び出しを含む)、GCPのapplication_default_credentials.json、Azureの~/.azure/ディレクトリ。

  • SSH秘密鍵(id_rsa, id_ed25519, ~/.git-credentials)。

  • コンテナとオーケストレーションのシークレット:~/.docker/config.json、~/.kube/config, すべての /etc/kubernetes/*.conf ファイル、Kubernetes ServiceAccountトークン。

  • パッケージマネージャーの認証情報:~/.npmrc、~/.pypirc、~/.cargo/credentials.toml。

  • その他、保存されているシークレット:.env*ファイル(最大6階層下までスキャン)、~/.vault-token、~/.netrc、~/.pgpass、~/.my.cnf、環境変数内のAPIトークン。

  • 暗号資産ウォレットファイル(Bitcoin、Litecoin、Dogecoin、Zcash、Dash、Monero、Ripple、Ethereum、Cardano、Solanaバリデーターのキーペア)。

  • システムファイル:/etc/passwd、/etc/shadow、シェルの履歴ファイル、/var/log/auth.log。

2. 収集したすべてのデータをまとめtrin.tar.gzというアーカイブにし、curl --data-binaryを使って、HTTPヘッダーX-Rise-To-The-Trinny: agreeを付け、igotnofriendsonlineorirl-imgonnakmslmao.skyhanni.cloudのC2サーバーに流出させました。

3. $TMPDIR/.trinny-security-update(Linux/macOS)または%TEMP%\.trinny-security-update(Windows)にマーカーファイルを残し、マルウェアが少なくとも一度は実行されたことを示しました。

窃取される認証情報は、dbtやデータウェアハウスにとどまりません。ペイロードはマシンからアクセスできるあらゆるシークレットを広く探し出すよう作られており、Kubernetesクラスター、インフラストラクチャのシークレット管理ツール、暗号資産のキーも対象です。dbtやデータウェアハウスを標的にしているため、このツールのユーザーにとって特に関係がありますが、開発者のマシンやCIランナーで実行した場合、さらに多くの情報が失われる可能性があります。

窃取対象の認証情報は、このツールの一般的なユーザー像とよく一致しています。elementary-data CLIを使うデータエンジニアは、ほぼ間違いなく接続先のデータウェアハウスでこのツールを使用しており、多くの場合、クラウドプロバイダーの認証情報をCI/CD環境のシークレットや環境変数として保存しています。これは無差別な攻撃ではなく、標的を絞った攻撃です。

影響と範囲

攻撃は4月24日22:20 UTC(パッケージがPyPIに公開された時点)から、コミュニティメンバーが6:18 UTCに問題を報告した後、4月25日8:51~11:51 UTCの間にパッケージが削除されるまで続きました。約8~10時間にわたり露出していたことになります。

次のいずれかに該当する場合、マルウェアが実行され、認証情報が流出したものとして対応してください。

  • この期間中にpip install elementary-dataを実行した、またはアップグレードした

  • 4月24日22:24 UTCから削除までの間に、elementary-dataレジストリから取得したDockerイメージを使用した

  • または、最新バージョンを自動的に取得するCI/CDパイプラインがあった

Elementary CloudとElementary dbtパッケージは影響を受けておらず、他のCLIバージョンに悪意あるコードは含まれていませんでした。

検出:影響を受けているか確認する

ステップ1:インストール済みのバージョンを確認する

pip show elementary-data

出力にVersion: 0.23.3と表示された場合、環境が影響を受ける状態にありました。

ステップ2:実行マーカーを確認する

マルウェアは実行時にマーカーファイルを書き込みます。

# Linux / macOS (checks $TMPDIR, which defaults to /tmp if unset)
ls -la "${TMPDIR:-/tmp}/.trinny-security-update"

# Windows (PowerShell)
Test-Path "$env:TEMP\.trinny-security-update"

このファイルが存在すれば、その環境で認証情報窃取コードが実行されたことを意味します。ファイルがないからといって安全とは限りません。すべての実行経路でマーカーが書き込まれたとは限らず、一時ディレクトリが消去されている可能性もあります。

ステップ3:Snykで確認する

Pythonの依存関係に、このパッケージやその他の既知の悪意あるパッケージ、脆弱なパッケージが含まれていないか確認するには、次の手順を実行してください。

# Scan your project dependencies
snyk test --file=requirements.txt

# Or for pip-based environments
pip freeze > requirements_check.txt && snyk test --file=requirements_check.txt

Snykの脆弱性データベースにはSNYK-PYTHON-ELEMENTARYDATA-16316110が登録されており、0.23.3が固定されたままの環境を検出します。

注:セキュアな開発のガイドラインを実践するために、Pythonセキュリティのベストプラクティス・チートシートとDockerを使用したPythonアプリケーションのコンテナ化に関するベストプラクティスをご確認ください。

修復方法

1. すぐにアップグレードする

pip install --upgrade elementary-data

バージョン0.23.4は2026年4月25日に公開され、悪意あるコードは含まれていません。

requirements.txtまたはpyproject.tomlを使用している場合は、バージョン指定を更新してください。

elementary-data>=0.23.4

2. 露出した可能性のある認証情報をすべてローテーションする

影響を受けたマシン上のPythonプロセスがアクセスできる認証情報は、すべて侵害されたものとして扱ってください。具体的には次のとおりです。

  • dbtプロファイル:~/.dbt/profiles.yml内のデータウェアハウスのパスワードとOAuthトークンをローテーションします。

  • クラウドプロバイダーのキー:AWS IAMキーをローテーションまたは無効化し(Secrets ManagerとSSM Parameter Storeでアクセスされた値も確認)、GCPサービスアカウントキーとAzureサービスプリンシパルも更新します。

  • Kubernetes:ServiceAccountトークンをローテーションし、アクセス可能だった/etc/kubernetes/*.confファイルを監査します。

  • コンテナレジストリ:~/.docker/config.jsonに保存されている認証情報をローテーションします。

  • パッケージマネージャーのトークン:~/.npmrc、~/.pypirc、~/.cargo/credentials.tomlのトークンをローテーションします。

  • シークレット管理ツール:HashiCorp Vaultのトークン(~/.vault-token)と、.netrc、.pgpass、.my.cnfに保存された認証情報をローテーションします。

  • SSHキー:マシン上に秘密鍵が存在していた場合は、漏えいしたものとみなし、ローテーションしてください。

  • CI/CDのシークレット:影響を受けたマシンがCIランナーだった場合、その環境に保存されているすべてのシークレットをローテーションしてください。

ローテーションだけでは不十分です。流出先ドメインigotnofriendsonlineorirl-imgonnakmslmao.skyhanni.cloudへのアクセスログと、各サービスのアクセスログを確認し、すでに発生した可能性のある不正アクセスを検出してください。

3. Pythonのキャッシュを削除する

# Remove any cached .pth files or bytecode
pip cache purge

# Find and remove any elementary.pth artifacts
find / -name "elementary.pth" 2>/dev/null

4. クリーンなDockerイメージを取得する

侵害されたイメージ(ghcr.io/elementary-data/elementary:0.23.3および:latest)のダイジェストはsha256:31ecc5939de6d24cf60c50d4ca26cf7a8c322db82a8ce4bd122ebd89cf634255です。最後に安全が確認されたイメージは0.23.2で、ダイジェストはsha256:b3bbfafde1a0db3a4d47e70eb0eb2ca19daef4a19410154a71abee567b35d3d9です。2026年4月25日以降にビルドされたクリーンなイメージを取得してください。

docker pull ghcr.io/elementary-data/elementary:latest

侵害されたイメージのキャッシュ済みコピーを実行していないことを確認してください。

docker images ghcr.io/elementary-data/elementary --digests

5. GitHub Actionsのワークフローを監査する

Pythonパッケージを管理している場合、このインシデントを機に、issueやPRのコメントイベントを処理するワークフローを監査してください。検索すべきなのは、引用符で囲まれていないコンテキスト式がrun:ブロックに直接展開されているパターンです。

# Vulnerable: ${{ github.event.comment.body }} expands before bash parses the command
- run: echo "Comment: ${{ github.event.comment.body }}"

# Safe: pass untrusted input through an environment variable
- run: echo "Comment: $COMMENT_BODY"
  env:
    COMMENT_BODY: ${{ github.event.comment.body }}

SnykによるGitHub Actionsの脆弱性に関する記事と、TJ Actionsの侵害分析では、より広範な注意すべきパターンを解説しています。

入力のサニタイズに加えて、より根本的な対策は、長期間有効なPyPI APIトークンをワークフローのシークレットから完全に排除することです。PyPIのTrusted Publishersは、特定のリポジトリ上の特定のワークフローにスコープを限定した短命のOIDCトークンを使用します。これらのトークンは流出して再利用されることがありません。elementary-dataへの攻撃者は公開に長期間有効なシークレットを必要としましたが、Trusted Publishersを使えばその攻撃対象領域をなくせます。また、公開手順の実行前に人の確認を必須とする手動承認ゲートを設け、特権を持つリリースワークフローを保護してください。

繰り返される攻撃パターン

この攻撃は、いまやよく知られた手口に沿っています。プロジェクトのGitHub Actions設定の不備を見つけ、PyPI公開トークンを盗むコードを注入し、そのトークンで悪意あるバージョンを公開し、.pthファイルなどの起動時フックを埋め込んで、影響範囲を最大化します。

同じパターンは、Ultralyticsへの攻撃(2024年12月、pull_request_targetブランチへのコード注入と暗号資産マイナー)、LiteLLMへの攻撃(2026年初頭、改ざんされたTrivyアクションを通じた、持続的なバックドアを伴う認証情報窃取)、そしてCline/Clinejectionインシデント(AIを利用したActionsへのプロンプトインジェクションとトークン窃取)でも確認されています。

このパターンは新しいものではありません。悪用の手法は広く知られており、繰り返し活発に使われているようです。パッケージのメンテナーが優先すべきなのは、ワークフローの強化です。the use of pull_request_targetを制限し、リリースワークフローに手動承認を必須とし、長期間有効なAPIトークンの代わりに短命のOIDCトークンでPyPIに公開し、不正なリリースの起動を防ぐブランチ保護ルールを導入してください。

elementary-dataのユーザーにとって、Elementaryチームの対応は迅速でした。コミュニティからの報告から初期の修正まで4時間未満で、チームは包括的なインシデントレポートも公開しました。この対応の速さは、インシデントそのものとあわせて注目に値します。

Snykでサプライチェーンを安全に

回答者の87%がサプライチェーンのセキュリティ問題の影響を受けています。Snykでサプライチェーンを安全に保ちましょう。