Esta versão do GitHub Enterprise foi descontinuada em 2021-09-23. Nenhum lançamento de patch será feito, mesmo para questões críticas de segurança. Para obter melhor desempenho, melhorar a segurança e novos recursos, upgrade to the latest version of GitHub Enterprise. Para ajuda com a atualização, contact GitHub Enterprise support.

Suporte SARIF para a varredura de código

Para exibir os resultados de uma ferramenta de análise estática de terceiros no seu repositório no GitHub, você precisará dos resultados armazenados em um arquivo SARIF que seja compatível com um subconjunto específico do esquema SARIF 2.1.0 JSON para varredura de código. Se você usar o mecanismo de análise estática padrão do CodeQL, os resultados aparecerão automaticamente no seu repositório no GitHub.

Varredura de código está disponível se você tiver uma licença para Segurança Avançada GitHub.

Observação: Varredura de código está em beta em GitHub Enterprise Server 2.22. Para a versão geralmente disponível do varredura de código, atualize para a versão mais recente de GitHub Enterprise Server.

Sobre o suporte SARIF

SARIF (Formato de Intercâmbio de Resultados de Análise Estática) é um OASIS Padrão que define um formato do arquivo de saída. O padrão SARIF é usado para simplificar como as ferramentas de análise estáticas compartilham seus resultados. O Varredura de código é compatível com um subconjunto do esquema SARIF 2.1.0 JSON.

Para fazer o upload de um arquivo SARIF a partir de um mecanismo de análise de código estático de terceiros, você deverá garantir que os arquivos carregados usem a versão SARIF 2.1.0. Para fazer o upload de um arquivo SARIF a partir de um mecanismo de análise de código estático de terceiros, você deverá garantir que os arquivos carregados usem a versão SARIF 2.1.0. Para obter mais informações, consulte "Enviar um arquivo SARIF para o GitHub". Para obter mais informações sobre o esquema SARIF 2.1.0 JSON, consulte sarif-schema-2.1.0.json.

Se o seu arquivo SARIF não incluir partialFingerprints, o campo partialFingerprints será calculado quando você fizer o upload do arquivo SARIF usando GitHub Actions. Para mais informações, consulte "Configurar Varredura de código para um repositório" ou "Executar CodeQL Varredura de código no seu sistema de CI".

GitHub usa propriedades no arquivo SARIF para exibir alertas. Por exemplo, shortDescription e fullDescription aparecem na parte superior de um alerta de Varredura de código. O local permite que GitHub mostre anotações no seu arquivo de código. Para obter mais informações, consulte "Gerenciar alertas de Varredura de código para o seu repositório".

Se você for novo no SARIF e quiser saber mais, consulte o repositório da Microsoft deTutoriais do SARIF.

Impedir alertas duplicados usando impressões digitais

Cada vez que um fluxo de trabalho do GitHub Actions executa uma nova varredura de código, os resultados de cada execução são processados e os alertas são adicionados ao repositório. Para evitar alertas duplicados para o mesmo problema, Varredura de código usa impressões digitais para corresponder aos resultados em várias execuções, para que apareçam apenas uma vez na última execução do ramo selecionado. Isto torna possível combinar alertas com a linha de código correta quando os arquivos são editados.

GitHub uses the partialFingerprints property in the OASIS standard as an input in the computation of whether two results are logically identical. Specifically, the primaryLocationLineHash is used as a stable intra-file location, which is combined with the repository, file path, and rule data to form the full identity. Para obter mais informações, consulte a entrada "partialFingerprints property" na documentação do OASIS.

OS arquivos do SARIF criados pelo Fluxo de trabalho de análise do CodeQL ou usando Executor do CodeQL incluem dados de impressão digital. Se você enviar um arquivo SARIF usando a ação upload-sarif e estes dados estiverem faltando, GitHub tenta preencher o campo partialFingerprints a partir dos arquivos de origem. Para obter mais informações sobre o upload de resultados, consulte "Fazer o upload de um arquivo SARIF para o GitHub".

