Skip to main content

Esta versión de GitHub Enterprise se discontinuará el 2022-09-28. No se realizarán lanzamientos de patch, ni siquiera para problemas de seguridad críticos. Para obtener rendimiento mejorado, seguridad mejorada y nuevas características, actualice a la versión más reciente de GitHub Enterprise. Para obtener ayuda con la actualización, póngase en contacto con el soporte técnico de GitHub Enterprise.

Soporte de SARIF para escaneo de código

Para mostrar los resultados de una herramienta de análisis estático de terceros en tu repositorio en GitHub, necesitas que éstos se almacenen en un archivo SARIF que sea compatible con un subconjunto del modelo de JSON para SARIF 2.1.0 para el code scanning. Si utilizas el motor de análisis estático predeterminado de CodeQL, tus resultados se mostrarán automáticamente en tu repositorio de GitHub.

Code scanning is available for organization-owned repositories in GitHub Enterprise Server. This feature requires a license for GitHub Advanced Security. Para más información, consulte "Acerca de GitHub Advanced Security".

Acerca del soporte de SARIF

SARIF (Static Analysis Results Interchange Format) es un estándar OASIS que define un formato de archivo de salida. El estándar SARIF se utiliza para optimizar la manera en el que las herramientas de análisis estático comparten sus resultados. Code scanning es compatible con un subconjunto del modelo SARIF 2.1.0 JSON.

Para cargar un archivo SARIF desde un motor de análisis estático de código desde un tercero, necesitaras asegurarte de que los archivos cargados utilicen la versión SARIF 2.1.0. GitHub analizará el archivo SARIF y mostrará las alertas utilizando los resultados en tu repositorio como parte de la experiencia del code scanning. Para obtener más información, consulte "Carga de un archivo SARIF en GitHub." Para obtener más información sobre el esquema de JSON SARIF 2.1.0, consulte sarif-schema-2.1.0.json.

Si estás utilizando GitHub Actions con el CodeQL analysis workflow, con el CodeQL runner, o con el CodeQL CLI, los resultados del code scanning usarán automáticamente el subconjunto compatible de SARIF 2.1.0. Para más información, consulta "Configuración de code scanning para un repositorio", "Ejecución de CodeQL runner en tu sistema de CI", o "Instalación de la CLI de CodeQL en tu sistema de CI".

Puedes cargar varios archivos SARIF para la misma confirmación y mostrar los datos de cada archivo como resultados del code scanning. Cuando cargas varios archivos de SARIF en una confirmación, debes indicar una "Categoría" para cada análisis. La forma de especificar una categoría varía de acuerdo con el método de análisis:

  • Si usa directamente CodeQL CLI, puede enviar el argumento --sarif-category al comando codeql database analyze cuando genere los archivos SARIF. Para obtener más información, consulte "Configuración de la CLI de CodeQL en el sistema de CI".
  • Utilice GitHub Actions con codeql-action/analyze para que la categoría se establezca automáticamente a partir del nombre del flujo de trabajo y las variables de matriz (normalmente, es language). Puede ignorar este ajuste si especifica una entrada en category para la acción, lo cual es útil cuando analiza diferentes secciones de un repositorio único en un flujo de trabajo simple.
  • Si GitHub Actions para cargar los resultados de otras herramientas de análisis estático, debe especificar una entrada en category si carga más de un archivo de resultados para la misma herramienta en un flujo de trabajo. Para obtener más información, consulte "Carga de un análisis de code scanning con GitHub Actions".
  • Si no usa ninguno de estos enfoques, debe especificar un runAutomationDetails.id único en cada archivo SARIF que se va a cargar. Para obtener más información acerca de esta propiedad, consulte Objeto de runAutomationDetails a continuación.

Si cargas un archivo de SARIF para una confirmación con la misma categoría y desde la misma herramienta, los resultados anteriores se sobreescribirán. Sin embargo, si intentas cargar varios archivos SARIF para la misma herramienta y categoría en una ejecución de flujo de trabajo de GitHub Actions sencilla, esta configuración errónea se detectará y la ejecución fallará.

