[Ready to ship] Code scanning: Allow upload of multiple SARIF files for 3rd party CI/CD (GA) (#19205)
* made a start * more work * fix typos and add dotcom example SARIF file * start addressing comments * address more comments * addressed more comments * address outstanding comments * Apply suggestions from code review Co-authored-by: Laura Coursen <lecoursen@github.com> Co-authored-by: Marco Gario <marcogario@github.com> * address more comments * Update content/code-security/secure-coding/sarif-support-for-code-scanning.md Co-authored-by: Laura Coursen <lecoursen@github.com> * more improvements * remove run id text * address comment on CodeQL runner * more improvements Co-authored-by: Laura Coursen <lecoursen@github.com> Co-authored-by: Marco Gario <marcogario@github.com>
This commit is contained in:
@@ -3,6 +3,7 @@ title: SARIF support for code scanning
|
||||
shortTitle: SARIF support
|
||||
intro: 'To display results from a third-party static analysis tool in your repository on {% data variables.product.prodname_dotcom %}, you''ll need your results stored in a SARIF file that supports a specific subset of the SARIF 2.1.0 JSON schema for {% data variables.product.prodname_code_scanning %}. If you use the default {% data variables.product.prodname_codeql %} static analysis engine, then your results will display in your repository on {% data variables.product.prodname_dotcom %} automatically.'
|
||||
product: '{% data reusables.gated-features.code-scanning %}'
|
||||
miniTocMaxHeadingLevel: 4
|
||||
redirect_from:
|
||||
- /github/finding-security-vulnerabilities-and-errors-in-your-code/about-sarif-support-for-code-scanning
|
||||
- /github/finding-security-vulnerabilities-and-errors-in-your-code/sarif-support-for-code-scanning
|
||||
@@ -28,6 +29,11 @@ If you're using {% data variables.product.prodname_actions %} with the {% data v
|
||||
{% if currentVersion == "free-pro-team@latest" or currentVersion ver_gt "enterprise-server@3.0" or currentVersion == "github-ae@next" %}
|
||||
If you're using the {% data variables.product.prodname_codeql_cli %}, then you can specify the version of SARIF to use. For more information, see "[Running {% data variables.product.prodname_codeql_cli %} in your CI system](/code-security/secure-coding/running-codeql-cli-in-your-ci-system#uploading-results-to-github)."{% endif %}
|
||||
|
||||
{% if currentVersion == "free-pro-team@latest" %}
|
||||
You can upload multiple SARIF files for the same tool and commit, and analyze each file using {% data variables.product.prodname_code_scanning %}. You can indicate a "category" for each analysis by specifying a `runAutomationDetails.id` in each file. Only SARIF files with the same category will overwrite each other. For more information about this property, see [`runAutomationDetails` object](#runautomationdetails-object) below.
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% data variables.product.prodname_dotcom %} uses properties in the SARIF file to display alerts. For example, the `shortDescription` and `fullDescription` appear at the top of a {% data variables.product.prodname_code_scanning %} alert. The `location` allows {% data variables.product.prodname_dotcom %} to show annotations in your code file. For more information, see "[Managing {% data variables.product.prodname_code_scanning %} alerts for your repository](/code-security/secure-coding/managing-code-scanning-alerts-for-your-repository)."
|
||||
|
||||
If you're new to SARIF and want to learn more, see Microsoft's [`SARIF tutorials`](https://github.com/microsoft/sarif-tutorials) repository.
|
||||
@@ -126,6 +132,45 @@ A location within a programming artifact, such as a file in the repository or a
|
||||
| `region.endLine` | **Required.** The line number of the last character in the region.
|
||||
| `region.endColumn` | **Required.** The column number of the character following the end of the region.
|
||||
|
||||
{% if currentVersion == "free-pro-team@latest" %}
|
||||
#### `runAutomationDetails` object
|
||||
|
||||
The `runAutomationDetails` object contains information that specifies the identity of a run.
|
||||
|
||||
{% note %}
|
||||
|
||||
**Note:** `runAutomationDetails` is a SARIF v2.1.0 object. If you're using the {% data variables.product.prodname_codeql_cli %}, you can specify the version of SARIF to use. The equivalent object to `runAutomationDetails` is `<run>.automationId` for SARIF v1 and `<run>.automationLogicalId` for SARIF v2.
|
||||
|
||||
{% endnote %}
|
||||
|
||||
| Name | Description |
|
||||
|----|----|
|
||||
| `id`| **Optional.** A string that identifies the category of the analysis and the run ID. Use if you want to upload multiple SARIF files for the same tool and commit, but performed on different languages or different parts of the code. |
|
||||
|
||||
The use of the `runAutomationDetails` object is optional.
|
||||
|
||||
The `id` field can include an analysis category and a run ID. We don't use the run ID part of the `id` field, but we store it.
|
||||
|
||||
Use the category to distinguish between multiple analyses for the same tool or commit, but performed on different languages or different parts of the code. Use the run ID to identify the specific run of the analysis, such as the date the analysis was run.
|
||||
|
||||
`id` is interpreted as `category/run-id`. If the `id` contains no forward slash (`/`), then the entire string is the `run_id` and the `category` is empty. Otherwise, `category` is everything in the string until the last forward slash, and `run_id` is everything after.
|
||||
|
||||
| `id` | category | `run_id` |
|
||||
|----|----|----|
|
||||
| my-analysis/tool1/2021-02-01 | my-analysis/tool1 | 2021-02-01
|
||||
| my-analysis/tool1/ | my-analysis/tool1 | _no `run-id`_
|
||||
| my-analysis for tool1 | _no category_ | my-analysis for tool1
|
||||
|
||||
- The run with an `id` of "my-analysis/tool1/2021-02-01" belongs to the category "my-analysis/tool1". Presumably, this is the run from February 2, 2021.
|
||||
- The run with an `id` of "my-analysis/tool1/" belongs to the category "my-analysis/tool1" but is not distinguished from other runs in that category.
|
||||
- The run whose `id` is "my-analysis for tool1 " has a unique identifier but cannot be inferred to belong to any category.
|
||||
|
||||
For more information about the `runAutomationDetails` object and the `id` field, see [runAutomationDetails object](https://docs.oasis-open.org/sarif/sarif/v2.1.0/cs01/sarif-v2.1.0-cs01.html#_Toc16012479) in the OASIS documentation.
|
||||
|
||||
Note that the rest of the supported fields are ignored.
|
||||
|
||||
{% endif %}
|
||||
|
||||
### SARIF output file examples
|
||||
|
||||
These example SARIF output files show supported properties and example values.
|
||||
@@ -134,7 +179,6 @@ These example SARIF output files show supported properties and example values.
|
||||
|
||||
This SARIF output file has example values to show the minimum required properties for {% data variables.product.prodname_code_scanning %} results to work as expected. If you remove any properties or don't include values, this data will not be displayed correctly or sync on {% data variables.product.prodname_dotcom %}.
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
|
||||
@@ -185,6 +229,260 @@ This SARIF output file has example values to show the minimum required propertie
|
||||
|
||||
This SARIF output file has example values to show all supported SARIF properties for {% data variables.product.prodname_code_scanning %}.
|
||||
|
||||
{% if currentVersion == "free-pro-team@latest" %}
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-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"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
{% else %}
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
|
||||
@@ -434,3 +732,4 @@ This SARIF output file has example values to show all supported SARIF properties
|
||||
]
|
||||
}
|
||||
```
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user