Rust開発者向け静的コード解析ツール

Rust開発者のツールボックス:最高の静的コード解析ツール

Rustのコンパイラは、ほとんどの開発者がこれまでに出会った中で最も意見の強いコードレビュー担当者と言えるでしょう。その所有権システム、借用チェッカー、ライフタイムの強制により、CやC++のコードベースを悩ませるバグのカテゴリ全体が排除されます。しかし、メモリエラーを防ぐコンパイラは、包括的な品質システムとは異なります。論理バグ、安全でない依存関係チェーン、安全でないブロックの誤用、パフォーマンスのアンチパターン、スタイルの逸脱などはすべて生き残ります。 rustc大規模かつ信頼性の高いRustを出荷するチームは、コンパイラと、それぞれ品質の異なる側面をカバーする階層化された静的解析ツール群を組み合わせて使用​​している。

間違った組み合わせを選ぶと、CI の時間が無駄になり、開発者が無視するようになるノイズが発生します。正しい組み合わせを選ぶと、コンパイラの厳格さが天井ではなく底辺のように感じられます。このガイドのツールは、アルファベット順ではなく、実際の機能に基づいて整理されているため、チームは、リンティングとイディオム、依存関係のセキュリティ、安全性が重要またはセキュリティに敏感なコードの詳細な検証という 3 つの品質レイヤーすべてを網羅するスタックを構築できます。

SMART TS XL

現代の Rust 開発では、言語の強力な安全性保証があっても、品質を維持するのは困難です。 SMART TS XL Rust独自の機能に合わせた詳細な静的解析機能を提供することで、信頼性、保守性、セキュリティに優れたソフトウェアの開発を支援するように設計されています。問題を早期に発見し、一貫性を維持し、手作業によるレビューの労力を削減することで、プロフェッショナルなエンジニアリングワークフローをサポートします。

錆の静的解析の3つの層

どのツールがどこに適しているかを理解することで、リンターで済むところに形式検証ツールを使ったり、セキュリティスキャナーが必要なところにリンターを使ったりといったよくある間違いを防ぐことができます。成熟したRustプロジェクトは、これら3つのレイヤーすべてを網羅しているべきです。

レイヤー1:リンティングとスタイルチェックにより、慣用表現の違反、よくある間違い、保守性の問題を検出します。使用ツール:Clippy、rustfmt、rust-analyzer。

レイヤー2:依存関係とサプライチェーンのセキュリティ監査では、サードパーティ製のクレートに既知の脆弱性やポリシー違反がないかを確認します。使用ツール:cargo-audit、cargo-deny、cargo-auditable。

レイヤー3:ディープ検証は、安全でないコードにおけるメモリ安全性の問題、未定義の動作を検出し、重要な関数の特性を形式的に証明します。ツール:Miri、Kani、MIRAI、Rudra、Creusot、Prusti。

以下の表は、主要なツールそれぞれを、そのレイヤー、コスト、CIへの適合性、および主な使用事例に対応付けたものです。

ツール層費用CIに適しています主なユースケース
クリピリンティング無料 / オープンソースソフトウェアはい慣用的なリンティング、スタイル、よくあるバグ
ラストフォームリンティング無料 / オープンソースソフトウェアはいコードフォーマットの強制
さび分析器リンティング/DX無料 / オープンソースソフトウェア一部IDE診断、インライン分析
貨物監査依存関係のセキュリティ無料 / オープンソースソフトウェアはいクレート内の既知のCVE
貨物拒否依存関係のセキュリティ無料 / オープンソースソフトウェアはいライセンス、複製、勧告
貨物監査可能依存関係のセキュリティ無料 / オープンソースソフトウェアはいバイナリに依存関係データを埋め込む
ミリディープ検証無料 / オープンソースソフトウェア選択的な安全でないコードにおける未定義の動作
可児ディープ検証無料 / オープンソースソフトウェア選択的な形式検証、モデル検査
みらいディープ検証無料 / オープンソースソフトウェア選択的な抽象解釈、汚染分析
ルドラディープ検証無料 / オープンソースソフトウェア研究unsafe Rust のメモリ安全性のバグ
セムグレップ分野横断的無料プラン+有料プランはいカスタムセキュリティパターン、多言語対応
ソナークラウド分野横断的無料プラン+有料プランはい継続的な品質ゲート、ダッシュボード

