Skip to main content

Enterprise Server 3.21 は、現在リリース候補として使用できます。

Code scanningの SARIF サポート

サードパーティ製ツールの SARIF ファイルが GitHubの標準に準拠していることを確認します。

この機能を使用できるユーザーについて

Code scanning は、次のリポジトリの種類で使用できます。

  • GitHub.com 上のパブリックリポジトリ
  • GitHub Team、GitHub Enterprise Cloud、または GitHub Enterprise Server 上の組織所有リポジトリ。 GitHub Code Security が 有効になっています。

GitHub では、サードパーティ製ツールによって生成された SARIF ファイルを解析して、リポジトリに code scanning アラートを表示できます。 詳細については、「コード スキャン用の SARIF ファイルについて」を参照してください。

この記事では、 GitHubの要件を満たし、有用なアラートに変換できる SARIF ファイルをアップロードするのに役立つ SARIF ファイルの主なプロパティについて説明します。

GitHub ActionsでCodeQL 分析ワークフローを使用している場合、またはCodeQL CLIを使用している場合、code scanningの結果では、サポートされている SARIF 2.1.0 のサブセットが自動的に使用されます。

重複したアラートを防ぐためのデータ

新しいコード スキャンの結果がアップロードされるたびに、結果が処理され、アラートがリポジトリに追加されます。 同じ問題に対する重複アラートを防ぐために、 code scanning はフィンガープリントを使用してさまざまな実行の結果を照合し、選択したブランチの最新の実行に 1 回だけ表示されるようにします。 これにより、ファイルが編集されたときに、アラートを適切なコードの行に照合させることができます。 結果の ruleId は、分析全体で同じである必要があります。

一貫性のあるファイルパス

安定したフィンガープリントの計算を可能にするために、ファイルパスは実行全体で一貫している必要があります。 同じ結果に対してファイルパスが異なる場合、新しい分析が行われるたびに新しいアラートが作成され、古いアラートが閉じられます。 これにより、同じ結果に対して複数のアラートが発生します。

指紋の生成

GitHub では、OASIS 標準の partialFingerprints プロパティを使用して、2 つの結果が論理的に同じであることを検出します。 詳細については、OASIS ドキュメントの partialFingerprints プロパティ エントリを参照してください。

CodeQL 分析ワークフローによって作成された SARIF ファイル、またはCodeQL CLIを使用する SARIF ファイルには、指紋データが含まれます。 upload-sarifアクションを使用して SARIF ファイルをアップロードし、このデータが見つからない場合、GitHubはソース ファイルから partialFingerprints フィールドの設定を試みます。 結果のアップロードの詳細については、「SARIF ファイルを GitHub にアップロードする」を参照してください。

/code-scanning/sarifs API エンドポイントを使用して指紋データなしで SARIF ファイルをアップロードすると、code scanningアラートが処理されて表示されますが、ユーザーに重複したアラートが表示されることがあります。 重複するアラートが表示されないようにするには、SARIF ファイルをアップロードする前に、指紋データを計算し、partialFingerprints プロパティを設定する必要があります。 upload-sarif アクションで便利な始点 https://github.com/github/codeql-action/blob/main/src/fingerprints.ts が使用されるスクリプトが見つかる場合があります。 API について詳しくは、「コード スキャン用の REST API エンドポイント」をご覧ください。

ルールと結果

SARIF ファイルは、ルールと結果の両方をサポートします。 これらの要素に格納されている情報は似ていますが、目的は異なります。

  • ルールは、reportingDescriptor オブジェクトに含まれる toolComponent オブジェクトの配列です。 ここに、分析中に実行されるルールの詳細を格納します。 これらのオブジェクト内の情報は、通常、ツールを更新したときに変更される頻度が低いはずです。
  • 結果は、result オブジェクト内の results の下で、一連の run オブジェクトとして格納されます。 各 result オブジェクトには、コードベース内の 1 つのアラートの詳細が含まれています。 results オブジェクト内で、アラートを検出したルールを参照できます。

異なるコードベースを同じツールとルールで分析して生成された SARIF ファイルを比較すると、分析の結果に違いが見られますが、ルールにはありません。

ソース ファイルの場所

ソース ファイルの場所とコード行を指定すると、特定された問題を含むファイル内にコード スキャン アラートが正確に表示され、対象となる問題の解決が可能になります。