GitHub utiliza propiedades en el archivo SARIF para mostrar alertas. Por ejemplo, shortDescription y fullDescription aparecen en la parte superior de una alerta de code scanning. location permite que GitHub muestre anotaciones en el archivo de código. Para obtener más información, consulte "Administración de alertas de code scanning para el repositorio".

Si no está familiarizado con SARIF y quiere obtener más información, consulte el repositorio SARIF tutorials de Microsoft.

Proporcionar datos para realizar un seguimiento de las alertas de code scanning entre ejecuciones

Cada vez que se cargan los resultados de un nuevo examen de código, los resultados se procesan y se agregan alertas al repositorio. Para prevenir las alertas duplicadas para el mismo problema, code scanning utiliza huellas dactilares para empatara los resultados a través de diversas ejecuciones para que solo aparezcan una vez en la última ejecución para la rama seleccionada. Esto hace posible emparejar las alertas con la línea de código correcta cuando se editan los archivos. El ruleID para un resultado debe ser el mismo en todo el análisis.

Informes de rutas de archivo coherentes

La ruta de acceso de archivo debe ser coherente en las ejecuciones para habilitar un cálculo de una huella digital estable. Si las rutas de archivo difieren para el mismo resultado, cada vez que se crea un nuevo análisis, se creará una nueva alerta y se cerrará la antigua. Esto provocará que haya varias alertas para el mismo resultado.

Inclusión de datos para la generación de huellas digitales

GitHub usa la propiedad partialFingerprints del estándar OASIS para detectar si hay dos resultados idénticos desde el punto de vista lógico. Para obtener más información, consulte la entrada "propiedad partialFingerprints" en la documentación de OASIS.

Los archivos SARIF que crea el CodeQL analysis workflow, con el CodeQL runner, o con el CodeQL CLI incluyen datos de huellas digitales. Si carga un archivo SARIF con la acción upload-sarif y faltan estos datos, GitHub intenta rellenar el campo partialFingerprints a partir de los archivos de origen. Para obtener más información sobre la carga de resultados, consulte "Carga de un archivo SARIF en GitHub."

Si carga un archivo SARIF sin datos de huella digital utilizando el punto de conexión de la API /code-scanning/sarifs, se procesarán y se mostrarán las alertas del code scanning, pero es posible que los usuarios vean alertas duplicadas. Para evitar ver alertas duplicadas, debe calcular los datos de huella digital y rellenar la propiedad partialFingerprints antes de cargar el archivo SARIF. Puede que el script que utiliza la acción upload-sarif le resulte un buen punto de partida: https://github.com/github/codeql-action/blob/main/src/fingerprints.ts. Para obtener más información sobre la API, consulte "Carga de un análisis como datos de SARIF".

Descripción de las reglas y los resultados

Los archivos SARIF admiten reglas y resultados. La información almacenada en estos elementos es similar, pero sirve para diferentes propósitos.

  • Las reglas son una matriz de objetos reportingDescriptor que se incluyen en el objeto toolComponent. Aquí es donde almacenas los detalles de las reglas que se ejecutan durante el análisis. La información de estos objetos debe cambiar con poca frecuencia, normalmente al actualizar la herramienta.

  • Los resultados se almacenan como una serie de objetos result en results en el objeto run. Cada objeto result contiene detalles de una alerta en el código base. Dentro del objeto results, puedes hacer referencia a la regla que ha detectado la alerta.

Al comparar los archivos SARIF generados mediante el análisis de diferentes bases de código con la misma herramienta y las mismas reglas, tendrías que ver diferencias en los resultados de los análisis, pero no en las reglas.

Especificación de la raíz para los archivos de origen

Code scanning interpreta los resultados que se notifican con rutas de acceso relativas en relación con la raíz del repositorio analizado. Si un resultado contiene un URI absoluto, el URI se convierte en un URI relativo. A continuación, el URI relativo se puede emparejar con un archivo confirmado en el repositorio.