レイヤー1:リンティング、スタイル、および開発者エクスペリエンス

クリピ

Clippyは、Rustの静的解析における決定的な出発点です。公式のRustツールチェーンに同梱されており、正確性、パフォーマンス、スタイル、複雑性、制約事項を網羅する700以上のリンターを提供します。多くのRustチームが日常的に使用しているツールであり、それには正当な理由があります。単なるスタイルの意見ではなく、実際のバグを検出してくれるからです。

bash

# Run all lints including pedantic and nursery groups
cargo clippy -- -W clippy::all -W clippy::pedantic

# Fail CI on any warning
cargo clippy -- -D warnings

# Check specific lint group
cargo clippy -- -W clippy::correctness -W clippy::suspicious

Clippyのリントカテゴリを明確に理解しておくことは重要です。

カテゴリー何を捕まえるか
correctnessほぼ確実に間違っているコード(常に拒否する)
suspiciousおそらく間違っているか、非常に驚​​くべきコード
style明らかに改善された非慣用的なパターン
complexity不必要に複雑な構造
performanceコンパイルはできるが、本来よりも実行速度が遅いコード
pedantic厳格なガイドライン、独自の判断(選択的に有効化)
restriction特定の状況で適用したいルール
nursery新しい糸くずは、偽陽性反応を引き起こす可能性があります。

カーゴチェック vs クリッピー: cargo check バイナリを生成せずに、型の正しさとコンパイルを検証します。高速で、ビルド検証に適しています。 cargo clippy runs cargo check さらに、すべてのリント分析も行います。CI の場合は、以下を実行します。 cargo check コンパイルのフィードバックを迅速に行うため、 cargo clippy -- -D warnings それぞれ独立した品質管理ゲートとして機能します。互換性はありません。 cargo check 慣用的な問題は検出されず、 cargo clippy 遅いです。

Clippyの設定 、 clippy.toml またはインライン属性を使用すると、チームはノイズを制御できます。

トムル

# clippy.toml
avoid-breaking-exported-api = false
msrv = "1.70"

さび

// Suppress a lint for one function with documented reason
#[allow(clippy::too_many_arguments)]
fn complex_setup(...) { ... }

Clippyがカバーしていない機能:モジュール間の詳細なデータフロー分析、依存関係におけるセキュリティ脆弱性のスキャン、正当性の形式的証明、組織固有のカスタムルール。これらは他のレイヤーのツールで対応する必要があります。

ラストフォーム

rustfmt は、コードベース全体で一貫したフォーマットを強制します。 cargo fmtを選択します。 rustfmt.toml 設定ファイルでは、プロジェクト全体のスタイルルールを設定します。CIでは、 cargo fmt -- --check ファイルが再フォーマットされる場合はゼロ以外の終了コードを返すため、設定の手間がかからないクリーンな品質ゲートとなります。

bash

# Check formatting without modifying files (CI mode)
cargo fmt -- --check

# Apply formatting (developer mode)
cargo fmt

rust-analyzerとIDEの統合

rust-analyzerは、Rust用の言語サーバープロトコル(LSP)実装であり、LSP互換エディタであればどこでも、リアルタイム診断、コード補完、定義へのジャンプ、インラインClippy警告などの機能を提供します。これは非推奨となったRLS(Rust Language Server)に代わるもので、新規プロジェクトでは唯一の言語サーバーとして使用されるべきです。

静的解析の観点から見ると、rust-analyzerは開発者が入力すると同時にClippy lintをインラインで表示し、別途ターミナルで実行する必要なく、スタイルや正確性に関する問題について導入時点で即座にフィードバックを提供します。

JSON

// VS Code settings.json: enable Clippy via rust-analyzer
{
  "rust-analyzer.check.command": "clippy",
  "rust-analyzer.check.extraArgs": [
    "--", "-W", "clippy::all", "-W", "clippy::pedantic"
  ]
}

rust-analyzerは、推論された型、借用ライフタイム、パラメータ名に関するヒントも提供しており、定義に移動することなく馴染みのないコードを確認するのに役立ちます。

レイヤー2:依存関係とサプライチェーンのセキュリティ

貨物監査

