(0) まえがき
Rust、もといCargo圏はほぼ中央集権1かつセマンティックバージョニングによる互換性が担保2されているので脆弱性アラートは解消しやすい部類に入ります。
そのため、dependabotと呼ばれるGitHub公式のbotが脆弱性を持たないバージョンに更新するために巡回して勝手にPull Requestを置いていってくれることがあります。もし成功していたら、それをマージしてあなたの仕事は終わりです。
しかし、dependabotは万能ではないため、ときどきバージョンの自動更新に失敗することがあります。
そこで、今回はGHSA-c827-hfw6-qwvmを例に取り、脆弱性アラートを無視せず正しく解決する方法を残します。
(1) 脆弱なパッケージの特定
通常、Dependabot alertによって当該パッケージが表示されるはずです。RustSecによる脆弱性データベースから流入してくることが結構あります。
今回のGHSA-c827-hfw6-qwvmはrustixというクレートが脆弱性を抱えています。
(2) 直接的な依存か、間接的な依存か見極める
パッケージ管理システムによってダウンロードされるパッケージは大きく分けて2つあります。
- 自分のパッケージが直接依存しているパッケージ
- 自分のパッケージが依存しているパッケージが依存しているパッケージ (推移的依存; transitive dependency)
しかし、その制約を解いた解の一つであるCargo.lockを眺めただけでは各バージョンがフラットに記述されており読み解くのは大変です。
そこで、cargo-treeの出番です。組み込みのサブコマンドによって、すぐにどの経路か特定することができます。
早速次のコマンドを打ってみましょう。
cargo tree -i rustix
私のプロジェクトでは、次のように表示されました。
rustix v0.37.6
└── is-terminal v0.4.6
└── env_logger v0.10.0
├── origlang-cli v0.1.0 (/home/kisaragi/IdeaProjects/origlang/package/origlang-cli)
└── origlang-testsuite v0.1.0 (/home/kisaragi/IdeaProjects/origlang/package/origlang-testsuite)
(3) 手でがんばる
制約さえ満たされればどの戦略を選んでも良いです。しかし、一般に古いバージョンを一気に新しいバージョンに上げることは大変なのでついでに直してしまいましょう。
Cargo.lockを手で触るわけには行かないので、cargo-updateというこれまた組み込みのサブコマンドを使います。
ただし、何もスイッチをつけないとすべてが更新されてノイズになってしまうので-pスイッチでクレートを指定して必要最小限のクレートを更新します。
まず、cargo update -p env_loggerを試します。しかし(執筆時点では)何も変化がありませんでした。
次にcargo update -p is-terminalを試します。すると以下のような出力が出ました:
Updating crates.io index
Updating errno v0.3.0 -> v0.3.5
Removing errno-dragonfly v0.1.2
Removing io-lifetimes v1.0.9
Updating is-terminal v0.4.6 -> v0.4.9
Updating linux-raw-sys v0.3.1 -> v0.4.10
Updating rustix v0.37.6 -> v0.38.13
rustixが0.38系列にアップグレードされました。しかし、このバージョンは脆弱なバージョンです。
最後にcargo update -p rustixを試しましょう。しかし、何も出ませんでした!なぜでしょう?
それは、-pをつけるとそのクレートの依存クレートのバージョンを変えない範囲で探索するようになるからです。
これをオプトアウトするためには、--aggressiveフラグをつける必要があります。早速やってみましょう:
Updating bitflags v2.4.0 -> v2.4.1
Updating libc v0.2.147 -> v0.2.149
Updating rustix v0.38.13 -> v0.38.20
Updating windows-targets v0.48.0 -> v0.48.5
Updating windows_aarch64_gnullvm v0.48.0 -> v0.48.5
Updating windows_aarch64_msvc v0.48.0 -> v0.48.5
Updating windows_i686_gnu v0.48.0 -> v0.48.5
Updating windows_i686_msvc v0.48.0 -> v0.48.5
Updating windows_x86_64_gnu v0.48.0 -> v0.48.5
Updating windows_x86_64_gnullvm v0.48.0 -> v0.48.5
Updating windows_x86_64_msvc v0.48.0 -> v0.48.5
うまく行きましたね!
(4) 終わりに
最近はdependabotやrenovateのおかげでだいぶ楽になりましたが、彼らはまだこういった込み入った問題を解決できる力を持っていません。
たまには手動で修正する必要もありますが、がんばりましょう ![]()
-
https://crates.io に大体ある ↩
-
互換性があるとみなされるバージョンに上げてコードを変えずに再コンパイルしようとした際動かなければライブラリ作者が「悪い」 ↩