Puedes proporcionar la raíz de origen para la conversión de URI absolutos a relativos de una de las siguientes maneras.

  • checkout_path entrada a la github/codeql-action/analyze acción
  • checkout_uri parámetro al punto de conexión de la API de carga de SARIF. Para más información, consulta "Code scanning" en la documentación de la API REST
  • invocation.workingDirectory.uri propiedad en el archivo de SARIF

Si proporciona una raíz de origen, cualquier ubicación de un artefacto especificado mediante un URI absoluto debe usar el mismo esquema de URI. Si hay una discrepancia entre el esquema de URI para la raíz de origen y uno o varios de los URI absolutos, se rechaza la carga.

Por ejemplo, un archivo SARIF se carga mediante una raíz de origen de 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

El archivo se carga correctamente, ya que ambos URI absolutos usan el mismo esquema de URI que la raíz de origen.

Validar tu archivo SARIF

Puedes verificar si un archivo SARIF es compatible con el code scanning si lo pruebas contra las reglas de ingestión de GitHub. Para obtener más información, visite el validador de SARIF de Microsoft.

Notas:

  • La carga de SARIF admite un máximo de 5000 resultados por carga. Los resultados que superen este límite se omiten. Si una herramienta genera demasiados resultados, debe actualizar la configuración para centrarse en los resultados de las reglas o consultas más importantes.

  • Para cada carga, la carga de SARIF admite un tamaño máximo de 10 MB para el archivo SARIF comprimido con gzip. Se rechazarán las cargas que superen este límite. Si el archivo SARIF es demasiado grande porque contiene demasiados resultados, debe actualizar la configuración para centrarse en los resultados de las reglas o consultas más importantes.

Propiedades compatibles de archivo de salida SARIF

Si utilizas un motor de análisis de código diferente a CodeQL, puedes revisar las propiedades SARIF compatibles para optimizar cómo aparecerán los resultados de tu análisis en GitHub.

Nota: Debes proporcionar un valor explícito para cualquier propiedad marcada como "obligatoria". La cadena vacía no se admite para las propiedades necesarias.

Puedes cargar cualquier archivo de salida SARIF 2.1.0 válido, sin embargo, code scanning utilizará únicamente las siguientes propiedades compatibles.

Objecto sarifLog

NombreDescripción
$schemaObligatorio. URI del esquema de JSON SARIF para la versión 2.1.0. Por ejemplo, https://json.schemastore.org/sarif-2.1.0.json.
versionObligatorio. Code scanning solo admite la versión 2.1.0 de SARIF.
runs[]Obligatorio. Un archivo SARIF contiene una matriz de una o varias ejecuciones. Cada ejecución representa una sola ejecución de una herramienta de análisis. Para obtener más información sobre un run, consulte el objeto run.

Objecto run

Code scanning usa el objeto run para filtrar resultados por herramienta y proporcionar información sobre el origen de un resultado. El objeto run contiene el objeto de componente de herramienta tool.driver, que contiene información sobre la herramienta que generó los resultados. Cada run puede tener resultados para una sola herramienta de análisis.

NombreDescripción
tool.driverObligatorio. Un objeto toolComponent que describe la herramienta de análisis. Para obtener más información, consulte el objeto toolComponent.
tool.extensions[]Opcional. Una matriz de objetos toolComponent que representan todos los complementos o extensiones usados por la herramienta durante el análisis. Para obtener más información, consulte el objeto toolComponent.
invocation.workingDirectory.uriOpcional. Este campo solo se usa cuando checkout_uri no se proporcionan (solo API de carga SARIF) o checkout_path (% data variables.product.prodname_actions %} solo). El valor se usa para convertir URI absolutos usados en physicalLocation objetos en URI relativos. Para obtener más información, consulta "Especificar la raíz para los archivos de origen".
results[]Obligatorio. Resultados de la herramienta de análisis. Code scanning muestra los resultados en GitHub. Para obtener más información, consulte el objeto result.

Objecto toolComponent