貨物監査は Cargo.lock RustSecアドバイザリデータベースに対してファイルを照合し、直接的および間接的な依存関係にある既知のCVEを特定します。これは、すべてのRustプロジェクトがCIで実行すべき最低限の依存関係セキュリティツールです。

bash

# Install
cargo install cargo-audit

# Run audit
cargo audit

# Ignore a specific advisory (document the reason in comments)
cargo audit --ignore RUSTSEC-2024-0001

# JSON output for pipeline integration
cargo audit --json | jq '.vulnerabilities'

cargo-auditは、既知の公開済みアドバイザリのみを対象としています。独自のコードの脆弱性、RustSecデータベースにまだ登録されていない問題、不要なライセンスなどのポリシー違反を検出することはできません。

貨物拒否

cargo-denyは、既知のCVEだけでなく、ライセンスコンプライアンス、重複クレートの検出、カスタム禁止/許可ポリシーなど、依存関係管理を拡張します。コンプライアンス要件のある組織にとって、より包括的なツールです。

トムル

# deny.toml
[advisories]
vulnerability = "deny"
unmaintained = "warn"

[licenses]
allow = ["MIT", "Apache-2.0", "ISC", "BSD-2-Clause", "BSD-3-Clause"]
deny = ["GPL-2.0"]
copyleft = "warn"

[bans]
multiple-versions = "warn"

bash

cargo install cargo-deny
cargo deny check

貨物監査可能

cargo-auditableは、コンパイル済みのRustバイナリに、専用のリンカーセクションに構造化されたメタデータとして完全な依存関係ツリーを埋め込みます。これにより、ソースコードにアクセスすることなくデプロイ済みのバイナリを監査することが可能になり、デプロイ後のセキュリティレビューやサプライチェーンの透明性確保に役立ちます。

bash

cargo install cargo-auditable
cargo auditable build --release
# The binary now contains auditable dependency metadata
# Audit a binary directly:
cargo audit bin ./target/release/my-service

レイヤー3:ディープ検証

このレイヤーのツールは、より多くの設定、より高度な専門知識、そしてより長い分析時間を必要とします。あらゆるコードベースのあらゆる機能に適しているわけではありません。しかし、安全でないコード、暗号化の実装、信頼できない入力を処理するパーサーロジック、そしてテストではなく正当性を証明する必要があるあらゆるコードには不可欠です。

Miri: 未定義動作の検出

Miriは、Rustの中間レベル表現(MIR)のインタプリタであり、コンパイラが許容するもののRustの安全性保証に違反する未定義動作(unsafeブロック内での範囲外メモリアクセス、解放後使用、アライメントのずれたポインタ逆参照、マルチスレッドのunsafeコード内でのデータ競合、Rustのエイリアシングモデルの違反など)を検出する方法でコードを実行します。

bash

# Install Miri (requires nightly)
rustup +nightly component add miri

# Run tests under Miri
cargo +nightly miri test

# Enable strict aliasing validation
MIRIFLAGS="-Zmiri-strict-provenance" cargo +nightly miri test

ミリが検出するもの: 未定義の動作 unsafe ブロック、メモリアクセス違反、解放後使用、アライメントのずれたアクセス、デバッグビルドでの整数オーバーフロー、安全でない並行コードでのデータ競合。

Miriが対象としないもの:未定義動作、依存関係の脆弱性、コードスタイル、パフォーマンスの問題を伴わない、安全なコードにおける論理バグ。

CI統合: Miriは10~50倍遅く動作します cargo test. 特定のモジュールに対して選択的に実行します unsafe コード、またはコミットごとではなく毎晩のスケジュールで:

ヤムル

- name: Miri on unsafe modules
  run: |
    rustup +nightly component add miri
    cargo +nightly miri test --package my-unsafe-crate

Kani: モデル検査と形式検証

Amazon Web Servicesが開発したKaniは、定義された境界までの実行パスを網羅的に探索することで、Rustコードの特性を形式的に検証するモデルチェッカーです。Miriが実際のテストケースを実行して具体的なバグを見つけるのに対し、Kaniは分析範囲内のすべての入力に対して特性が成り立つかどうかを証明または反証します。

Kaniでは、検証ハーネスを作成する必要があります。検証ハーネスとは、入力空間と検証対象のプロパティを定義する関数です。

さび

#[cfg(kani)]
mod verification {
    use super::*;