Se o seu arquivo SARIF não incluir partialFingerprints, o campo partialFingerprints será calculado quando você fizer o upload do arquivo SARIF usando GitHub Actions. Para evitar ver alertas duplicados, você deve calcular dados de impressão digital e preencher a propriedade partialFingerprints antes de enviar o arquivo SARIF. Você pode encontrar o script que a ação upload-sarif usa como um ponto inicial útil: https://github.com/github/codeql-action/blob/main/src/fingerprints.ts. Para obter mais informações sobre a API, consulte "Fazer o upload de uma análise como dados do SARIF".

Validar seu arquivo SARIF

Você pode marcar um arquivo SARIF compatível com Varredura de código testando-o com as regras de ingestão de GitHub. Para obter mais informações, acesse o validador do Microsoft SARIF.

Notas:

  • SARIF upload supports a maximum of 1000 results per upload. Todos os resultados acima deste limite são ignorados. Se uma ferramenta gerar muitos resultados, você deverá atualizar a configuração para focar nos resultados para as regras ou consultas mais importantes.

  • For each upload, SARIF upload supports a maximum size of 10 MB for the gzip-compressed SARIF file. Any uploads over this limit will be rejected. If your SARIF file is too large because it contains too many results, you should update the configuration to focus on results for the most important rules or queries.

Propriedades compatíveis do arquivo de saída SARIF

Se você usar um mecanismo de análise de código diferente de CodeQL, você poderá revisar as propriedades do SARIF compatíveis para otimizar como seus resultados de análise aparecerão em GitHub.

É possível fazer o upload de qualquer arquivo de saída SARIF 2.1.0 válido, no entanto, Varredura de código usará apenas as seguintes propriedades compatíveis.

Objeto sarifLog

NomeDescrição
$schemaObrigatório. A URI do esquema SARIF JSON para a versão 2.1.0. Por exemplo, https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json.
versãoObrigatório. Varredura de código é compatível apenas com a versão 2.1.0 do SARIF.
runs[]Obrigatório. Um arquivo SARIF contém um array de uma ou mais execuções. Cada execução representa uma execução única de uma ferramenta de análise. Para obter mais informações sobre uma execução, consulte o objeto executar.

Objeto run

O Varredura de código usa o objeto executar para filtrar resultados por ferramenta e fornecer informações sobre a fonte de um resultado. O objeto executar contém o objeto tool.driver do componente da ferramenta, que contém informações sobre a ferramenta que gerou os resultados. Cada execução pode ter resultados apenas para uma ferramenta de análise.

NomeDescrição
tool.driver.nameObrigatório. O nome da ferramenta de análise. Varredura de código exibe o nome em GitHub para permitir que você filtre resultados por ferramenta.
tool.driver.versionOpcional. A versão da ferramenta de análise. O Varredura de código usa o número da versão para fazer o monitoramento quando os resultados podem ter mudado devido a uma mudança na versão da ferramenta em vez de uma mudança no código que está sendo analisado. Se o arquivo SARIF incluir o campo semanticVersion, Varredura de código não usará versão.
tool.driver.semanticVersionOpcional. A versão da ferramenta de análise especificada pelo formato Semantic Versioning 2.0. O Varredura de código usa o número da versão para fazer o monitoramento quando os resultados podem ter mudado devido a uma mudança na versão da ferramenta em vez de uma mudança no código que está sendo analisado. Se o arquivo SARIF incluir o campo semanticVersion, Varredura de código não usará versão. Para obter mais informações, consulte "Semantic Versioning 2.0.0" na documentação de Semantic Versioning.
tool.driver.rules[]Obrigatório. Um array de objetos reportingDescriptor que representam regras. A ferramenta de análise usa regras para encontrar problemas no código que está sendo analisado. Para obter mais informações, consulte o objeto reportingDescriptor.
results[]Obrigatório. Os resultados da ferramenta de análise. Varredura de código exibe os resultados em GitHub. Para obter mais informações, consulte o objeto resultado.