NombreDescripción
nameObligatorio. Nombre de la herramienta de análisis. Code scanning muestra el nombre en GitHub para permitirte filtrar los resultados por herramienta.
versionOpcional. Versión de la herramienta de análisis. Code scanning utiliza el número de versión para rastrear cuando los resultados pudieran haber cambiado debido al cambio de versión en la herramienta en vez de debido a un cambio del código que se analiza. Si el archivo SARIF incluye el campo semanticVersion, el code scanning no usa version.
semanticVersionOpcional. Versión de la herramienta de análisis, especificada por el formato Versionamiento Semántico 2.0. Code scanning utiliza el número de versión para rastrear cuando los resultados pudieran haber cambiado debido al cambio de versión en la herramienta en vez de debido a un cambio del código que se analiza. Si el archivo SARIF incluye el campo semanticVersion, el code scanning no usa version. Para obtener más información, consulte "Versionamiento Semántico 2.0.0" en la documentación sobre Versionamiento Semántico.
rules[]Obligatorio. Matriz de objetos reportingDescriptor que representan reglas. La herramienta de análisis utiliza reglas para encontrar problemas en el código que se analiza. Para obtener más información, consulte el objeto reportingDescriptor.

Objecto reportingDescriptor

Aquí es donde almacenas los detalles de las reglas que se ejecutan durante el análisis. La información de estos objetos debe cambiar con poca frecuencia, normalmente al actualizar la herramienta. Para obtener más información, consulta "Descripción de las reglas y los resultados" más arriba.

NombreDescripción
idObligatorio. Identificador único para la regla. Al id se hace referencia desde otras secciones del archivo SARIF, y se puede usar en el code scanning para mostrar las URL en GitHub.
nameOpcional. Nombre de la regla. Code scanning muestra el nombre para permitir que se filtren los resultados por regla en GitHub.
shortDescription.textObligatorio. Descripción concisa de la regla. Code scanning muestra la descripción corta en GitHub junto a los resultados asociados.
fullDescription.textObligatorio. Una descripción de la regla. Code scanning muestra la descripción completa en GitHub junto a los resultados asociados. La cantidad máxma de caracteres se limita a 1000.
defaultConfiguration.levelOpcional. Nivel de gravedad predeterminado de la regla. Code scanning utiliza niveles de severidad para ayudarte a entender qué tan crítico es el resultado de una regla. El atributo level del objeto result puede invalidar este valor. Para obtener más información, consulte el objeto result. Predeterminado: warning.
help.textObligatorio. Documentación de la regla con formato de texto. Code scanning muestra esta documentación de ayuda junto a los resultados asociados.
help.markdownOpción recomendada. Documentación de la regla con formato de Markdown. Code scanning muestra esta documentación de ayuda junto a los resultados asociados. Cuando help.markdown está disponible, se muestra en lugar de help.text.
properties.tags[]Opcional. Una matriz de cadenas. Code scanning usa tags para permitirle filtrar resultados en GitHub. Por ejemplo, es posible filtrar todos los resultados que tengan la etiqueta security.
properties.precisionOpción recomendada. Cadena que indica con qué frecuencia se cumplen los resultados indicados por esta regla. Por ejemplo, si una regla tiene una tasa alta de falsos positivos, la precisión debería ser low. Code scanning ordena los resultados de acuerdo con su precisión en GitHub para que aquellos con el level y el precision más altos aparezcan primero. Puede ser very-high, high, medium o low.
properties.problem.severityOpción recomendada. Cadena que indica el nivel de gravedad de las alertas generadas por una consulta que no sea de seguridad. Esto, junto con la propiedad properties.precision, determina si los resultados se muestran de manera predeterminada en GitHub para que los resultados con el problem.severity y el precision más altos aparezcan primero. Puede ser de tipo error, warning o recommendation.
properties.security-severityOpción recomendada. Cadena que representa una puntuación que indica el nivel de gravedad, entre 0,0 y 10,0, de las consultas de seguridad (@tags incluye security). Esto, junto con la propiedad properties.precision, determina si los resultados se muestran de manera predeterminada en GitHub para que los resultados con el security-severity y el precision más altos aparezcan primero. Code scanning traduce las puntuaciones numéricas de la siguiente manera: más de 9,0 escritical, entre 7,0 y 8,9 es high, entre 4,0 y 6,9 es medium y menos de 3,9 o 3,9 es low.

