CodeQL 2.26.1を利用し、C/C++向けのcustom dataflow modelをYAMLで管理している場合は、models-as-dataのflow summaryに残っている未修飾field名を、MyNamespace::MyStruct::myFieldのような完全修飾名へ移行する必要があります。
現時点ではmyFieldのような未修飾名も互換機能によって動作します。しかし、GitHubは2026年7月29日の案内で、未修飾field名のサポートを12か月後に削除する予定だと説明しています。実務上は2027年7月ごろを目安にしつつ、早めにモデルの棚卸し、置換、テスト、再混入防止まで完了させるのが安全です。(The GitHub Blog)
CodeQL 2.26.1でC/C++のfield名はどう変わったのか
今回の変更点を整理すると、次のようになります。
| 項目 | 内容 |
|---|---|
| 対象 | C/C++のmodels-as-data flow summary |
| 旧形式 | myField |
| 新形式 | MyNamespace::MyStruct::myField |
| 現在の互換性 | 未修飾名も一時的に利用可能 |
| 移行期間 | 12か月 |
| 削除時期の目安 | 2027年7月ごろ |
| 推奨対応 | 既存モデルを完全修飾field名へ変更 |
CodeQL CLI 2.26.1のリリース日は2026年7月15日です。正式な変更履歴では、この変更は即時削除を伴うBreaking Changesではなく、Deprecated APIsとして案内されています。その後、GitHubが2026年7月29日に公開したChangelogで、未修飾名のサポートを12か月後に削除する方針が明示されました。削除されるCodeQLの正確なバージョンまでは公表されていません。(The GitHub Blog)
つまり、CodeQL 2.26.1へ更新した直後にすべてのカスタムモデルが壊れるわけではありません。ただし、現在正常に動いていることを理由に対応を先送りすると、互換機能の削除後にflow summaryが適用されなくなる可能性があります。
影響を受けるのはmodels-as-dataのflow summary
CodeQLのC/C++向けカスタムモデルは、YAML形式のdata extensionで定義できます。flow summaryを追加するときは、通常、次のようにsummaryModelを指定します。
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data:
- <モデルを表すタプル>
summaryModelは、関数やメソッドのどこからどこへデータが流れるかを定義するモデルです。タプルにはnamespace、type、関数名、input、output、flowの種類などを記述します。今回の変更は、このflow summary内で参照するfield名に関係します。(CodeQL)
最優先で確認するファイル
まず、リポジトリやmodel pack内で、次の条件に該当するYAMLファイルを探します。
pack: codeql/cpp-allを使用しているextensible: summaryModelを使用している- inputまたはoutputのaccess pathに
Field[...]がある - 自動生成されたC/C++モデルを含んでいる
- 複数のリポジトリから共有されているmodel packである
たとえば、次のような記述が移行候補です。
Argument[-1].Field[myField]
今回の変更後は、fieldを宣言しているnamespaceと型を含めます。
Argument[-1].Field[MyNamespace::MyStruct::myField]
公式情報で明示されている主な対象は、models-as-dataのflow summaryです。C/C++ソースコードに書かれたメンバー変数名そのものを変更する話ではありません。
また、sourceModelやsinkModelをすべて一律に書き換える変更でもありません。ただし、同じmodel pack内でfieldを含むaccess pathを使用している場合は、CodeQL更新後の動作確認をまとめて行うと安全です。
変数をsourceやsinkにする変更とは別問題
CodeQL 2.26.1では、models-as-dataで変数をsourceやsinkとして使用する機能が削除されています。該当するモデルはQL言語での定義へ移行する必要があります。
これは、未修飾field名に12か月の移行期間が設けられた今回の変更とは別です。調査中にエラーが見つかった場合は、field名の問題なのか、変数をsourceやsinkにしている問題なのかを切り分けてください。(CodeQL)
完全修飾field名の作り方
完全修飾field名は、基本的に次の要素を::でつないだ名前です。
namespace::宣言元の型::field名
たとえば、C++側の宣言が次のようになっているとします。
namespace MyNamespace {
struct MyStruct {
std::string myField;
};
}
この場合、CodeQLモデルで指定するfield名は次の形式です。
MyNamespace::MyStruct::myField
構成要素を分解すると、次のようになります。
| 要素 | 値 |
|---|---|
| namespace | MyNamespace |
| fieldを宣言する型 | MyStruct |
| field名 | myField |
| 完全修飾field名 | MyNamespace::MyStruct::myField |
namespaceが階層化されている場合は、その階層も含めます。
namespace Company {
namespace Security {
struct Request {
std::string payload;
};
}
}
この場合は、次のように指定します。
Company::Security::Request::payload
重要なのは、モデル化しているメソッドのnamespaceとtypeを機械的にfield名の前へ付けないことです。
たとえば、Argument[0].Field[...]が第1引数の内部fieldを参照している場合、そのfieldの宣言元はメソッドを所有するクラスではなく、第1引数の型です。必ずC/C++の宣言を確認し、実際にfieldを宣言している型の完全修飾名を使用してください。
custom dataflow modelの修正例
次の例では、setFieldの第1引数から、オブジェクトのmyFieldへ値が流れることを表しています。
修正前
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data:
- ["MyNamespace", "MyStruct", False, "setField", "", "",
"Argument[0]",
"Argument[-1].Field[myField]",
"value",
"manual"]
修正後
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data:
- ["MyNamespace", "MyStruct", False, "setField", "", "",
"Argument[0]",
"Argument[-1].Field[MyNamespace::MyStruct::myField]",
"value",
"manual"]
差分だけを見ると、変更箇所は明確です。
- "Argument[-1].Field[myField]"
+ "Argument[-1].Field[MyNamespace::MyStruct::myField]"
今回の移行では、原則としてField[...]の中身を完全修飾名へ変更します。タプル先頭のnamespace、type、関数名、signatureまで一緒に変更する必要はありません。ただし、既存モデル自体に誤りが見つかった場合は別途修正します。
この例はfield名の書式に焦点を当てたものです。実際のinput、output、valueまたはtaintの選択は、対象となるライブラリのデータフローに合わせる必要があります。summaryModelでは、第7要素がflowの入力、第8要素が出力を表します。(CodeQL)
CodeQL C/C++のfield名を移行する手順
model packとYAMLファイルを棚卸しする
最初に、C/C++向けのdata extensionをリポジトリ全体から探します。
ripgrepを利用できる環境では、次のコマンドでsummaryModelとField[を含む箇所を検索できます。
rg -n --glob '*.yml' --glob '*.yaml' \
'extensible:\s*summaryModel|Field\[' .
次の場所も忘れずに確認してください。
- CodeQLクエリを置いている専用リポジトリ
- 共通のmodel pack
- GitHub Container Registryで配布しているpackのソース
- ビルド処理で生成されるYAMLファイル
- monorepo内のサブプロジェクト
- 過去のモデルをコピーして作った派生リポジトリ
共有model packを修正せず、各利用リポジトリだけを確認しても、次回のpack更新で未修飾名が再び入り込む可能性があります。
未修飾field名の候補を抽出する
単純なC/C++識別子だけがField[...]内に書かれている行は、次の正規表現で候補を抽出できます。
rg -n --glob '*.yml' --glob '*.yaml' \
'Field\[[A-Za-z_][A-Za-z0-9_]*\]' .
たとえば、次の記述は検出対象になります。
Field[myField]
Field[data]
Field[payload]
一方、すでに完全修飾されている次の記述は検出されません。
Field[MyNamespace::MyStruct::myField]
この正規表現は、単純な未修飾名を見つけるための一次チェックです。特殊な命名、生成形式、複雑なaccess pathをすべて検証できるわけではないため、最終的にはField[を含む行を目視でも確認します。
C/C++の宣言から完全修飾名を確定する
検出したfieldごとに、次の情報を確認します。
- fieldを宣言しているnamespace
- fieldを直接宣言しているstructまたはclass
- 入れ子になった型があるか
- 同名fieldを持つ別の型がないか
- access pathの起点が引数、戻り値、オブジェクトのどれか
ヘッダーファイル、ライブラリの公開API、コンパイル対象の実装を確認し、推測だけで完全修飾名を作らないことが重要です。
特にdata、value、name、bufferのような一般的なfield名は、多数の型で重複しやすいため、優先的に確認します。
モデルの生成元を修正する
YAMLがスクリプトやmodel generatorから生成されている場合は、生成結果だけでなく生成元を修正します。
生成済みYAMLだけを手作業で変更すると、次回の生成処理で未修飾名へ戻ってしまいます。次の順番で対応すると再発を防げます。
- テンプレートやモデル生成ロジックを修正する
- YAMLを再生成する
- 生成後のYAMLに未修飾名が残っていないか検索する
- 生成結果と生成元を同じPull Requestに含める
現行CodeQLでモデルをテストする
置換後は、YAMLの構文確認だけで終わらせず、実際のCodeQL解析を実行します。
確認する項目は次のとおりです。
- model packが正常に読み込まれるか
- 解析がエラーなく完了するか
- 想定するfieldまでデータフローが到達するか
- 既存のセキュリティアラートが不自然に消えていないか
- 無関係な型の同名fieldへflowが広がっていないか
- 修正前後で解析時間が大きく変化していないか
テストコードには、同じfield名を持つ複数のstructを用意すると効果的です。
namespace App {
struct Request {
std::string data;
};
struct Response {
std::string data;
};
}
この場合、App::Request::dataだけをモデル化したときに、App::Response::dataまで誤ってflowとして扱われないことを確認できます。完全修飾へ移行する利点を直接検証できるテストです。
CodeQLのC/C++ライブラリには、models-as-dataの行に誤記がないか調べるExternalFlow::ModelValidation::invalidModelRowも用意されています。ただし、構文上正しい完全修飾名が実際に意図したfieldを指しているかまでは、データフローのテストで確認する必要があります。(CodeQL)
CIで未修飾名の再混入を防ぐ
移行後は、単純な未修飾field名を検出するチェックをCIへ追加できます。
if rg -n --glob '*.yml' --glob '*.yaml' \
'Field\[[A-Za-z_][A-Za-z0-9_]*\]' .; then
echo "Unqualified CodeQL C/C++ field name found." >&2
exit 1
fi
このチェックは、次のようなPull Requestを失敗させます。
Field[myField]
一方、次のような完全修飾名は許可します。
Field[MyNamespace::MyStruct::myField]
正規表現だけでは完全修飾名の正しさまでは保証できません。そのため、CIでは次の2段階にすると実用的です。
- 正規表現で明らかな未修飾名を拒否する
- CodeQLのモデルテストでfieldの解決とデータフローを確認する
移行で失敗しやすいポイント
| 失敗例 | 問題点 | 対策 |
|---|---|---|
| 解析が成功しているので対応しない | 現在は互換機能で動いている可能性がある | 未修飾名を検索してゼロにする |
| タプル先頭のnamespaceとtypeをそのまま付ける | fieldが引数や戻り値の型に属する場合がある | fieldの実際の宣言元を確認する |
| 生成済みYAMLだけを書き換える | 再生成時に未修飾名へ戻る | generatorやテンプレートを修正する |
myFieldという文字列を一括置換する | 関数名やコメントまで変更する恐れがある | Field[...]内だけを対象にする |
| YAMLの読み込み成功だけを確認する | 間違った型のfieldを指していても気付けない | positive・negative両方のflowテストを行う |
| 12か月後まで作業しない | 正確な削除バージョンは未公表 | 互換期間をテスト期間として使う |
| 利用リポジトリだけを修正する | 共有model packから再混入する | 配布元のpackを先に修正する |
特に注意したいのは、解析が失敗しないことと、移行が完了していることは別という点です。未修飾field名は移行期間中もサポートされるため、通常の解析成功だけでは未対応箇所を発見できません。
GitHub code scanningでは早めの対応が必要
GitHub.comのGitHub code scanningには、新しいCodeQLバージョンが自動的に展開されます。そのため、利用者がCodeQL CLIのバージョンを明示的に更新していなくても、GitHub側の更新によって新しい動作が適用されることがあります。
GitHub Enterprise ServerではCodeQL 2.26.1の機能が将来のリリースに含まれる予定ですが、導入時期はGitHub.comと異なる可能性があります。複数環境で同じmodel packを利用している場合は、未修飾名と完全修飾名が混在する状態を長期間維持せず、完全修飾名へ統一する方が管理しやすくなります。(The GitHub Blog)
C/C++のdata extensionによるライブラリカスタマイズは、公式ドキュメント上でもBetaかつUnstable APIとされています。今後も書式変更が発生する可能性があるため、モデル定義を通常のソースコードと同様にテストし、CodeQLの更新履歴を継続的に確認できる運用が必要です。(CodeQL)
よくある疑問
未修飾field名は今すぐ使えなくなるのか
今すぐ使えなくなるわけではありません。CodeQL 2.26.1では引き続き未修飾名がサポートされています。
ただし、これは移行のための互換対応です。GitHubは12か月後にサポートを削除する予定としているため、新しいモデルを未修飾名で追加することは避けてください。(The GitHub Blog)
具体的な削除日はいつか
GitHubの案内を基準にすると、2027年7月ごろが目安です。ただし、削除されるCodeQLのバージョンや正確な日付は明示されていません。
社内計画では期限ぎりぎりの日付を設定せず、2026年中など余裕のある時期に移行を完了させる方が安全です。
GitHub Actionsのworkflowも変更する必要があるか
今回の中心的な修正対象は、C/C++のcustom dataflow modelを定義しているYAMLです。field名の完全修飾化だけを理由として、GitHub Actionsのworkflow変更が必須だとは案内されていません。
ただし、CodeQL ActionやCLIのバージョンを固定している場合は、現在使用しているバージョンと更新後のバージョンの両方でモデルをテストしてください。
C/C++ソースコードのfield名も変更するのか
変更しません。ソースコード側のmyFieldというメンバー変数名はそのままです。
変更するのは、CodeQLのmodels-as-data flow summaryからそのfieldを参照するときの文字列です。
- Field[myField]
+ Field[MyNamespace::MyStruct::myField]
まとめ:まず未修飾field名を検索する
CodeQL 2.26.1では、C/C++のmodels-as-data flow summaryで使用するfield名が、完全修飾名へ移行します。
対応の要点は次のとおりです。
summaryModelを含むC/C++のYAMLを棚卸しするField[myField]のような未修飾名を検索する- fieldの宣言元を確認する
Field[MyNamespace::MyStruct::myField]へ置き換える- CodeQL解析とデータフローテストを実行する
- generatorや共有model packも修正する
- CIで未修飾名の再混入を防ぐ
12か月は対応を先送りするための期間ではなく、既存モデルを安全に切り替えるための移行期間です。まずはリポジトリ全体でField[を検索し、未修飾名の件数と修正対象のmodel packを把握するところから始めてください。

コメント