この精度により、コード レビューと解決プロセスの効率が向上し、開発者がコードベースのコンテキストで直接問題に対処できるようにすることで、開発ワークフローを効率化できます。

Code scanning では、アラートで特定されたすべてのコード行がプル リクエストの差分内に存在する場合、プル リクエストのチェック結果にもアラートが表示されます。

pull request チェックに表示するには、アラートが次のすべての条件を満たしている必要があります:

  • アラートによって識別されるすべてのコード行は、アラートの最初の行を含む pull request 差分に存在します。
  • アラートは、削除された行ではなく、pull request で追加または編集されたコード行に存在する必要があります。

送信された SARIF ファイル内の physicalLocation オブジェクトは、アラートのコード行を識別します。 詳細については、「physicalLocation オブジェクト」を参照してください。

ソース ファイルのルートの場所

Code scanning は、相対パスを使用して報告された結果を、分析されたリポジトリのルートに対する相対パスとして解釈します。 結果に絶対 URI が含まれている場合、URI は相対 URI に変換されます。 その後、リポジトリにコミットされたファイルに対して相対 URI を照合できます。

絶対 URI から相対 URI への変換のソース ルートは、次のいずれかの方法で指定できます。

  • checkout_path 入力
  •           SARIF アップロード API エンドポイントに対する `checkout_uri` パラメーター。 詳細については、「[AUTOTITLE](/rest/code-scanning/code-scanning#upload-an-analysis-as-sarif-data)」を参照してください。
    
  • invocations[0].workingDirectory.uri プロパティ

ソース ルートを指定する場合、絶対 URI を使用して指定された成果物の場所では、同じ URI スキームを使用する必要があります。 ソース ルートの URI スキームと 1 つ以上の絶対 URI の間に不一致がある場合、アップロードは拒否されます。

たとえば、SARIF ファイルは file:///github/workspace のソース ルートを使用してアップロードされます。

# Conversion of absolute URIs to relative URIs for location artifacts

file:///github/workspace/src/main.go -> src/main.go
file:///tmp/go-build/tmp.go          -> file:///tmp/go-build/tmp.go

両方の絶対 URI でソース ルートと同じ URI スキームが使用されると、ファイルが正常にアップロードされます。

結果の相対 URI がシンボリック リンクを使用して定義されたファイルと一致した場合、コード スキャンでは結果を表示できません。 したがって、シンボリック リンクされたファイルを解決し、解決された URI を使用してそれらのファイルの結果を報告する必要があります。

ファイルの互換性

SARIF ファイルが code scanning と互換性があるかどうかを確認する場合は、 GitHub インジェスト ルールに対してテストします。 詳細については、Microsoft SARIF 検証ツールを参照してください。

gzip 圧縮の SARIF ファイルごとに、SARIF アップロードでサポートされる最大サイズは 10 MB となります。 この制限を超えるアップロードはすべて拒否されます。 含まれる結果が多すぎるために SARIF ファイルが大きくなりすぎた場合は、最も重要なルールまたはクエリの結果に焦点を当てるように構成を更新する必要があります。 詳細については、「SARIF 結果ファイルが大きすぎる」を参照してください。

Code scanning では、次の表のデータ オブジェクトのエントリの最大数のアップロードがサポートされています。 これらのオブジェクトのいずれかがその最大値を超えている場合、SARIF ファイルは拒否されます。 一部のオブジェクトでは、表示される値の数に追加の制限もあります。 可能な限り、最も重要な値が表示されます。 サポートされている制限を超えるデータが含まれている場合に分析を最大限に活用するには、分析構成を最適化してみてください (たとえば、 CodeQL ツールの場合は、最もノイズの多いクエリを特定して無効にします)。 詳細については、「SARIF 結果が 1 つ以上の制限を超えている」を参照してください。

SARIF データ最大値データ切り捨て制限
ファイルあたりの実行数20なし
実行あたりの結果数25,000重要度による優先順位で、上位 5,000 件の結果のみが含まれます。
実行あたりのルール数25,000なし
実行あたりのツール拡張機能数100なし
結果あたりのスレッド フローの場所数10,000優先順位付けを使用して、上位 1,000 個のスレッド フローの場所のみが含まれます。
結果あたりの場所数1,000100 個の場所のみが含まれます。
ルールあたりのタグ数2010 個のタグのみが含まれます。
アラート制限1,000,000なし

その他のエラーについては、 SARIF アップロードのトラブルシューティング を参照してください。

サポートされているプロパティ

CodeQL以外のコード分析エンジンを使用する場合は、サポートされている SARIF プロパティを確認して、GitHubでの分析結果の表示方法を最適化できます。

メモ

"必須" としてマークされたプロパティには、明示的な値を指定する必要があります。 空の文字列は、必須のプロパティではサポートされていません。

有効な SARIF 2.1.0 出力ファイルはアップロードできますが、 code scanning では、サポートされている次のプロパティのみが使用されます。

sarifLog オブジェクト

名前RequiredDescription
$schemaバージョン 2.1.0 の SARIF JSON スキーマの URI。 たとえば、「 https://json.schemastore.org/sarif-2.1.0.json 」のように入力します。
version
Code scanning では、SARIF バージョンの 2.1.0のみがサポートされます。
runs[]SARIF ファイルには、1 つ以上の実行の配列が含まれています。 各実行は、分析ツールの 1 回の実行を表します。
run の詳細については、「run オブジェクト」を参照してください。

run オブジェクト

Code scanning では、 run オブジェクトを使用してツールで結果をフィルター処理し、結果のソースに関する情報を提供します。 run オブジェクトには、結果を生成したツールに関する情報を含む tool.driver ツール コンポーネント オブジェクトが含まれます。 run ごとに、1 つの分析ツールの結果のみを取得できます。

名前RequiredDescription
tool.driver分析ツールについて説明する toolComponent オブジェクト。 詳細については、「toolComponent オブジェクト」を参照してください。
tool.extensions[]分析中にツールによって使用されるプラグインまたは拡張機能を表す toolComponent オブジェクトの配列。 詳細については、「toolComponent オブジェクト」を参照してください。
invocation.workingDirectory.uriこのフィールドは、 checkout_uri (SARIF アップロード API のみ) または checkout_path (GitHub Actions のみ) が指定されていない場合にのみ使用されます。 この値は、physicalLocation オブジェクトで使用される絶対 URI を相対 URI に変換するために使用されます。 詳しくは、「ソース ファイルのルートの指定」を参照してください。
results[]分析ツールの結果。
Code scanning では、結果が GitHubに表示されます。 詳細については、「result オブジェクト」を参照してください。

toolComponent オブジェクト

名前RequiredDescription
name分析ツールの名前。
Code scanning
GitHubに名前が表示され、ツールで結果をフィルター処理できます。
version分析ツールのバージョン。
Code scanning では、バージョン番号を使用して、分析対象のコードの変更ではなく、ツールのバージョンの変更によって結果が変更された可能性があるタイミングを追跡します。 SARIF ファイルに semanticVersion フィールドが含まれている場合、 version は code scanningでは使用されません。
semanticVersionセマンティック バージョニング 2.0 形式で指定された分析ツールのバージョン。
Code scanning では、バージョン番号を使用して、分析対象のコードの変更ではなく、ツールのバージョンの変更によって結果が変更された可能性があるタイミングを追跡します。 SARIF ファイルに semanticVersion フィールドが含まれている場合、 version は code scanningでは使用されません。 詳細については、セマンティック バージョニング ドキュメントの「セマンティック バージョニング 2.0.0」を参照してください。
rules[]ルールを表す reportingDescriptor オブジェクトの配列。 分析ツールはルールを使用して、分析対象のコードの問題を見つけます。 詳細については、「reportingDescriptor オブジェクト」を参照してください。

reportingDescriptor オブジェクト

ここに、分析中に実行されるルールの詳細を格納します。 これらのオブジェクト内の情報は、通常、ツールを更新したときに変更される頻度が低いはずです。 詳細については、上記の ルールと結果を 参照してください。

名前RequiredDescription
idルールのための一意の識別子。
idは SARIF ファイルの他の部分から参照され、code scanningがGitHubに URL を表示するために使用できます。
nameルールの名前です。
Code scanning には、 GitHubのルールで結果をフィルター処理できるようにするための名前が表示されます。 上限は 255 文字です。
shortDescription.textルールの簡潔な説明。
Code scanning は、関連付けられた結果の横にある GitHub の短い説明を表示します。 上限は 1024 文字です。
fullDescription.textルールの説明。
Code scanning は、関連する結果の横にある GitHub の完全な説明を表示します。 上限は 1024 文字です。
defaultConfiguration.levelルールの既定の重大度レベル。
Code scanning は、重大度レベルを使用して、特定のルールについての結果がどの程度重大かを把握するのに役立ちます。 既定では、defaultConfiguration.levelwarning に設定されています。 ただし、結果に関連付けられている level オブジェクトの result 属性を設定することで、ルールの既定のレベルをオーバーライドできます。 詳細については、result オブジェクトに関するドキュメントを参照してください。
defaultConfiguration.level の有効な値は、notewarningerror です。
help.textテキスト形式を使用したルールのドキュメント。
Code scanning は、関連する結果の横にこのヘルプ ドキュメントを表示します。
help.markdown(推奨) Markdown 形式のルールのドキュメント。
Code scanning は、関連する結果の横にこのヘルプ ドキュメントを表示します。
help.markdown が使用可能な場合は、help.text の代わりに表示されます。
properties.tags[]文字列の配列。
Code scanning では、 tags を使用して、 GitHubの結果をフィルター処理できます。 たとえば、security タグを含むすべての結果をフィルターすることができます。
properties.precision(推奨) このルールによって示される結果が true となる頻度を示す文字列。 たとえば、ルールの誤検知率が高いことがわかっている場合、精度は low である必要があります。
Code scanning は、 GitHub の精度で結果を並べ替え、最も高い levelと最も高い precision の結果が最初に表示されるようにします。
very-highhighmedium、または low のいずれかにすることができます。
properties.problem.severity(推奨) セキュリティ以外のクエリによって生成されたアラートの重大度レベルを示す文字列。 これは、 properties.precision プロパティを使用して、 GitHub で結果を既定で表示するかどうかを決定し、最も高い problem.severityと最も高い precision の結果が最初に表示されるようにします。
errorwarning、または recommendation のいずれかにすることができます。
properties.security-severity(セキュリティ規則にのみ推奨) このフィールドに値を入力すると、ルールの結果はセキュリティの結果として扱われます。 セキュリティ クエリ (@tags には security が含まれる) の重大度のレベル (0.0 より大きく 10.0 まで) を示すスコアを表す文字列。 これは、 properties.precision プロパティを使用して、 GitHub で結果を既定で表示するかどうかを決定し、最も高い security-severityと最も高い precision の結果が最初に表示されるようにします。
Code scanning は数値スコアを次のように変換します。9.0 以上が critical、7.0 から 8.9 が high、4.0 から 6.9 が medium 、0.1 から 3.9 が low。 0.0 または指定された範囲外のその他の値は、セキュリティの重大度がないと見なされます。

result オブジェクト

result オブジェクトには、コードベース内の 1 つのアラートの詳細が含まれています。 results オブジェクト内で、アラートを検出したルールを参照できます。 詳細については、上記の ルールと結果を 参照してください。

名前RequiredDescription
ruleIdルールの一意識別子 (reportingDescriptor.id)。 詳細については、「reportingDescriptor オブジェクト」を参照してください。
Code scanning では、ルール識別子を使用して、 GitHubのルールで結果をフィルター処理します。
ruleIndexツール コンポーネント reportingDescriptor 配列内の関連するルール (rules オブジェクト) のインデックス。 詳細については、「run オブジェクト」を参照してください。 このプロパティに使用できる範囲は 0 から 2^63 - 1 です。
ruleこの結果のルール (レポート記述子) を見つけるために使用される参照。 詳細については、「reportingDescriptor オブジェクト」を参照してください。
level結果の重大度。 このレベルは、ルールで定義されているデフォルトの重要度をオーバーライドします。
Code scanning では、レベルを使用して、 GitHubの重大度で結果をフィルター処理します。
message.text結果を説明するメッセージ。
Code scanning は、結果のタイトルとしてメッセージ テキストを表示します。 表示スペースが限られている場合、メッセージの最初の文のみが表示されます。
locations[]最大 10 個の結果が検出された場所のセット。 指定された場所ごとに変更を加えることでのみ問題を修正できる場合を除き、1 つの場所のみを含める必要があります。
**メモ:**code scanningが結果を表示するには、少なくとも 1 つの場所が必要です。
Code scanning では、このプロパティを使用して、結果で注釈を付けるファイルを決定します。 この配列の最初の値のみが使用されます。 その他の値はすべて無視されます。
partialFingerprints結果の一意の ID を追跡するために使用される文字列のセット。
Code scanning は、partialFingerprints を使用して、コミットやブランチをまたいでどの結果が同一であるかを正確に特定します。
Code scanning は、 partialFingerprints が存在する場合は使用を試みます。 サード パーティーの SARIF ファイルを upload-action でアップロードしているときに partialFingerprints が SARIF ファイルに含まれていない場合は、このアクションで作成されます。 詳しくは、「実行全体でコード スキャン アラートを追跡するデータを提供する」を参照してください。
**注:**Code scanning は、 primaryLocationLineHashのみを使用します。
codeFlows[].threadFlows[].locations[]実行スレッドを介したプログラムの進行状況を記述する、location オブジェクトの threadFlow オブジェクトの配列。
codeFlow オブジェクトは、結果の検出に使用されるコード実行パターンを記述します。 コード フローが指定されている場合、 code scanning は関連する結果の GitHub でコード フローを拡張します。 詳細については、「location オブジェクト」を参照してください。
relatedLocations[]この結果に関連する場所。
Code scanning は、結果メッセージに埋め込まれている関連する場所にリンクします。 詳細については、「location オブジェクト」を参照してください。

location オブジェクト

プログラミングアーティファクト内の場所(リポジトリ内のファイルやビルド中に生成されたファイルなど)。

名前RequiredDescription
location.idこの場所を単一の結果オブジェクト内の他のすべての場所と区別する一意の識別子。 このプロパティに使用できる範囲は 0 から 2^63 - 1 です。
location.physicalLocationアーティファクトとリージョンを識別します。 詳細については、「physicalLocation」を参照してください。
location.message.text場所に関連するメッセージ。

physicalLocation オブジェクト

名前RequiredDescription
artifactLocation.uriアーティファクトの場所を示す URI (通常はリポジトリ内にあるか、ビルド中に生成されたファイル)。 最適な結果を得るには、分析対象のGitHub リポジトリのルートからの相対パスを使用することをお勧めします。 たとえば、「 src/main.js 」のように入力します。 成果物 URI について詳しくは、「ソース ファイルのルートの指定」を参照してください。
region.startLineリージョンの最初の文字の行番号。
region.startColumnリージョンの最初の文字の列番号。
region.endLineリージョンの最後の文字の行番号。
region.endColumnリージョンの末尾に続く文字の列番号。

runAutomationDetails オブジェクト

runAutomationDetails オブジェクトには、実行の ID を指定する情報が含まれています。

名前RequiredDescription
id分析のカテゴリと実行 ID を識別する文字列。 同じツールとコミットに対して、ただし様々な言語やコードの様々な部分にを処理した場合に、複数のSARIFファイルをアップロードする際に使ってください。

runAutomationDetails オブジェクトの使用は省略可能です。

id フィールドには、分析のカテゴリと実行 ID を含めることができます。 id フィールドの実行 ID の部分は使いませんが、保存はされます。

カテゴリを使って、同じツールあるいはコミットに対して行われる、ただし様々な言語やコードの様々な部分に対して行われる複数の分析を区別してください。 実行IDを使って、分析が実行された日付など、特定の分析の実行を識別してください。

idcategory/run-id として解釈されます。 id にスラッシュ (/) が含まれていない場合は、文字列全体が run_id であり、category は空です。 それ以外の場合、category は最後のスラッシュまでの文字列内のすべてであり、run_id はそれ以降のすべてです。

idカテゴリrun_id
my-analysis/tool1/2022-01-02my-analysis/tool12022-01-02
my-analysis/tool1/my-analysis/tool1None
私の分析 ツール1用None私の分析 ツール1用
  • "my-analysis/tool1/2021-02-01" という id での実行は、"my-analysis/tool1" というカテゴリに属します。
  • "my-analysis/tool1/" という id での実行は "my-analysis/tool1" というカテゴリに属しますが、そのカテゴリの他の実行とは区別されません。
  • "my-analysis for tool1" が id の実行は、一意の識別子を持ちますが、いずれかのカテゴリに属していると推定できません。

runAutomationDetails オブジェクトと id フィールドの詳細については、OASIS ドキュメントの「runAutomationDetails オブジェクト」を参照してください。

サポートされている残りのフィールドは無視されることに注意してください。

SARIF 出力ファイルの例

次の例の SARIF 出力ファイルは、サポートされているプロパティと値の例を示しています。

最低限必要なプロパティの例

この SARIF 出力ファイルには、 code scanning 結果が期待どおりに動作するために必要な最小プロパティを示す値の例があります。 プロパティを削除したり、値を省略したり、空の文字列を使用したりすると、このデータは正しく表示されず、 GitHubに同期されません。

{
  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
  "version": "2.1.0",
  "runs": [
    {
      "tool": {
        "driver": {
          "name": "Tool Name",
          "rules": [
            {
              "id": "R01"
                      ...
              "properties" : {
                 "id" : "java/unsafe-deserialization",
                 "kind" : "path-problem",
                 "name" : "...",
                 "problem.severity" : "error",
                 "security-severity" : "9.8",
               }
            }
          ]
        }
      },
      "results": [
        {
          "ruleId": "R01",
          "message": {
            "text": "Result text. This result does not have a rule associated."
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "fileURI"
                },
                "region": {
                  "startLine": 2,
                  "startColumn": 7,
                  "endColumn": 10
                }
              }
            }
          ],
          "partialFingerprints": {
            "primaryLocationLineHash": "39fa2ee980eb94b0:1"
          }
        }
      ]
    }
  ]
}