Objecto result

Cada objeto result contiene detalles de una alerta en el código base. Dentro del objeto results, puedes hacer referencia a la regla que ha detectado la alerta. Para obtener más información, consulta "Descripción de las reglas y los resultados" más arriba.

Notas:

  • La carga de SARIF admite un máximo de 5000 resultados por carga. Los resultados que superen este límite se omiten. Si una herramienta genera demasiados resultados, debe actualizar la configuración para centrarse en los resultados de las reglas o consultas más importantes.

  • Para cada carga, la carga de SARIF admite un tamaño máximo de 10 MB para el archivo SARIF comprimido con gzip. Se rechazarán las cargas que superen este límite. Si el archivo SARIF es demasiado grande porque contiene demasiados resultados, debe actualizar la configuración para centrarse en los resultados de las reglas o consultas más importantes.

NombreDescripción
ruleIdOpcional. Identificador único de la regla (reportingDescriptor.id). Para obtener más información, consulte el objeto reportingDescriptor. Code scanning utiliza el identificador de reglas para filtrar los resultados por regla en GitHub.
ruleIndexOpcional. Índice de la regla asociada (objeto reportingDescriptor) en la matriz rules de componentes de herramienta. Para obtener más información, consulte el objeto run. El rango permitido para esta propiedad de 0 to 2^63 - 1.
ruleOpcional. Referencia usada para buscar la regla (descriptor de informes) de este resultado. Para obtener más información, consulte el objeto reportingDescriptor.
levelOpcional. Gravedad del resultado. Este nivel invalida la severidad predeterminada que se define en la regla. Code scanning utiliza el nivel para filtrar los resultados en GitHub por severidad.
message.textObligatorio. Mensaje que describe el resultado. Code scanning muestra el texto del mensaje como el título del resultado. Se mostrará únicamente la primera oración del mensaje cuando el espacio visible esté limitado.
locations[]Obligatorio. Conjunto de ubicaciones donde se detectó el resultado (hasta un máximo de 10). Sólo se deberá incluir una ubicación a menos de que el problema solo pueda corregirse realizando un cambio en cada ubicación especificada. Nota: Se requiere al menos una ubicación para que code scanning muestre el resultado. Code scanning utilizará esta propiedad para decidir qué archivo anotar con el resultado. Únicamente si se utiliza el primer valor de este arreglo. Se ignorará al resto de los otros valores.
partialFingerprintsObligatorio. Conjunto de cadenas usadas para realizar un seguimiento de la identidad única del resultado. Code scanning usa partialFingerprints para identificar con precisión los resultados que son iguales en todas las confirmaciones y ramas. Code scanning intentará usar partialFingerprints si están presentes. Si va a cargar archivos SARIF de terceros con upload-action, la acción creará partialFingerprints automáticamente cuando no se incluyan en el archivo SARIF. Para obtener más información, consulta "Proporcionar datos para realizar un seguimiento de las alertas de análisis de código entre ejecuciones". Nota: Code scanning solo usa primaryLocationLineHash.
codeFlows[].threadFlows[].locations[]Opcional. Matriz de objetos location para un objeto threadFlow, que describe el progreso de un programa a través de un subproceso de ejecución. Un objeto codeFlow describe un patrón de ejecución de código utilizado para detectar un resultado. Si se proporcionan flujos de código, code scanning los expandirá en GitHub para el resultado relevante. Para obtener más información, consulte el objeto location.
relatedLocations[]Un conjunto de ubicaciones relevantes para el resultado. Code scanning vinculará las ubicaciones cuando se incorporen en el mensaje de resultado. Para obtener más información, consulte el objeto location.

Objecto location

Una ubicación dentro de un artefacto de programación, tal como un archivo en el repositorio o un archivo que se generó durante una compilación.