    #[kani::proof]
    fn verify_add_no_overflow() {
        let a: u32 = kani::any();
        let b: u32 = kani::any();
        if a.checked_add(b).is_some() {
            let result = safe_add(a, b);
            assert!(result == a + b);
        }
    }
}

bash

cargo install --locked kani-verifier
cargo kani setup
cargo kani

最適な用途:安全性が極めて重要な機能、プロトコルの実装、金融コードや暗号コードにおける算術演算、および正当性をテストするだけでなく証明する必要があるあらゆる機能。

MIRAI:抽象解釈と汚染分析

Facebook Researchが開発したMIRAIは、抽象解釈を用いてRustのMIRを分析します。関数呼び出しを通して値がどのように流れるかを追跡する手続き間分析を実行し、潜在的なパニック、契約違反、コード内での汚染の伝播を検出します。

さび

use mirai_annotations::*;

fn divide(a: i32, b: i32) -> i32 {
    precondition!(b != 0);  // MIRAI verifies all callers satisfy this
    a / b
}

MIRAIは毎晩更新されるRustコンパイラを必要とし、セットアップに時間がかかるため、セキュリティエンジニアリングに特化した能力を持つチームや、研究志向の品質要件を持つチームに最適です。

Rudra: 安全でないライブラリコードにおけるメモリの安全性

Rudraは、クレート全体にわたるプログラム全体の分析を実行し、Rustの所有権モデルに特有のメモリ安全性のバグを検出します。具体的には、Send/Syncトレイトの安全性違反、不適切なライフタイム延長を可能にする高階ライフタイムの問題、およびunsafeコードにおけるパニック安全性の問題などを検出します。元々は研究者によって開発されたもので、コンパイラプラグインとして動作し、特定のナイトリービルドバージョンが必要です。unsafe内部構造を持つライブラリクレートに対しては、コミットごとではなく、定期的に実行することをお勧めします。

クルーゾとプルスティ:演繹的検証

CreusotとPrustiは、Rustプログラムの数学的特性を証明する演繹的検証ツールです。どちらも形式仕様(事前条件、事後条件、ループ不変条件)を必要とし、自動定理証明器を用いて実装をこれらの仕様に照らして検証します。対象とする安全なRustのサブセットに限定されており、形式手法に関する専門知識が必要です。規制対象業界、暗号ライブラリ開発、あるいは数学的な正当性の証明が契約上または規制上の要件となるあらゆる状況に適しています。

追加で含める価値のあるツール

カスタムセキュリティパターン用のSemgrep

Semgrepは、複数の言語で同時に動作するパターンベースの静的解析ツールです。Rustの場合、Clippyでは表現できない組織のセキュリティポリシーやコードベース固有のパターンを強制するカスタムルールをチームが作成できるようになります。

ヤムル

# Custom rule: flag .unwrap() in production paths
rules:
  - id: no-unwrap-in-production
    pattern: $X.unwrap()
    message: "Use proper error handling instead of .unwrap()"
    languages: [rust]
    severity: WARNING

Semgrepは、コミュニティによって管理されているRustセキュリティルールを収録した管理ルールレジストリも提供しています。

継続的な品質ゲートのためのSonarCloud / SonarQube

SonarCloudは、ダッシュボード、トレンド追跡、プルリクエストの装飾機能などを備えた、継続的なコード品質分析を提供します。Rustのサポートでは、一般的なバグパターン、セキュリティ上の問題点、コードの悪臭などを網羅しています。他の言語で既にSonarCloudを使用している企業チームにとって、同じパイプラインにRustを追加することで、スタック全体にわたる統一された品質可視化が可能になります。

階層型CI/CDパイプラインの構築

以下のGitHub Actionsワークフローは、過剰な設計をせずに包括的なRust品質カバレッジを実現したいチームにとって、実践的な出発点となります。

ヤムル

# .github/workflows/quality.yml
name: Code Quality and Security

on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt

      - name: Check formatting
        run: cargo fmt -- --check

      - name: Clippy (treat warnings as errors)
        run: cargo clippy -- -D warnings

  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable

      - name: Install security tools
        run: |
          cargo install cargo-audit
          cargo install cargo-deny

      - name: Dependency audit
        run: cargo audit --deny warnings

      - name: License and policy check
        run: cargo deny check

  verify:
    runs-on: ubuntu-latest
    # Scheduled or manually triggered, not on every push
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@nightly
        with:
          components: miri

      - name: Miri on unsafe modules
        run: cargo +nightly miri test --package my-unsafe-crate