Objeto reportingDescriptor

NomeDescrição
idObrigatório. Um identificador exclusivo para a regra. O id `` é referenciado a partir de outras partes do arquivo SARIF e pode ser usado por Varredura de código para exibir URLs em GitHub.
nameOpcional. O nome da regra. Varredura de código exibe o nome para permitir que os resultados sejam filtrados pela regra em GitHub.
shortDescription.textObrigatório. Uma descrição concisa da regra. Varredura de código exibe a breve descrição em GitHub ao lado dos resultados associados.
fullDescription.textObrigatório. Uma descrição da regra. Varredura de código exibe a descrição completa em GitHub ao lado dos resultados associados. O número máximo de caracteres é 1000.
defaultConfiguration.levelOpcional. Gravidade-padrão da regra. Varredura de código usa níveis de gravidade para ajudar você a entender quão crítico é o resultado para uma determinada regra. Esse valor pode ser substituído pelo atributo de nível no objeto resultado. Para obter mais informações, consulte o objeto resultado. Padrão: alerta.
help.textObrigatório. Documentação para a regra usando o formato de texto. O Varredura de código exibe essa documentação de ajuda ao lado dos resultados associados.
help.markdownRecomendado. Documentação para a regra que o formato Markdown. O Varredura de código exibe essa documentação de ajuda ao lado dos resultados associados. Quando help.markdown estiver disponível, será exibido em vez de help.text.
properties.tags[]Opcional. Um array de strings. Varredura de código usa tags para permitir que você filtre resultados em GitHub. Por exemplo, é possível filtrar para todos os resultados que têm a tag segurança.
properties.precisionRecomendado. Uma string que indica quantas vezes os resultados indicados por esta regra são verdadeiros. Por exemplo, se uma regra tem uma alta taxa conhecida de falsos-positivos, a precisão deve ser baixa. Varredura de código ordena os resultados por precisão em GitHub de modo que os resultados com o mais alto nível e a mais alta precisão sejam exibidos primeiro. Pode ser: very-high, high, medium ou low.

Objeto resultado

Notas:

  • SARIF upload supports a maximum of 1000 results per upload. Todos os resultados acima deste limite são ignorados. Se uma ferramenta gerar muitos resultados, você deverá atualizar a configuração para focar nos resultados para as regras ou consultas mais importantes.

  • For each upload, SARIF upload supports a maximum size of 10 MB for the gzip-compressed SARIF file. Any uploads over this limit will be rejected. If your SARIF file is too large because it contains too many results, you should update the configuration to focus on results for the most important rules or queries.

NomeDescrição
ruleIdOpcional. O identificador exclusivo da regra (reportingDescriptor.id). Para obter mais informações, consulte o objeto reportingDescriptor. Varredura de código usa o identificador da regra para filtrar os resultados por regra em GitHub.
ruleIndexOpcional. O índice da regra associada (objeto reportingDescriptor) no array regras no componente da ferramenta. Para obter mais informações, consulte o objeto executar.
ruleOpcional. Uma referência usada para localizar a regra (descritor de relatório) para este resultado. Para obter mais informações, consulte o objeto reportingDescriptor.
levelOpcional. A gravidade do resultado. Esse nível sobrepõe a severidade-padrão definida pela regra. Varredura de código usa o nível para filtrar resultados por gravidade em GitHub.
message.textObrigatório. Uma mensagem que descreve o resultado. Varredura de código exibe o texto da mensagem como o título do resultado. Apenas a primeira frase da mensagem será exibida quando o espaço visível for limitado.
locations[]Obrigatório. O conjunto de locais onde o resultado foi detectado até o máximo de 10. Só um local deve ser incluído, a não ser que o problema só possa ser corrigido fazendo uma alteração em cada local especificado. Observação: Pelo menos um local é necessário para Varredura de código apresentar um resultado. Varredura de código usará essa propriedade para decidir qual arquivo fazer anotações com o resultado. Apenas o primeiro valor desse array é usado. Todos os outros valores são ignorados.
partialFingerprintsObrigatório. Um conjunto de strings usado para rastrear a identidade única do resultado. Varredura de código uses partialFingerprints as part of the computation to accurately identify which results are the same across commits and branches. O Varredura de código tentará usar partialFingerprints, se existirem. Se você estiver fazendo upload de arquivos SARIF de terceiros com upload-action, a ação irá criar partialFingerprints para você quando não estiverem incluídos no arquivo SARIF. Para obter mais informações, consulte "Prevenir alertas duplicados usando impressões digitais". Observação: Varredura de código usa apenas primaryLocationLineHash.
codeFlows[].threadFlows[].locations[]Opcional. Uma array de objetos local para um objeto threadFlow, que descreve o progresso de um programa por meio de um thread de execução. Um objeto codeFlow descreve um padrão de execução de código usado para detectar um resultado. Se forem fornecidos fluxos de código, Varredura de código irá expandir os fluxos de código em GitHub para o resultado relevante. Para obter mais informações, consulte o objeto local.
relatedLocations[]Um conjunto de locais relevantes para este resultado. Varredura de código irá vincular a locais relacionados quando forem incorporados à mensagem do resultado. Para obter mais informações, consulte o objeto local.

