.NET向けプロジェクトで「Bump YamlDotNet from 17.0.1 to 17.1.0」という更新を見た場合、まず押さえるべき結論はシンプルです。これは.NET本体の仕様変更ではなく、YAML処理ライブラリ YamlDotNet の依存関係を 17.0.1 から 17.1.0 に上げる更新です。主な目的はセキュリティ改善で、特に大きなYAMLファイル、外部入力のYAML、MergingParser を使ったマージキー処理を扱うプロジェクトでは、更新後の動作確認が必要です。Microsoftの agent-governance-toolkit では2026年5月5日にDependabotによるPRがマージされ、AgentGovernance.csproj の PackageReference が YamlDotNet 17.0.1 から 17.1.0 に変更されています。(GitHub)
.NET documentation update: Bump YamlDotNet from 17.0.1 to 17.1.0で確認すべきポイント
今回の更新は、単なる「最新版に上げた」だけの変更として扱わない方が安全です。YamlDotNet 17.1.0 のリリースノートでは、変更点として Security improvements が挙げられており、MergingParser で大きなYAMLを扱う場合に潜在的な破壊的変更があると説明されています。具体的には、処理できるパースイベント数に上限が入り、既定値は 100,000 イベントです。(GitHub)
.NETアプリケーションでYAMLを使う場面は、設定ファイル、CI/CD定義、Kubernetesマニフェスト、OpenAPI関連ファイル、社内ツールの定義ファイルなど多岐にわたります。YamlDotNetはNuGet上でも広く利用されているYAMLライブラリで、低レベルのパース、YAML出力、オブジェクトモデル、シリアライズ・デシリアライズ機能を提供しています。([NuGet][3])
今回確認すべき点は、主に次の4つです。
| 確認項目 | 見るべき内容 | 対応の優先度 |
|---|---|---|
| YamlDotNetの利用有無 | .csproj、Directory.Packages.props、ロックファイルで参照を確認 | 高 |
| YAML入力の性質 | 外部ユーザー、API、アップロード、リポジトリ外部から入るか | 高 |
| 大きなYAMLの処理 | 大量のキー、アンカー、タグ、マージキーを含む可能性があるか | 高 |
MergingParser の利用 | 直接利用、またはマージキーを展開する処理があるか | 中〜高 |
何が変わったのか
Microsoftの agent-governance-toolkit のPRでは、変更ファイルは .csproj 1件のみで、YamlDotNet のバージョン指定が 17.0.1 から 17.1.0 に置き換えられています。PR上では、この依存関係は direct:production、更新種別は version-update:semver-minor とされています。(GitHub)
<PackageReference Include="YamlDotNet" Version="17.0.1" />
更新後は次のようになります。
<PackageReference Include="YamlDotNet" Version="17.1.0" />
Central Package Managementを使っているプロジェクトでは、.csproj ではなく Directory.Packages.props 側で管理している場合があります。
<PackageVersion Include="YamlDotNet" Version="17.1.0" />
NuGetのパッケージページでも、YamlDotNet 17.1.0 のインストール例として dotnet add package YamlDotNet --version 17.1.0、PackageReference、CPM向けの PackageVersion が案内されています。([NuGet][3])
YamlDotNet 17.1.0の主な変更点
YamlDotNet 17.1.0 の中心はセキュリティ改善です。関連するPRでは、主に2つの問題に対応しています。
1つ目は、MergingParser において、マージ処理によってパースイベントが膨張し、メモリを過剰に消費する可能性です。これを抑えるため、MergingParser に最大パースイベント数の制限が追加されました。
2つ目は、YAML内の一意なキー、アンカー、タグなどを大量に処理する場合に、文字列インターンがメモリ消費につながる可能性です。関連PRでは、入力由来のアンカー名、タグ名、スカラーキーに対する string.Intern の扱いが変更されています。(GitHub)
MergingParserにイベント数上限が追加された
MergingParser には、最大パースイベント数を指定できるコンストラクターが追加されています。既定値は 100,000 です。上限を超えた場合は、過剰なメモリ使用を防ぐために YamlException が投げられます。(GitHub)
関連PRの差分では、次のような考え方の変更が確認できます。
public MergingParser(IParser innerParser)
: this(innerParser, 100_000)
{
}
public MergingParser(IParser innerParser, int maxParsingEvents = 100_000)
{
if (maxParsingEvents <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxParsingEvents), "Max parsing events must be a positive integer.");
}
// ...
}
実務上重要なのは、「大きなYAMLファイルなら必ず壊れる」という意味ではない点です。通常の設定ファイルや小〜中規模のYAMLでは、100,000イベントはかなり大きな上限です。一方で、マージキー、アンカー、エイリアスを多用して展開後の構造が大きくなるYAMLでは、ファイルサイズが見た目ほど大きくなくてもイベント数が膨らむ可能性があります。
文字列インターンによるメモリ問題が緩和された
PRでは、AnchorName、TagName、スカラーキーに関連する処理で、入力由来の文字列を常に string.Intern するのではなく、すでにインターン済みならそれを使い、そうでなければ元の値を使う形に変更されています。(GitHub)
たとえば、アンカー名では次のような変更が行われています。
this.value = string.Intern(value);
から、次のような処理に変わっています。
this.value = string.IsInterned(value) ?? value;
これは、攻撃的または異常に大きなYAML入力によって、多数の一意なキー・アンカー・タグが作られた場合のメモリ消費リスクを下げるための変更と見てよいでしょう。
誰が対応すべきか
対応が必要かどうかは、「YamlDotNetを使っているか」だけでなく、「どのようなYAMLを処理しているか」で判断します。
| 対象 | 対応方針 |
|---|---|
| 外部ユーザーがアップロードしたYAMLを処理するAPI・Webアプリ | 早めに 17.1.0 へ更新し、異常入力のテストを追加 |
| CI/CD、Kubernetes、OpenAPI、設定生成ツールなどで大きなYAMLを読むツール | 更新後に大きな実データで回帰テスト |
MergingParser を直接使っているライブラリ・社内ツール | maxParsingEvents の既定値で足りるか確認 |
| 小さな社内設定ファイルだけを読むアプリ | 基本は更新で問題ないが、ビルドと最低限の読み込みテストは実施 |
| YAMLを出力するだけで入力をほぼ読まないアプリ | 影響は限定的。ただし依存関係管理上は更新候補 |
特に注意したいのは、「自社アプリではYamlDotNetを直接意識していないが、別のパッケージ経由で使っている」ケースです。NuGetでは推移的依存関係としてライブラリが入ることがあります。dotnet list package --include-transitive を使うと、直接依存だけでなく推移的依存も確認できます。
dotnet list package --include-transitive
直接参照している場合は、次のように表示されます。
dotnet list package
複数プロジェクトのソリューションでは、ルートでまとめて確認します。
dotnet list YourSolution.sln package --include-transitive
影響範囲はどこまで見るべきか
今回の更新では、.NET SDK、ASP.NET Core、ランタイムそのものの挙動が変わるわけではありません。影響範囲は、YamlDotNetを使ったYAMLの読み書き処理に限定して考えるのが現実的です。
ただし、YAMLは設定や定義ファイルとして使われやすいため、障害が起きるとアプリ起動、デプロイ、設定読み込み、コード生成、スキーマ変換などの初期段階で失敗することがあります。ライブラリ更新の影響が小さそうに見えても、起動時にYAMLを読むシステムでは確認を省かない方が安全です。
確認すべきコード例
次のようなコードがある場合は、更新後に実データでテストしてください。
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var config = deserializer.Deserialize<MyConfig>(yamlText);
通常のデシリアライズ処理だけであれば、大きな破壊的変更に直面する可能性は高くありません。ただし、読み込むYAMLが巨大、またはアンカーやマージキーを多用している場合は別です。
特に次のようなYAMLを扱う場合は、テストを厚めにします。
defaults: &defaults
retry: 3
timeout: 30
serviceA:
<<: *defaults
endpoint: https://example.com/a
serviceB:
<<: *defaults
endpoint: https://example.com/b
この程度のマージで問題になる可能性は低いものの、マージが何層にもネストし、さらに多数の項目へ展開されると、内部イベント数が増えます。17.1.0では、その膨張を制限する仕組みが入っています。
移行時の実務チェックリスト
更新作業は、単にNuGetパッケージを上げて終わりにせず、次の順で確認すると失敗を避けやすくなります。
| 手順 | 作業内容 | 判断基準 |
|---|---|---|
| 依存関係の確認 | YamlDotNet の直接・推移的参照を確認 | 17.0.1以前を使っていないか |
| バージョン更新 | 17.1.0 に更新 | .csproj または Directory.Packages.props を修正 |
| ビルド確認 | dotnet restore、dotnet build を実行 | 参照解決やコンパイルエラーがないか |
| YAML読み込みテスト | 実際の設定ファイル・定義ファイルでテスト | 起動・変換・デシリアライズが成功するか |
| 大規模YAML確認 | 大きなファイルやマージキー付きYAMLを処理 | Too many parsing events が発生しないか |
| セキュリティ観点の確認 | 外部入力YAMLにサイズ制限や検証を設ける | 異常入力でメモリを消費し続けないか |
更新コマンドは次の通りです。
dotnet add package YamlDotNet --version 17.1.0
既存のプロジェクトで復元とビルドを確認します。
dotnet restore
dotnet build
dotnet test
Central Package Managementを使っている場合は、Directory.Packages.props を編集します。
<ItemGroup>
<PackageVersion Include="YamlDotNet" Version="17.1.0" />
</ItemGroup>
その後、ソリューション全体でテストします。
dotnet restore
dotnet test
Too many parsing events が出た場合の考え方
YamlDotNet 17.1.0への更新後、MergingParser を使う処理で Too many parsing events を含む YamlException が出た場合、すぐに上限を大きくするのではなく、まずYAMLの内容を確認してください。関連PRでは、上限を超えた場合に「過剰なメモリ使用を防ぐため」として例外を投げる処理が追加されています。(GitHub)
確認の順番は次の通りです。
- 対象YAMLにマージキー
<<が多用されていないか - アンカー
&nameとエイリアス*nameが深くネストしていないか - 同じ定義を過剰に展開する構造になっていないか
- 外部入力の場合、サイズ制限やスキーマ検証があるか
- 業務上本当に必要な構造か
業務上どうしても大きなYAMLを扱う場合は、MergingParser の上限を明示的に指定する選択肢があります。
using System.IO;
using YamlDotNet.Core;
using YamlDotNet.Serialization;
var parser = new Parser(new StringReader(yamlText));
// 例: 業務上必要な範囲を検証したうえで上限を調整
var mergingParser = new MergingParser(parser, maxParsingEvents: 200_000);
var deserializer = new DeserializerBuilder().Build();
var result = deserializer.Deserialize<Dictionary<string, object>>(mergingParser);
ただし、上限を大きくするほど、悪意ある入力や異常データによるメモリ消費リスクも上がります。外部から受け取るYAMLでは、ライブラリ側の上限に頼るだけでなく、アプリ側でもファイルサイズ、行数、最大ネスト、受け付けるキーの種類を制限する方が安全です。
失敗しやすいポイント
「マイナーアップデートだから安全」と判断してしまう
17.0.1から17.1.0はSemVer上はマイナー更新です。しかし、今回のリリースノートでは、大きなYAMLを MergingParser で処理する場合に潜在的な破壊的変更があると明記されています。バージョン番号だけで影響が小さいと判断せず、リリースノートの内容で判断してください。(GitHub)
テストデータが小さすぎる
開発環境では小さなサンプルYAMLしか使わず、本番では大量の設定、生成済みマニフェスト、長いOpenAPI定義を読むケースがあります。この場合、通常の単体テストでは問題が見つかりません。
本番に近いYAMLを最低1つはテストに入れてください。特に「生成ツールが出力したYAML」は、人間が書いた設定ファイルよりも巨大化しやすいため注意が必要です。
推移的依存関係を見落とす
YamlDotNetを自分でインストールした記憶がなくても、別のNuGetパッケージが内部で使っている場合があります。直接参照だけを見て「使っていない」と判断しないでください。
dotnet list package --include-transitive
このコマンドで、YamlDotNetがどこから入っているかを確認できます。推移的依存の場合、自分のプロジェクトから直接バージョンを固定するか、依存元パッケージの更新を待つかを判断します。
例外を握りつぶして設定読み込み失敗に気づかない
設定ファイル読み込み時に例外を握りつぶし、デフォルト設定で起動する実装は危険です。YamlDotNet更新後にパース失敗が起きても、ログがなければ原因を追えません。
設定読み込みでは、少なくとも次の情報をログに出すようにします。
| ログ項目 | 理由 |
|---|---|
| 読み込んだファイル名 | どのYAMLで失敗したか分かる |
| 例外メッセージ | Too many parsing events などの判定に必要 |
| アプリのバージョン | 更新前後の比較に必要 |
| YamlDotNetのバージョン | 依存関係更新の影響を切り分けやすい |
外部入力のYAMLを扱う場合の安全な設計
YamlDotNet 17.1.0のセキュリティ改善は重要ですが、ライブラリ更新だけでYAML処理の安全性が完成するわけではありません。外部入力を受け付ける.NETアプリでは、次のような多層防御が必要です。
| 対策 | 具体例 |
|---|---|
| サイズ制限 | アップロードYAMLは1MBまで、API入力は数百KBまでなど |
| タイムアウト | 解析処理をリクエスト時間内に制限 |
| スキーマ検証 | 許可するキー、型、階層を限定 |
| マージキー制限 | 不要なら <<、アンカー、エイリアスを受け付けない |
| エラーログ | 解析失敗を監視し、異常な入力パターンを検知 |
| サンドボックス化 | 変換ツールやバッチ処理を本体アプリから分離 |
実務では、「YAMLを読める」ことよりも「想定外のYAMLを安全に拒否できる」ことが重要です。特にWeb API、管理画面、CI連携、Bot連携などでYAMLを受け付ける場合は、正常系だけでなく異常系のテストを追加してください。
.NETプロジェクトでの更新判断
今回の「Bump YamlDotNet from 17.0.1 to 17.1.0」は、基本的には前向きに適用すべき更新です。理由は、セキュリティ改善が主目的であり、通常規模のYAML処理では大きな修正を必要としない可能性が高いからです。
ただし、次の条件に当てはまる場合は、更新を自動マージで済ませず、レビュー対象にしてください。
- YAMLを外部入力として受け取っている
- YAMLのマージキー、アンカー、エイリアスを使っている
- 生成された巨大なYAMLを処理している
MergingParserを直接利用している- 設定ファイルの読み込み失敗がアプリ起動に直結する
- NuGetパッケージ更新をDependabotやGitHub Actionsで自動化している
MicrosoftのPRでも、Dependency Reviewでは脆弱なパッケージ数は0件と表示されつつ、YamlDotNet 17.1.0 のライセンスが unknown として検出されています。NuGet上ではYamlDotNet 17.1.0 のパッケージページにMIT licenseが表示されているため、組織のライセンスチェックツールで差異が出る場合は、ツール側の検出結果とNuGet上のパッケージ情報を照合してください。(GitHub)
更新後に入れておきたいテスト
最低限、次の3種類のテストを追加すると安心です。
通常の設定ファイルを読み込めるか
[Fact]
public void LoadConfig_ShouldDeserializeYaml()
{
var yaml = """
serviceName: sample
retryCount: 3
timeoutSeconds: 30
""";
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var config = deserializer.Deserialize<AppConfig>(yaml);
Assert.Equal("sample", config.ServiceName);
Assert.Equal(3, config.RetryCount);
}
マージキーを含むYAMLを読み込めるか
[Fact]
public void LoadConfig_ShouldHandleYamlMergeKeys()
{
var yaml = """
defaults: &defaults
retryCount: 3
timeoutSeconds: 30
service:
<<: *defaults
serviceName: sample
""";
var parser = new Parser(new StringReader(yaml));
var mergingParser = new MergingParser(parser);
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var result = deserializer.Deserialize<Dictionary<string, object>>(mergingParser);
Assert.NotNull(result);
}
異常に大きい入力を拒否できるか
[Fact]
public void LoadConfig_ShouldRejectTooManyParsingEvents()
{
var yaml = GenerateLargeMergedYaml();
var parser = new Parser(new StringReader(yaml));
var mergingParser = new MergingParser(parser, maxParsingEvents: 1_000);
Assert.Throws<YamlException>(() =>
{
while (mergingParser.MoveNext())
{
}
});
}
このテストの目的は、「大きなYAMLを無理に通す」ことではありません。想定外の入力に対して、アプリがメモリを消費し続けず、安全に失敗できることを確認するためです。
まとめ:まず依存関係を確認し、YAML入力の規模で対応を決める
「.NET documentation update: Bump YamlDotNet from 17.0.1 to 17.1.0」は、.NET本体の変更ではなく、YamlDotNetのセキュリティ改善を取り込む依存関係更新です。通常の.NETアプリでは、17.1.0への更新を前向きに検討してよい内容です。
ただし、MergingParser に最大パースイベント数の制限が入ったため、大きなYAMLやマージキーを多用するYAMLでは、更新後に例外が発生する可能性があります。対応の第一歩は、dotnet list package --include-transitive でYamlDotNetの利用有無を確認することです。そのうえで、実際に使っているYAMLファイル、外部入力、マージキーの有無を見直し、必要なら maxParsingEvents の調整や入力制限を追加してください。
依存関係更新は、ビルドが通るだけでは完了ではありません。YAMLを読む場所、失敗時のログ、外部入力の制限まで確認しておくことで、セキュリティ改善を取り込みながら、運用上のトラブルも避けやすくなります。
[3]: https://www.nuget.org/packages/YamlDotNet/17.1.0 “
NuGet Gallery
| YamlDotNet 17.1.0
“

コメント