
ランタイム脆弱性スキャナー:ホスト上で実際に実行されているサービス内のCVEを検出し、ネットワーク露出度に基づいてランク付けします。
# OffSeq Threat Finder
[](https://github.com/offseq/threat-finder/actions/workflows/ci.yml)
[](https://crates.io/crates/threat-finder)
[](https://docs.rs/threat-finder)
[](#license)
**threat-finder** は、マニフェストが主張する内容ではなく、ホスト上で _実際に実行されている_ 脆弱なソフトウェアを見つけ出し、どの検出結果が**ネットワーク到達可能**かを教えてくれます。実行中の各サービス(および `--scope all` の場合はインストール済みのすべての OS パッケージ)を正確な [Package-URL](https://github.com/package-url/purl-spec) に解決し、エコシステムネイティブなバージョン規則を用いて [OffSeq Radar](https://radar.offseq.com) カタログと照合するため、バックポート/修正済みビルドが誤検出されることはありません。

```text
Vulnerability summary (highest risk first):
openssh-server@1:8.9p1-3ubuntu0.6 — 1 finding(s) [PUBLIC tcp 0.0.0.0:22]
[ACT-NOW 92] HIGH CVE-2024-6387 [KEV] regreSSHion: remote code execution in OpenSSH
→ fix: 1:8.9p1-3ubuntu0.10 https://radar.offseq.com/threat/…
[email protected] — 1 finding(s)
[SCHEDULE 41] MED CVE-2023-44487 HTTP/2 Rapid Reset
2 confirmed finding(s) across 2 asset(s); 1 exposed, 1 known-exploited.
```
## インストール
```sh
brew install offseq/tap/threat-finder # Homebrew (macOS/Linux), prebuilt
cargo binstall threat-finder # prebuilt binary, no toolchain
cargo install threat-finder # from source
```
Linux/macOS (x86_64 + arm64) および Windows (x86_64) 向けのプレビルドアーカイブは [リリースページ](https://github.com/offseq/threat-finder/releases/latest) にあります。ソースからビルドするには Rust ≥ 1.87 が必要です。Linux、macOS、BSD、Windows がすべてサポートされています。
## クイックスタート
```sh
export OFFSEQ_API_KEY=... # from https://radar.offseq.com/console
threat-finder
```
実行中のサービスをスキャンし、リスク順に並べたサマリーを表示し、完全な JSON レポートを `/tmp/threats.json` に書き出します。`--scope all` を追加すると、インストール済みのすべての OS パッケージもスキャンします。
## 使い方
```sh
threat-finder [OPTIONS]
```
| Flag | Description |
|------|-------------|
| `-o, --output <PATH>` | JSON レポートを `PATH` に書き出します(デフォルト: プロンプト、または `/tmp/threats.json`) |
| `--json` | JSON レポートをファイルではなく stdout に出力します |
| `--scope <SCOPE>` | `running`(デフォルト)または `all`(+ インストール済みのすべての OS パッケージ) |
| `--severity <LEVEL>` | `critical\|high\|medium\|low` 以上の検出結果のみを報告します |
| `--strict` | 座標が確認できていない検出結果を除外します(確認済みのみ報告) |
| `--fail-on <WHAT>` | 一致する検出結果が存在する場合に終了コード `5` を返します: `any\|critical\|high\|medium\|low\|kev\|exposed` |
| `--sarif <PATH>` | SARIF 2.1.0 レポートも書き出します(コードスキャン UI 用) |
| `--include <GLOB>` / `--exclude <GLOB>` | 名前のグロブでアセットをフィルタリングします(繰り返し指定可) |
| `-q, --quiet` | バナー、進捗、サマリーを抑制します |
| `--no-color` | ANSI カラーを無効にします |
| `-y, --yes` | デフォルトを仮定し、プロンプトを表示しません(CI/cron) |
| `--reset` | 保存済みの API キーを無視して再入力します |
| `--register` | スキャンしたホストを継続的モニタリング用に Radar に登録します(プロンプトなし) |
| `--no-register` | この実行ではモニタリングの登録・プロンプトを行いません |
| `--host-name <NAME>` | 登録時に送信するフレンドリなホスト名 |
| `--unregister` | Radar からこのホストのインベントリを削除して終了します |
| `--windows-missing-updates` | (Windows) Windows Update Agent から保留中のセキュリティ更新も一覧表示します(オンラインスキャン。管理者権限で実行) |
| `-h, --help` / `-V, --version` | ヘルプ / バージョン |
```sh
# CI: only high+ findings, JSON to stdout, no prompts
OFFSEQ_API_KEY=… threat-finder --yes --json --severity high > report.json
# Fail the build only when a network-exposed service has a known-exploited CVE
OFFSEQ_API_KEY=… threat-finder --yes --quiet --fail-on exposed
```
**終了コード:** `0` 正常 · `1` ルックアップ/IO エラー · `2` API キーなし · `3` 未サポートの OS · `4` レート制限/クォータ、または API アクセスが必要(アップグレードが必要) · `5` `--fail-on` のしきい値に到達。
**API キー**([Radar Console](https://radar.offseq.com/console) から取得)は次の順序で解決されます:
1. `OFFSEQ_API_KEY` 環境変数(CI/cron に最適)。
2. `--reset` が指定されていない場合、`$XDG_CONFIG_HOME/offseq-rust/config.toml`(`0600`)に保存されたキー。
3. TTY 上での対話式の非表示プロンプト — その後、次回のために保存されます。
キーがない状態で非対話実行(`--yes` / TTY なし)すると終了コード `2` で終了します。
`OFFSEQ_CONFIG_DIR` を設定すると、設定の保存場所を上書きできます(デフォルト: OS のユーザーごとの設定ディレクトリ)。決定論的なパスが必要なコンテナ/CI に便利です。
## 仕組み
**正確な座標マッチング。** 各アセットは、_完全な_ バージョン(エポック + ディストリビューションリビジョン)と `?distro=` 修飾子を持つ purl になります。例: `pkg:deb/ubuntu/openssh-server@1:8.9p1-3ubuntu0.6?distro=jammy`。インベントリはバッチ処理された `POST /match/batch` 呼び出し(ティアサイズのチャンクごとに 1 リクエスト)で照合され、**エコシステムネイティブなバージョン規則**(dpkg/rpm/apk/semver)を使用して**サーバーサイドで**処理されるため、`1.18.0-6+deb11u3` のようなバックポート済み・修正済みビルドは正しく検出されず、クライアントサイドでのバージョン推測もありません。検出結果は API の `confirmed` フラグで分類されます: 確認済みの一致は報告され、バージョンを確認できない座標一致は**未確認 / トリアージ**として別途表示されます(件数、`byCve`、`--fail-on` から除外。`--strict` で除外できます)。
**ネットワーク露呈の相関付け。** マニフェストスキャナ(Trivy、Grype、osv-scanner)はパッケージリストを読み取りますが、外部スキャナ(Nessus、OpenVAS)は別のホストが必要です。このツールは、実行中の各サービスのプロセスを、それが**リッスン**しているソケット(Linux では `/proc/net`、その他の Unix では `lsof`、Windows では `Get-NetTCPConnection` / `netstat`)にマッピングし、到達可能性を `loopback` / `private` / `public` に分類します。`0.0.0.0` 上の脆弱なサービスは `127.0.0.1` 上のものとはまったく異なるリスクです。検出結果は露出しているものを優先してランク付けされ、`--fail-on exposed` はまさにその条件で CI をゲートします。パケットは送信されません。検出結果には CISA **KEV** と **EPSS** も含まれます。
**露呈を考慮した優先順位付け。** すべての検出結果には `riskScore`(0〜100)と SSVC スタイルの `decision` バンド — **`act-now` · `soon` · `schedule` · `track`** — が付与され、深刻度、EPSS、KEV、および所有アセットの**ネットワーク露呈**から統合されます。サマリーは各行を `[ACT-NOW 92]` スタイルのバッジで始め、それでソートするため、公開されており既知の悪用がある少数の問題が、ノイズの多いホストの先頭に浮かび上がります。スコアはローカルとサーバーサイドで同じ計算式を使用し(Radar のモニタリングビューでは、KEV の検出結果が期日を過ぎている場合に小さなボーナスが追加されます。この期日は CLI にはありません)、`--json` と SARIF(`properties`)に表示されます。
## 継続的モニタリング
1 回限りのスキャンはある時点のスナップショットです。ホストを一度登録すれば Radar が監視を続けます: **新たに公開された CVE** がその座標のいずれかに影響する場合、露呈に基づいて優先順位付けされたアラート(メール + Console)を受け取ります。再スキャンは不要です。
対話式スキャンの後、ツールは次のように尋ねます:
```text
Add these 42 services to Radar for continuous monitoring & alerts? [Y/n/never]
```
`Y` はこのホストを登録し、`n` はこの実行をスキップし、`never` は選択を記憶します(設定に保存され、再度尋ねられることはありません)。再スキャン時には**ドリフト**(`+added / -removed / ~changed`)と、前回のスキャン以降に**新しく見つかった**検出結果も報告します。ホストの管理 — モニタリングの切り替え、検出結果の表示、登録解除 — は [Radar Console](https://radar.offseq.com/console) の **Inventory** から行えます。
自動化の場合はプロンプトをスキップできます: `--register` は非対話で登録し(CI ではデフォルトでオフ)、`--no-register` はオプトアウトし、`--host-name <NAME>` はホストにラベルを付け、`--unregister` は削除します。安定したホストごとの ID とプロンプトの設定は `$XDG_CONFIG_HOME/offseq-rust/config.toml` に保存されます。登録によって終了コードが変わることはありません — モニタリングの一時的な問題でスキャンが失敗することはありません。Basic/Pro/Enterprise プラン(または Pro Console)が必要です。
## スコープとカバレッジ
`--scope running`(デフォルト)は実行中のサービスをスキャンします。これは、露呈を相関付けられる小さくてシグナルの高いセットです。`--scope all` はさらに**インストール済みのすべての OS パッケージ**(`dpkg`/`rpm`/`pacman`/`apk`/`brew`/`pkg`/`pkg_info`)を列挙し、照合対象の表面を 10〜50 倍に拡大します。実行中で露呈しているプロセスの基盤にもなっているパッケージは、その露呈を維持します(アセットは座標ごとに重複排除されマージされます)。カーネルは `--scope all` の下でそのパッケージ(`linux-image…`)としてカバーされます。
> `--scope all` では数百〜数千のパッケージが生成される可能性があります。無料ティア(1 時間あたり 15 ルックアップ)ではレート制限が発生します。ツールはインベントリが予算を超えると警告します。(ルックアップはすでにバッチ処理されています。ローカル結果キャッシュはロードマップに含まれています。)
## OS 別サポート
| OS | 検出方法 | 座標ソース |
|----|-----------|-------------------|
| Linux (systemd) | `ListUnits` → `/proc/<pid>/exe` | dpkg / rpm / pacman / apk |
| Linux (SysV/OpenRC) | `service --status-all` / `rc-status` | パッケージ DB |
| macOS | `launchctl list` → `ps`(サードパーティのみ) | Homebrew |
| FreeBSD / DragonFly | `service -e` | `pkg` |
| OpenBSD | `rcctl ls started` | `pkg_info` |
| NetBSD | `/etc/rc.d` の状態 | `pkg_info` |
| Solaris / illumos | `svcs` → `svcprop` | プローブ(`--version`) |
| Windows | `Win32_Service` → `Get-NetTCPConnection` / `netstat` | レジストリ / winget / Appx / Chocolatey / Scoop → CPE; npm / pip / dotnet → purl; OS ビルド → CPE |
パッケージがバイナリを所有していない場合、バージョンは強化された `--version` プローブ(絶対パスのみ、サニタイズされた環境)にフォールバックします。macOS では、Apple のシステムサービス(`com.apple.*`、SIP で保護されたパス)はスキップされます。これらは OS バージョンでカバーされており、数百ものプローブを行うのは無意味だからです。
**Windows** では、すべてが組み込みの `powershell.exe` を介して収集されます(追加のランタイムは不要、コアインベントリに管理者権限も不要)。インストール済みアプリはキュレートされた名前テーブルを通じて NVD CPE にマッピングされます(マッピングされていないアプリは誤った推測ではなく名前検索にフォールバックします)。OS エディション/ビルドは機能修飾付きの OS CPE(例: `windows_11_23h2`)になります。`--windows-missing-updates` は、保留中のセキュリティパッチに関する Windows Update Agent のアドバイザリをオプトインで追加します。
## 出力
JSON は決定論的(ソート済み)なキーとタイムスタンプなしで出力されるため、レポートの差分がきれいに取れます:
- **`services`** — `pkg@version` → 確認済みの検出結果(`cveId`、`severity`、`cvssScore`、`epss`、`kev`、`riskScore`、`decision`、`confirmed`、`matchedRange`、`matchBasis`、`fixedVersions`、`remediation`、`cwes`、`references`、`radarUrl`)、リスクが最も高いものから順に。
- **`unconfirmed`** — バージョンを確認できなかった座標一致(トリアージ)。
- **`assets`** — `pkg@version` → `{ exe, versionSource, exposed, reachability, listeners }`(`versionSource` = `package-db` | `probe`。`reachability` は TCP **および** UDP をカバー)。
- **`byCve`** — 影響を受けるすべてのアセットにわたって各 CVE を集約(「1 回のパッチで多数を修正」)。
- **`errors`** — アセットごとのルックアップ失敗。失敗が「クリーン」と誤読されることはありません。
- **`registration`** — 実行がホストを登録した場合に存在: `host_id`、`monitoring`、`drift`、`summary`、`newSinceLastCount`。
- **`meta`** — `{ tool, version, schemaVersion }`(`schemaVersion` 2)。
コードスキャン UI 向けの SARIF 2.1.0 レポート(`--sarif`)も利用できます。
## OffSeq エコシステム
| | |
|---|---|
| [**OffSeq**](https://offseq.com) | EU セキュリティ監査、脅威モニタリング、CISO-as-a-Service、NIS2 コンプライアンス |
| [**Radar**](https://radar.offseq.com) | リアルタイム脅威インテリジェンス — threat-finder が照合するカタログ |
| [**Radar Console**](https://radar.offseq.com/console) | サブスクリプション、カスタムフィード、およびあなたの `OFFSEQ_API_KEY` |
| [**Radar API**](https://radar.offseq.com/api-docs) | ここで使用される `/match` エンドポイントの REST ドキュメント |
| [**Radar Threats**](https://radar.offseq.com/threats) | 検索可能な CVE / マルウェア / 脅威アクターのデータベース |
| [**Radar Feeds**](https://radar.offseq.com/feeds) | CISA、CIRCL、ThreatFox などを集約するカスタムフィード |
| [**Radar Pricing**](https://radar.offseq.com/pricing) | 無料ティアから Enterprise まで |
| [**Breach**](https://breach.offseq.com) | ダークウェブのデータ漏洩 & 露出した認証情報のモニタリング |
| [**Veil**](https://veil.offseq.com) | クライアントサイド PNG ステガノグラフィー(AES-256-GCM) |
| [**Guard**](https://offseq.com/guard/) | AI による Web サイトのセキュリティ & コンプライアンス分析 |
| [**Training**](https://training.offseq.com) | PECB 認定のセキュリティ & プライバシーコース |
## 開発
```sh
cargo build --release
cargo test # unit tests
cargo test -- --ignored # + macOS live-discovery smoke test
cargo clippy --all-targets
```
エンジンはライブラリクレート(`find_threats`)であり、`Collector` 抽象化を備えています(現在は実行中サービスと OS パッケージ。次はロックファイル / コンテナ / SBOM)。そのため、バイナリはその上に構築された薄い CLI です。
## ライセンス
[MIT](https://github.com/offseq/threat-finder/blob/main/LICENSE) または [Apache-2.0](https://github.com/offseq/threat-finder/blob/main/LICENSE) のデュアルライセンスです。お好きな方を選択できます。