SARIF プロデューサーの相対 URI ガイダンス

この SARIF 出力ファイルには、相対 URI 参照を使用するときに SARIF プロデューサーが含める必要がある最低限必要なプロパティを示す、フィールド originalUriBaseIds の値の例があります。

メモ

このプロパティは、GitHubの結果を正しく表示するためにcode scanningでは必要ありませんが、相対 URI 参照を使用する場合は有効な SARIF 出力を生成する必要があります。

{
  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
  "version": "2.1.0",
  "runs": [
    {
      "tool": {
        "driver": {
          "name": "Tool Name",
          "rules": [
            {
              "id": "R01"
                      ...
              "properties" : {
                 "id" : "java/unsafe-deserialization",
                 "kind" : "path-problem",
                 "name" : "...",
                 "problem.severity" : "error",
                 "security-severity" : "9.8",
               }
            }
          ]
        }
      },
      "originalUriBaseIds": {
        "PROJECTROOT": {
         "uri": "file:///C:/Users/Mary/code/TheProject/",
           "description": {
             "text": "The root directory for all project files."
           }
        },
         "%SRCROOT%": {
           "uri": "src/",
           "uriBaseId": "PROJECTROOT",
           "description": {
             "text": "The root of the source tree."
           }
         }
      },
      "results": [
        {
          "ruleId": "R01",
          "message": {
            "text": "Result text. This result does not have a rule associated."
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "fileURI",
                  "uriBaseId": "%SRCROOT%"
                },
                "region": {
                  "startLine": 2,
                  "startColumn": 7,
                  "endColumn": 10
                }
              }
            }
          ],
          "partialFingerprints": {
            "primaryLocationLineHash": "39fa2ee980eb94b0:1"
          }
        }
      ]
    }
  ]
}