Objeto local

Um local dentro de um artefato de programação, como, por exemplo, um arquivo no repositório ou um arquivo gerado durante uma criação.

NomeDescrição
location.idOpcional. Um identificador exclusivo que distingue este local de todos os outros locais dentro de um único objeto de resultado.
location.physicalLocationObrigatório. Identifica o artefato e a região. Para obter mais informações, consulte physicalLocation.
location.message.textOpcional. Uma mensagem relevante para o local.

Objeto physicalLocation

NomeDescrição
artifactLocation.uriObrigatório. Um URI indicando o local de um artefato, geralmente um arquivo no repositório ou gerado durante uma criação. Se o URI for relativo, ele deverá ser relativo à raiz do repositório do GitHub que está sendo analisado. Por exemplo, main.js ou src/script.js são relativos à raiz do repositório. Se o URI for absoluto, o Varredura de código poderá usar o URI para fazer checkout do artefato e corresponder os arquivos no repositório. Por exemplo, https://github.com/ghost/example/blob/00/src/promiseUtils.js.
region.startLineObrigatório. O número da linha do primeiro caractere na região.
region.startColumnObrigatório. O número da coluna do primeiro caractere na região.
region.endLineRequerido. O número da linha do último caractere na região.
region.endColumnObrigatório. O número da coluna do caractere após o final da região.

Exemplos de arquivos de saída SARIF

Estes exemplos de arquivos de saída SARIF mostram as propriedades compatíveis e os valores de exemplo.

Exemplo com as propriedades mínimas necessárias

Este arquivo de saída SARIF tem exemplo de valores para mostrar as propriedades mínimas necessárias para que os resultados de Varredura de código funcionem conforme esperado. Se você remover qualquer propriedade ou não incluir valores, esses dados não serão exibidos corretamente e não serão sincronizados em GitHub.

{
  "$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",
          "rules": [
            {
              "id": "R01"
            }
          ]
        }
      },
      "results": [
        {
          "ruleId": "R01",
          "message": {
            "text": "Result text. Este resultado não tem nenhuma regra associada."
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "fileURI"
                },
                "region": {
                  "startLine": 2,
                  "startColumn": 7,
                  "endColumn": 10
                }
              }
            }
          ],
          "partialFingerprints": {
            "primaryLocationLineHash": "39fa2ee980eb94b0:1"
          }
        }
      ]
    }
  ]
}

Exemplo que mostra todas as propriedades compatíveis como SARIF

Este arquivo de saída SARIF tem valores de exemplo para mostrar todas as propriedades do SARIF compatíveis com Varredura de código.

{
  "$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"
            }
          ]
        }
      },
      "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"
    }
  ]
}