どのツールを使うべきか?意思決定ガイド

新しいRustプロジェクトを始めるには、Clippy + rustfmt + cargo-audit を使用します。5分以内に設定でき、チームが遭遇する品質およびセキュリティ上の問題の大部分を検出します。

外部依存関係を持つ本番サービス:CVE以外にも、ライセンスコンプライアンスとサプライチェーンポリシーの強制のために貨物拒否機能を追加します。

内部に安全でないコードを含むライブラリクレート:安全でないコードを含むモジュールのテストスイートにMiriを追加してください。Rudraを定期的に実行してください。

安全性が極めて重要なコードまたは暗号化コード:最も重要な機能については、Kani検証ハーネスを作成してください。チームに形式手法の専門知識がある場合は、CreusotまたはPrustiの使用を検討してください。

セキュリティ重視の組織:組織のセキュリティポリシーに対応したカスタムルール付きのSemgrepを追加し、リリースビルドでcargo-auditableを有効にします。

より大規模なチームのための継続的な可視性:SonarCloudは、オープンソースツールと連携して、トレンド追跡、プルリクエストの装飾、品質ゲートを提供します。

多言語対応の企業環境 RustがCOBOL、Java、またはその他のレガシー言語と連携する場合、単一言語のRustツールでは言語境界を越えて認識することはできません。 SMART TS XL システム全体を網羅する、言語横断的な分析を提供します。

Rustの静的解析とエンタープライズシステムが出会うとき

メインフレームやレガシープラットフォーム上でCOBOL、Java、PL/I、RPGなどを実行している組織では、新しいサービスにRustがますます利用されるようになっています。このような環境では、静的解析の範囲はRust専用ツールでは捉えきれないほど広範囲に及びます。Rustマイクロサービスは、COBOLプログラムを呼び出したり、共有データベースに書き込んだり、レガシーバッチシステムによって生成されたイベントを消費したりする可能性があります。エンタープライズアーキテクトにとって重要な品質および依存関係分析は、これらすべてのシステムを同時に対象とする必要があります。

SMART TS XL このギャップに対処するため、アプリケーションポートフォリオ全体にわたるクロス言語依存関係分析を提供します。Clippy と cargo-audit は Rust しか認識しませんが、 SMART TS XL Rust サービスが共有データ構造、レガシー プログラム、エンタープライズ API にどのように依存しているか、またそれらの依存関係を変更した場合の影響は何かを示します。そのため、これは次の目的に最適なツールとなります。 影響分析 (NAIST) と レガシーシステムの近代化計画 Rustが数あるプログラミング言語の一つとして使われている環境において。

大規模なエンタープライズコードベース内で Rust を段階的に採用するチームの場合、 SMART TS XLさん 静的コード分析 Rustコンポーネントがより大きなシステムにどのように適合するかを理解するのに必要な構造的な可視性を提供し、他の言語で書かれたコンポーネントに影響を与える可能性のある変更を行う前にそれを実現します。 依存関係グラフとアプリケーションリスクシステムを拡張する前に、依存関係の構造全体をマッピングすることが、スムーズに進む変更と、誰もテストすることを想定していなかったコンポーネントに障害を引き起こす変更を分ける決定的な要素となる。

階層的なアプローチがポイントです

Rustにおける静的解析は、単一のツールを選択するものではありません。コンパイラが無料で提供する機能から始まり、コードのリスクプロファイルに基づいて拡張していく、階層的な手法です。Clippyとrustfmtは最低限必要なツールです。cargo-auditは、外部依存関係を持つプロジェクトには必須です。Miriは、安全でないコードを含むプロジェクトには欠かせません。Kaniや形式検証ツールは、誤りが許されない関数に使用します。

これを正しく実践しているチームは、静的解析を開発ループに組み込んでいます。エディタにClippyをインラインで組み込み、CI実行ごとにcargo-auditを実行し、テストだけでは検出できないバグを毎晩Miriで検出します。その結果、バグが減るだけでなく、開発と本番環境の間の解析レイヤーが正しく機能しているという確信が生まれ、チームはコードベースに対して迅速に変更を加えることができるようになります。