
🐍 🔍 GuardDogは、悪意のあるPyPIおよびnpmパッケージを特定するCLIツールです。
# GuardDog
[](https://github.com/DataDog/guarddog/actions/workflows/checks.yml)
[](https://securityscorecards.dev/viewer/?uri=github.com/DataDog/guarddog)
[](https://www.bestpractices.dev/projects/12273)
<p align="center">
<img src="https://raw.githubusercontent.com/DataDog/guarddog/v3/docs/images/logo.png?raw=true" alt="GuardDog" width="300" />
</p>
GuardDog は、悪意のある PyPI および npm パッケージ、Go モジュール、Rust クレート、RubyGems、GitHub Actions、または VSCode 拡張機能を識別する CLI ツールです。パッケージのソースコード(YARA ルールによる)に対して静的解析を実行し、パッケージのメタデータを分析してサプライチェーン攻撃を検出します。
**GuardDog が他と異なる点:** 疑わしいパターンを列挙するだけではなく、GuardDog は調査結果を関連付けて、攻撃チェーンに基づく実際の**リスク**を特定します。パッケージが高リスクとしてフラグ付けされるには、同じファイル内にアクションを実行する**能力**(例: ネットワークアクセス)と**脅威インディケーター**(例: 不審なドメイン)の両方が必要です。
以下からコードをダウンロードしてスキャンします:
* NPM: [npmjs.org](https://www.npmjs.com/) でホストされているパッケージ
* PyPI: [PyPI.org](https://pypi.org/) でホストされているソースファイル (tar.gz) パッケージ
* Go: [GitHub.com](https://github.com) でホストされているリポジトリの GoLang ソースファイル
* Rust: [crates.io](https://crates.io/) でホストされているクレート
* RubyGems: [rubygems.org](https://rubygems.org/) でホストされている Gem パッケージ
* GitHub Actions: [GitHub.com](https://github.com) でホストされているリポジトリの Javascript ソースファイル
* VSCode 拡張機能: [marketplace.visualstudio.com](https://marketplace.visualstudio.com/) でホストされている拡張機能 (.vsix) パッケージ

## GuardDog の仕組み
GuardDog は、コードの能力と脅威インディケーターを関連付ける**リスクベースの検出モデル**を使用します:
1. **検出**: ルールは**能力**(コードが *実行できる* こと)または**脅威**(不審なインディケーター)を識別します
2. **関連付け**: 同じファイルで見つかった能力と脅威が**リスク**を形成します(ファイルをまたぐ一致もリスクを形成しますが、重大度は引き下げられます)
3. **スコアリング**: リスクは、攻撃チェーンの完全性と巧妙さに基づいて (0-10) でスコアリングされます
4. **レポート**: パッケージには、詳細なリスクの内訳とともに重大度評価(低/中/高)が付与されます
### このアプローチの理由
従来の SAST ツールはすべての疑わしいパターンを個別にフラグ付けするため、アラート疲れを引き起こします。GuardDog は次のことを理解しています:
- **能力だけ**では悪意はありません(ネットワークライブラリは HTTP リクエストを行うべきです)
- **脅威インディケーターだけ**では誤検知の可能性があります(テストフィクスチャ、ドキュメント)
- **能力 + 脅威の組み合わせ**が実際のリスクを示します(悪意のあることを *実行でき、かつ実行する* コード)
### リスクスコアリング
パッケージは、4 つの要素に基づいて **0-10** のスコアを受け取ります:
| 要素 | 重み | 説明 |
|--------|--------|-------------|
| **重大度** | 30% | 最も高い重大度の検出結果(低/中/高) |
| **攻撃チェーン** | 20% | 完全な攻撃ステージの存在(初期 → 中期/後期) |
| **特異性** | 30% | パターンがマルウェア特有であるか、正当なコードにも当てはまるかの度合い |
| **巧妙さ** | 20% | 技術の高度さ |
**スコアラベル:**
- **0**: リスクが検出されていない
- **0.1-3**: 低リスク(単一ステージの脅威、特異性が低い)
- **3.1-7.5**: 中リスク(部分的な攻撃チェーン、メタデータのインディケーター、または単一ステージのコード検出結果)
- **7.6-10**: 高リスク(ソースコードの証拠を伴う多段階の攻撃チェーン — 侵害の可能性がほぼ確実)
**攻撃チェーンのステージ**(MITRE ATT&CK に基づく):
- **初期**: 初期アクセス、実行能力
- **中期**: 永続化、防御回避、資格情報へのアクセス
- **後期**: コマンド&コントロール、外部への持ち出し、影響
---
### GuardDog 向けの新しい Datadog Agent [インテグレーション](https://docs.datadoghq.com/integrations/guarddog/) と Cloud SIEM [コンテンツパック](https://app.datadoghq.com/security/siem/content-packs?query=guarddog) をチェックしてください。
---
## はじめに
### インストール
GuardDog を実行する最も簡単な方法は [`uvx`](https://docs.astral.sh/uv/guides/tools/) を使用することです:
```sh
uvx guarddog pypi scan requests
```
ローカルにインストールするには:
```sh
uv tool install guarddog
# or
pip install guarddog
```
または Docker イメージを使用します:
```sh
docker pull ghcr.io/datadog/guarddog
alias guarddog='docker run --rm ghcr.io/datadog/guarddog'
```
*注: Windows でサポートされているインストール方法は Docker のみです。*
### 使用例
```sh
# Scan the most recent version of the 'requests' package
guarddog pypi scan requests
# Scan a specific version of the 'requests' package
guarddog pypi scan requests --version 2.28.1
# Scan the 'request' package using 2 specific heuristics
guarddog pypi scan requests --rules exec-base64 --rules code-execution
# Scan the 'requests' package using all rules but one
guarddog pypi scan requests --exclude-rules exec-base64
# Scan a local package archive
guarddog pypi scan /tmp/triage.tar.gz
# Scan a local package directory
guarddog pypi scan /tmp/triage/
# Scan a package stored in S3 (a folder/prefix or a single archive object)
guarddog pypi scan s3://my-bucket/path/to/package/
guarddog pypi scan s3://my-bucket/path/to/package.tar.gz
# Scan every package referenced in a requirements.txt file of a local folder
guarddog pypi verify workspace/guarddog/requirements.txt
# Scan every package referenced in a requirements.txt file and output a sarif file - works only for verify
guarddog pypi verify --output-format=sarif workspace/guarddog/requirements.txt
# Output JSON to standard output - works for every command
guarddog pypi scan requests --output-format=json
# All the commands also work on npm, go, crates, rubygems
guarddog npm scan express
guarddog go scan github.com/DataDog/dd-trace-go
guarddog go verify /tmp/repo/go.mod
# Scan Rust crates
guarddog crates scan serde
guarddog crates verify /tmp/repo/Cargo.lock
# Scan RubyGems packages
guarddog rubygems scan rails
guarddog rubygems verify /tmp/repo/Gemfile.lock
# Additionally can support scanning GitHub actions that are implemented in JavaScript
guarddog github_action scan DataDog/synthetics-ci-github-action
guarddog github_action verify /tmp/repo/.github/workflows/main.yml
# Scan VSCode extensions from the marketplace
guarddog extension scan ms-python.python
# Scan a specific version of a VSCode extension
guarddog extension scan ms-python.python --version 2023.20.0
# Scan a local VSCode extension directory or VSIX archive
guarddog extension scan /tmp/my-extension/
# Run in debug mode
guarddog --log-level debug npm scan express
```
## サンドボックススキャン
パッケージをスキャンする際、GuardDog は**カーネルレベルのサンドボックス**(Linux では Landlock、macOS では Seatbelt を [nono](https://github.com/always-further/nono-py) を使用して利用)内でソースコード解析を実行します。サンドボックスはすべてのネットワークアクセスをブロックし、ファイルシステム操作を解析に必要なパスのみに制限します。これにより、アーカイブの抽出やスキャン中にコードを実行しようとする悪意のあるパッケージから保護されます。
デフォルトではサンドボックスが必須です。プラットフォームで利用できない場合、保護なしで実行する代わりにスキャンは失敗します。サンドボックスなしでスキャンするには、明示的に `--no-sandbox` を渡す必要があります:
```sh
# Default: require the sandbox, exit with an error if it's unavailable
guarddog pypi scan requests
# Explicitly disable the sandbox
guarddog pypi scan requests --no-sandbox
```
リモートパッケージの場合、3 つのフェーズが異なる権限レベルで実行されます:
1. **ダウンロード**と**メタデータ分析**はサンドボックスなしで実行されます(ネットワークアクセスが必要)
2. **アーカイブの抽出**はサンドボックス化されたサブプロセスで実行されます(ネットワークはブロックされ、ファイルシステムは制限されます)
3. **ソースコード解析** (YARA) はサンドボックスが適用された後、メインプロセスで実行されます(ネットワークはブロックされ、ファイルシステムは抽出されたファイルに制限されます)
サンドボックスは、アーカイブ抽出中のパストラバーサルおよびコード実行の脆弱性を軽減するために導入されました (CVE-2022-23530、CVE-2022-23531、CVE-2026-22870、CVE-2026-22871)。
## S3 からのパッケージスキャン
GuardDog は、S3 に保存されているパッケージを、フォルダー/プレフィックスまたは単一のアーカイブオブジェクトとしてスキャンできます:
```sh
guarddog npm scan s3://my-bucket/path/to/package/
guarddog npm scan s3://my-bucket/path/to/package.tar.gz
```
これは既存の AWS 認証情報(環境変数、`~/.aws`、SSO、または IAM ロール)を使用します。GuardDog は何かを行う前に STS 経由で認証を検証し、有効な認証情報が見つからない場合はエラーで終了します。オブジェクトは一時ディレクトリに同期され、他の信頼できないコンテンツと同様にサンドボックス下でスキャンされた後、ディスクから削除されます。
## ルール
GuardDog は、リスクベースのスコアリングエンジンに参加する 2 種類の検出ルールを使用します:
* **ソースコードルール** (YARA): パッケージのソースコードの静的解析により、能力と脅威を検出します
* **メタデータルール** (Python ディテクター): パッケージレジストリのメタデータの分析により、サプライチェーン攻撃のインディケーターを検出します
エコシステムごとのルールの完全なリストについては、**[RULES.md](https://github.com/datadog/guarddog/blob/v3/RULES.md)** を参照してください。
新しいルールの作成については、**[WRITING_RULES.md](https://github.com/datadog/guarddog/blob/v3/WRITING_RULES.md)** を参照してください。
## GitHub Action での GuardDog の実行
CI パイプラインに GuardDog を統合する最も簡単な方法は、SARIF 出力形式を活用し、GitHub の [code scanning](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning) 機能にアップロードすることです。
これにより、次のものが得られます:
* GuardDog スキャン出力に基づくプルリクエストへの自動コメント
* GitHub UI での組み込みの誤検知管理
GuardDog を使用した GitHub Action のサンプル:
```yaml
name: GuardDog
on:
push:
branches:
- main
pull_request:
branches:
- main
permissions:
contents: read
jobs:
guarddog:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
name: Scan dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v7
- run: uvx guarddog pypi verify requirements.txt --output-format sarif --exclude-rules repository_integrity_mismatch > guarddog.sarif
- name: Upload SARIF file to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
category: guarddog-builtin
sarif_file: guarddog.sarif
```
## 開発
### GuardDog のローカルバージョンの実行
* poetry が `python >=3.10` の env を持っていることを確認します `poetry env use 3.10.0`
* 依存関係をインストールします `poetry install`
* guarddog を実行します `poetry run guarddog` または `poetry shell` を実行してから `guarddog` を実行します
### ユニットテスト
すべてのユニットテストを実行: `make test`
パッケージメタデータのヒューリスティックに対するユニットテストを実行: `make test-metadata-rules` (テストは[こちら](https://github.com/DataDog/guarddog/tree/v3/tests/analyzer/metadata))。
### ベンチマーク
正当なパッケージと悪意のあるパッケージに対して GuardDog を実行し、誤検知と見逃しを特定できます。[./tests/samples](https://github.com/datadog/guarddog/blob/v3/tests/samples) を参照してください。
### コード品質チェック
型チェッカーを実行します:
```shell
mypy --install-types --non-interactive guarddog
```
およびリンターを実行します:
```shell
flake8 guarddog --count --select=E9,F63,F7,F82 --show-source --statistics --exclude tests/analyzer/sourcecode,tests/analyzer/metadata/resources,evaluator/data
flake8 guarddog --count --max-line-length=120 --statistics --exclude tests/analyzer/sourcecode,tests/analyzer/metadata/resources,evaluator/data --ignore=E203,W503
```
### 環境変数による設定
GuardDog の動作は環境変数を使用してカスタマイズできます:
#### 一般的な設定
| 環境変数 | 説明 | デフォルト値 |
|---------------------|-------------|---------------|
| `GUARDDOG_PARALLELISM` | 並列処理に使用するスレッド数 | 利用可能な CPU 数 |
| `GUARDDOG_VERIFY_EXHAUSTIVE_DEPENDENCIES` | 依存関係のすべての可能なバージョンを分析する (`true`/`false`) | `false` |
| `GUARDDOG_NPM_INCLUDE_DEV_DEPENDENCIES` | npm `package.json` ファイルをスキャンするときに `devDependencies` を含める (`true`/`false`)。`guarddog npm verify --include-dev-dependencies` で呼び出しごとに切り替えることもできます | `false` |
| `GUARDDOG_TOP_PACKAGES_CACHE_LOCATION` | トップパッケージのキャッシュディレクトリの場所 | `guarddog/analyzer/metadata/resources` |
| `GUARDDOG_YARA_EXT_EXCLUDE` | YARA スキャンから除外するファイル拡張子のカンマ区切りリスト | `ini,md,rst,txt,lock,json,yaml,yml,toml,xml,html,csv,sql,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,changelog,readme,makefile,dockerfile,pkg-info,d.ts` |
#### メタデータルールの設定
| 環境変数 | 説明 | デフォルト値 |
|---------------------|-------------|---------------|
| `GUARDDOG_NEW_DEPENDENCY_RISK_THRESHOLD` | 新たに導入された依存関係が `risky_new_dependency` ルールで親パッケージをフラグ付けするための最小リスクスコア | `5.0` |
#### アーカイブ抽出のセキュリティ制限
GuardDog は、パッケージアーカイブを抽出する際に、圧縮爆弾(zip bomb)やファイルディスクリプタ枯渇攻撃から保護するために複数のセキュリティチェックを実装しています:
| 環境変数 | 説明 | デフォルト値 |
|---------------------|-------------|---------------|
| `GUARDDOG_MAX_UNCOMPRESSED_SIZE` | 許容される最大非圧縮サイズ(バイト単位)(ディスク容量の枯渇を防ぎます) | 2147483648 (2 GB) |
| `GUARDDOG_MAX_COMPRESSION_RATIO` | 許容される最大圧縮率(不審な圧縮パターンを検出します) | 100 (100:1) |
| `GUARDDOG_MAX_FILE_COUNT` | アーカイブで許可される最大ファイル数(ファイルディスクリプタ/inode の枯渇を防ぎます) | 100000 |
## メンテナー
* [Sebastian Obregoso](https://www.linkedin.com/in/sebastianobregoso/)
* [Ian Kretz](https://github.com/ikretz)
* [Tesnim Hamdouni](https://github.com/tesnim5hamdouni)
## 著者
* [Ellen Wang](https://www.linkedin.com/in/ellen-wang-4bb5961a0/)
* [Christophe Tafani-Dereeper](https://github.com/christophetd)
## 謝辞
インスピレーション:
* [Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks](https://arxiv.org/pdf/2005.09535)
* [What are Weak Links in the npm Supply Chain?](https://arxiv.org/pdf/2112.10165.pdf)
* [A Survey on Common Threats in npm and PyPi Registries](https://arxiv.org/pdf/2108.09576.pdf)
* [A Benchmark Comparison of Python Malware Detection Approaches](https://arxiv.org/pdf/2209.13288.pdf)
* [Towards Measuring Supply Chain Attacks on Package Managers for Interpreted Languages](https://arxiv.org/pdf/2002.01139)