サポートされているすべての SARIF プロパティを示す例

この SARIF 出力ファイルには、 code scanningでサポートされているすべての SARIF プロパティを示す値の例があります。

{
  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
  "version": "2.1.0",
  "runs": [
    {
      "tool": {
        "driver": {
          "name": "Tool Name",
          "semanticVersion": "2.0.0",
          "rules": [
            {
              "id": "3f292041e51d22005ce48f39df3585d44ce1b0ad",
              "name": "js/unused-local-variable",
              "shortDescription": {
                "text": "Unused variable, import, function or class"
              },
              "fullDescription": {
                "text": "Unused variables, imports, functions or classes may be a symptom of a bug and should be examined carefully."
              },
              "defaultConfiguration": {
                "level": "note"
              },
              "properties": {
                "tags": [
                  "maintainability"
                ],
                "precision": "very-high"
              }
            },
            {
              "id": "d5b664aefd5ca4b21b52fdc1d744d7d6ab6886d0",
              "name": "js/inconsistent-use-of-new",
              "shortDescription": {
                "text": "Inconsistent use of 'new'"
              },
              "fullDescription": {
                "text": "If a function is intended to be a constructor, it should always be invoked with 'new'. Otherwise, it should always be invoked as a normal function, that is, without 'new'."
              },
              "properties": {
                "tags": [
                  "reliability",
                  "correctness",
                  "language-features"
                ],
                "precision": "very-high"
              }
            },
            {
              "id": "R01"
            }
          ]
        }
      },
      "automationDetails": {
        "id": "my-category/"
      },
      "results": [
        {
          "ruleId": "3f292041e51d22005ce48f39df3585d44ce1b0ad",
          "ruleIndex": 0,
          "message": {
            "text": "Unused variable foo."
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "main.js",
                  "uriBaseId": "%SRCROOT%"
                },
                "region": {
                  "startLine": 2,
                  "startColumn": 7,
                  "endColumn": 10
                }
              }
            }
          ],
          "partialFingerprints": {
            "primaryLocationLineHash": "39fa2ee980eb94b0:1",
            "primaryLocationStartColumnFingerprint": "4"
          }
        },
        {
          "ruleId": "d5b664aefd5ca4b21b52fdc1d744d7d6ab6886d0",
          "ruleIndex": 1,
          "message": {
            "text": "Function resolvingPromise is sometimes invoked as a constructor (for example [here](1)), and sometimes as a normal function (for example [here](2))."
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "src/promises.js",
                  "uriBaseId": "%SRCROOT%"
                },
                "region": {
                  "startLine": 2
                }
              }
            }
          ],
          "partialFingerprints": {
            "primaryLocationLineHash": "5061c3315a741b7d:1",
            "primaryLocationStartColumnFingerprint": "7"
          },
          "relatedLocations": [
            {
              "id": 1,
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "src/ParseObject.js",
                  "uriBaseId": "%SRCROOT%"
                },
                "region": {
                  "startLine": 2281,
                  "startColumn": 33,
                  "endColumn": 55
                }
              },
              "message": {
                "text": "here"
              }
            },
            {
              "id": 2,
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "src/LiveQueryClient.js",
                  "uriBaseId": "%SRCROOT%"
                },
                "region": {
                  "startLine": 166
                }
              },
              "message": {
                "text": "here"
              }
            }
          ]
        },
        {
          "ruleId": "R01",
          "message": {
            "text": "Specifying both [ruleIndex](1) and [ruleId](2) might lead to inconsistencies."
          },
          "level": "error",
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "full.sarif",
                  "uriBaseId": "%SRCROOT%"
                },
                "region": {
                  "startLine": 54,
                  "startColumn": 10,
                  "endLine": 55,
                  "endColumn": 25
                }
              }
            }
          ],
          "relatedLocations": [
            {
              "id": 1,
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "full.sarif"
                },
                "region": {
                  "startLine": 81,
                  "startColumn": 10,
                  "endColumn": 18
                }
              },
              "message": {
                "text": "here"
              }
            },
            {
              "id": 2,
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "full.sarif"
                },
                "region": {
                  "startLine": 82,
                  "startColumn": 10,
                  "endColumn": 21
                }
              },
              "message": {
                "text": "here"
              }
            }
          ],
          "codeFlows": [
            {
              "threadFlows": [
                {
                  "locations": [
                    {
                      "location": {
                        "physicalLocation": {
                          "region": {
                            "startLine": 11,
                            "endLine": 29,
                            "startColumn": 10,
                            "endColumn": 18
                          },
                          "artifactLocation": {
                            "uriBaseId": "%SRCROOT%",
                            "uri": "full.sarif"
                          }
                        },
                        "message": {
                          "text": "Rule has index 0"
                        }
                      }
                    },
                    {
                      "location": {
                        "physicalLocation": {
                          "region": {
                            "endColumn": 47,
                            "startColumn": 12,
                            "startLine": 12
                          },
                          "artifactLocation": {
                            "uriBaseId": "%SRCROOT%",
                            "uri": "full.sarif"
                          }
                        }
                      }
                    }
                  ]
                }
              ]
            }
          ],
          "partialFingerprints": {
            "primaryLocationLineHash": "ABC:2"
          }
        }
      ],
      "columnKind": "utf16CodeUnits"
    }
  ]
}