NombreDescripción
location.idOpcional. Identificador único que distingue esta ubicación de todas las demás ubicaciones dentro de un único objeto de resultado. El rango permitido para esta propiedad de 0 to 2^63 - 1.
location.physicalLocationObligatorio. Identifica el artefacto y la región. Para obtener más información, consulte physicalLocation.
location.message.textOpcional. Mensaje relevante para la ubicación.

Objecto physicalLocation

NombreDescripción
artifactLocation.uriObligatorio. URI que indica la ubicación de un artefacto, normalmente un archivo del repositorio o generado durante una compilación. Para obtener los mejores resultados, se recomienda que se trata de una ruta de acceso relativa de la raíz del repositorio de GitHub que se está analizando. Por ejemplo, src/main.js. Para obtener más información sobre los URI de artefacto, consulta "Especificación de la raíz para los archivos de origen".
region.startLineObligatorio. Número de línea del primer carácter de la región.
region.startColumnObligatorio. Número de columna del primer carácter de la región.
region.endLineObligatorio. Número de línea del último carácter de la región.
region.endColumnObligatorio. Número de columna del carácter que sigue al final de la región.

Objecto runAutomationDetails

El objeto runAutomationDetails contiene información que especifica la identidad de una ejecución.

Nota: runAutomationDetails es un objeto de SARIF v2.1.0. Si estás utilizando el CodeQL CLI, puedes especificar la versión de SARIF a utilizar. El objeto equivalente a runAutomationDetails es <run>.automationId para SARIF v1 y <run>.automationLogicalId para SARIF v2.

NombreDescripción
idOpcional. Cadena que identifica la categoría del análisis y el identificador de ejecución. Utilízala si quieres cargar varios archivos SARIF para la misma herramienta y confirmación, pero que se realice en diferentes lenguajes o partes del código.

El uso del objeto runAutomationDetails es opcional.

El campo id puede incluir una categoría de análisis y un identificador de ejecución. No usamos la parte del identificador de ejecución del campo id, pero la almacenamos.

Utiliza la categoría para distinguir entre los diversos análisis de la misma herramienta o confirmación, pero cuando se llevan a cabo en diferentes lenguajes o en partes diferentes del código. Utiliza la ID de ejecución para identificar la ejecución específica del análisis, tal como la fecha en la que este se ejecutó.

id se interpreta como category/run-id. Si id no contiene ninguna barra diagonal (/), la cadena completa es la run_id y la category está vacía. De lo contrario, category será todo lo que aparezca en la cadena hasta la última barra diagonal, y run_id el resto.

idcategoryrun_id
my-analysis/tool1/2021-02-01my-analysis/tool12021-02-01
my-analysis/tool1/my-analysis/tool1no run-id
my-analysis for tool1no categorymy-analysis for tool1
  • La ejecución con un id de "my-analysis/tool1/2021-02-01" pertenece a la categoría "my-analysis/tool1". Supuestamente, esta es la ejecución del 2 de febrero de 2021.
  • La ejecución con un id de "my-analysis/tool1/" pertenece a la cateogría "my-analysis/tool1", pero no se distingue de otras ejecuciones de esa categoría.
  • La ejecución cuyo id es "my-analysis for tool1 " tiene un identificador único, pero no se puede inferir que pertenezca a alguna categoría.

Para obtener más información sobre el objeto runAutomationDetails y el campo id, consulte Objeto runAutomationDetails en la documentación de OASIS.

Nota que el resto de los campos compatibles se ignorarán.

Ejemplos de archivo de salida SARIF

Estos ejemplos de archivos de salida SARIF muestran las propiedades compatibles y los valores de ejemplo.

Ejemplo con las propiedades mínimas requeridas

Este archivo de salida SARIF tiene valores de ejemplo para mostrar las propiedades mínimas requeridas para que los resultados de code scanning funcionen como se espera. Si eliminas cualquier propiedad u omites valores, o si usas una cadena vacía, estos datos no se mostrarán correctamente ni se sincronizarán en 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"
          }
        }
      ]
    }
  ]
}

Ejemplo que muestra todas las propiedades compatibles con SARIF

Este archivo de salida SARIF tiene valores ejemplo para mostrar todas las propiedades de SARIF compatibles con code scanning.

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