Skip to main content

Creación de conjuntos de consultas de CodeQL

Puedes crear conjuntos de consultas para consultas que uses con frecuencia en los análisis de CodeQL.

¿Quién puede utilizar esta característica?

CodeQL está disponible para los siguientes tipos de repositorios:

Acerca de la creación de conjuntos de consultas de CodeQL

Note

En este artículo se describen las características disponibles con el paquete CodeQL CLI 2.17.6 que se incluye en la versión inicial de GitHub Enterprise Server 3.14.

Si el administrador del sitio ha actualizado tu versión de la CodeQL CLI a una versión más reciente, consulta la versión de GitHub Enterprise Cloud de este artículo para obtener información sobre las características más recientes.

Los conjuntos de consultas de CodeQL proporcionan una manera de seleccionar consultas, según su nombre de archivo, ubicación en el disco o en un paquete de CodeQL o propiedades de metadatos. Crea conjuntos de consultas para consultas que quieras usar con frecuencia en los análisis de CodeQL.

Los conjuntos de consultas permiten pasar varias consultas a CodeQL sin tener que especificar la ruta de acceso en cada archivo de consulta individualmente. Las definiciones del conjunto de consultas se almacenan en archivos YAML con la extensión .qls. Una definición de conjuntos es una secuencia de instrucciones, donde cada instrucción es una asignación de YAML que (normalmente) tiene una sola clave. Las instrucciones se ejecutan en el orden en que aparecen en la definición del conjunto de consultas. Una vez ejecutadas todas las instrucciones de la definición del conjunto, el resultado es un conjunto de consultas seleccionadas.

Note

Las consultas personalizadas que quieras agregar a un conjunto de consultas deben estar en un paquete de CodeQL y contener los metadatos de consulta correctos. Para obtener más información, consulta Uso de consultas personalizadas con la CodeQL CLI.

Búsqueda de consultas que se van a agregar a un conjunto de consultas

Al crear un conjunto de consultas, primero debes especificar las ubicaciones de las consultas que quieres seleccionar. Puedes definir la ubicación de una o varias consultas mediante lo siguiente:

  • Una instrucción query: indica a CodeQL que busque uno o varios archivos .ql especificados:

    - query: <path-to-query>
    

    El argumento debe ser una o varias rutas de acceso de archivo, que hagan referencia al paquete de CodeQL que contiene la definición del conjunto.

  • Una instrucción queries: indica a CodeQL que examine de forma recursiva un directorio para los archivos .ql:

    - queries: <path-to-subdirectory>
    

    La ruta de acceso del directorio debe hacer referencia a la raíz del paquete de CodeQL que contiene el archivo de definición del conjunto. Para buscar las consultas que hacen referencia a un paquete de CodeQL, agrega un campo from:

    - queries: <path-to-subdirectory>
      from: <ql-pack-name>
      version: ^x.y.z
    

    El campo version es opcional y especifica un intervalo de versiones compatibles de este paquete de CodeQL. Si no especificas una versión del paquete, se usará la más reciente.

  • Una instrucción qlpack: indica a CodeQL que resuelva las consultas en el conjunto predeterminado del paquete de CodeQL nombrado:

    - qlpack: <qlpack-name>
      version: ^x.y.z
    

    El conjunto predeterminado de un paquete de consultas incluye un conjunto recomendado de consultas dentro de ese paquete de consultas. No todos los paquetes de consultas tienen un conjunto predeterminado. Si el paquete de consultas dado no define un conjunto predeterminado, la instrucción qlpack se resolverá en todas las consultas del paquete.

    El campo version es opcional y especifica un intervalo de versiones compatibles de este paquete de CodeQL. Si no especificas una versión del paquete, se usará la más reciente.

Note

Cuando los nombres de rutas de acceso aparecen en las definiciones del conjunto de consultas, siempre deben llevar una barra diagonal, /, como separador de directorios. Esto garantiza que las definiciones del conjunto de consultas funcionen en todos los sistemas operativos.

Debes agregar al menos una instrucción query, queries o qlpack a la definición del conjunto; de lo contrario, no se seleccionará ninguna consulta. Si el conjunto no contiene más instrucciones, se seleccionan todas las consultas que se encuentran en la lista de archivos, en el directorio especificado o en el paquete de CodeQL nombrado. Si hay instrucciones de filtrado adicionales, solo se seleccionarán las consultas que coincidan con las restricciones que han impuesto esas instrucciones.

Filtrado de las consultas en un conjunto de consultas

Después de definir el conjunto inicial de consultas que se van a agregar al conjunto especificando instrucciones query, queries o qlpack, puedes agregar instrucciones include y exclude. Estas instrucciones definen criterios de selección en función de propiedades específicas:

  • Al ejecutar una instrucción include en un conjunto de consultas, las consultas que coincidan con las condiciones se conservan en la selección y las que no coincidan se quitan.
  • Al ejecutar una instrucción exclude en un conjunto de consultas, las consultas que coincidan con las condiciones se quitan de la selección y las que no coincidan se conservan.

El orden de las instrucciones de filtro es importante. La primera instrucción de filtro que aparece después de las instrucciones de ubicación determina si las consultas se incluyen o excluyen de manera predeterminada. Si el primer filtro es un elemento include, las consultas ubicadas al principio solo formarán parte del conjunto si coinciden con un filtro explícito include. Si el primer filtro es un elemento exclude, las consultas ubicadas al principio forman parte del conjunto a menos que se excluyan de forma explícita.

Las instrucciones posteriores se ejecutan en orden y las instrucciones que aparecen más adelante en el archivo tienen prioridad sobre las instrucciones anteriores. Por lo tanto, las instrucciones include se pueden invalidar mediante instrucciones exclude posteriores que coincidan con la misma consulta. Del mismo modo, un elemento include posterior puede invalidar elementos exclude.

Para ambas instrucciones, el argumento es un bloque de restricciones, es decir, una asignación de YAML que representa las restricciones. Cada restricción es una entrada de la asignación, donde la clave suele ser una propiedad de metadatos de consulta. El valor puede ser lo siguiente:

  • Una sola cadena.
  • Una expresión regular incluida entre /.
  • Una lista que contiene cadenas, expresiones regulares o ambas.

Para que coincida con una restricción, un valor de metadatos debe coincidir con una de las cadenas o expresiones regulares. Cuando hay más de una clave de metadatos, deben coincidir todas las claves. Las claves de metadatos estándar disponibles para establecer coincidencias son: description, id, kind, name, tags, precision y problem.severity. Para obtener más información sobre las propiedades de metadatos de consulta, consulta Metadatos para las consultas de CodeQL.

Además de las etiquetas de metadatos, las claves del bloque de restricciones también pueden ser lo siguiente:

  • query filename: coincide con el último componente de ruta de acceso del nombre de archivo de la consulta.
  • query path: coincide con la ruta de acceso al archivo de la consulta que hace referencia a su paquete de CodeQL contenedor.
  • tags contain: una de las cadenas de coincidencia especificadas debe coincidir con uno de los componentes separados por espacios del valor de la propiedad de metadatos @tags.
  • tags contain all: cada una de las cadenas de coincidencia especificadas debe coincidir con uno de los componentes de la propiedad de metadatos @tags.

Ejemplos de filtrado de las consultas que se van a ejecutan

Un caso de uso común es crear un conjunto de consultas que ejecute todas las consultas de un paquete de CodeQL, excepto algunas consultas específicas que el usuario no quiere ejecutar. Por lo general, se recomienda filtrar por la consulta id, que es un identificador único y estable para cada consulta. Las tres definiciones de conjunto de consultas siguientes son semánticamente idénticas y filtran por la consulta id:

Este filtro coincide con todas las consultas del conjunto predeterminado de codeql/cpp-queries, excepto para las dos consultas con los identificadores excluidos:

- qlpack: codeql/cpp-queries
- exclude:
    id:
      - cpp/cleartext-transmission
      - cpp/cleartext-storage-file

En este ejemplo, se usa una instrucción exclude independiente para cada consulta:

- qlpack: codeql/cpp-queries
- exclude:
    id: cpp/cleartext-transmission
- exclude:
    id: cpp/cleartext-storage-file

En este ejemplo, una expresión regular excluye las mismas dos consultas. También excluiría las consultas futuras agregadas al conjunto con identificadores que comienzan por cpp/cleartext-:

- qlpack: codeql/cpp-queries
- exclude:
    id:
      - /^cpp\/cleartext-.*/

Para definir un conjunto que seleccione todas las consultas del conjunto predeterminado del paquete codeql/cpp-queries de CodeQL y, después, las mejore para incluir solo consultas de seguridad, usa lo siguiente:

- qlpack: codeql/cpp-queries
- include:
    tags contain: security

Para definir un conjunto que seleccione todas las consultas con @kind problem y @precision high desde el directorio my-custom-queries, usa lo siguiente:

- queries: my-custom-queries
- include:
    kind: problem
    precision: very-high

Tenga en cuenta que la definición siguiente del conjunto de consultas se comporta de forma diferente de la definición anterior. Esta definición selecciona las consultas que son @kind problem o @precision very-high:

- queries: my-custom-queries
- include:
    kind: problem
- include:
    precision: very-high

Para crear un conjunto que seleccione todas las consultas con @kind problem desde el directorio my-custom-queries, excepto aquellas que incluyan @problem.severity recommendation, usa lo siguiente:

- queries: my-custom-queries
- include:
    kind: problem
- exclude:
    problem.severity: recommendation

Para crear un conjunto que seleccione todas las consultas con @tag security y @precision high, o very-high, desde el paquete codeql/cpp-queries de CodeQL, usa lo siguiente:

- queries: .
  from: codeql/cpp-queries
- include:
    tags contain: security
    precision:
    - high
    - very-high

Note

Puedes usar el comando codeql resolve queries /path/to/suite.qls para ver qué consultas ha seleccionado una definición de conjunto de consultas. Para más información, consulta resolve queries.

Reutilización de definiciones del conjunto de consultas existente

Las definiciones del conjunto de consultas existente se pueden reutilizar especificando lo siguiente:

  • Una instrucción import: agrega las consultas que ha seleccionado previamente un archivo .qls definido al conjunto actual:

    - import: <path-to-query-suite>
    

    La ruta de acceso al conjunto importado debe hacer referencia al paquete de CodeQL que contiene la definición del conjunto actual. Si el conjunto de consultas importado está en otro paquete de QL, puedes usar lo siguiente:

    - import: <path-to-query-suite>
      from: <ql-pack>
      version: ^x.y.z
    

    El campo version es opcional y especifica un intervalo de versiones compatibles de este paquete de CodeQL. Si no especificas una versión del paquete, se usará la más reciente.

    Las consultas agregadas mediante una instrucción import se pueden filtrar mediante instrucciones exclude posteriores.

  • Una instrucción apply: agrega todas las instrucciones de un archivo .qls definido previamente al conjunto actual. Las instrucciones del archivo .qls aplicado se ejecutan como si aparecieran en lugar de apply. Las instrucciones include y exclude del conjunto aplicado también actúan en las consultas que han agregado instrucciones anteriores:

    - apply: <path-to-query-suite>
    

    La instrucción apply también se puede usar para aplicar un conjunto de condiciones reutilizables, guardadas en un archivo .yml, en varias definiciones de consulta. Para obtener más información, consulta los ejemplos que se indican a continuación.

Ejemplos de reutilización

Para usar las mismas condiciones en varias definiciones del conjunto de consultas, crea un archivo .yml independiente que incluya las instrucciones. Por ejemplo, guarda lo siguiente en un archivo denominado reusable-instructions.yml:

- include:
    kind:
    - problem
    - path-problem
    tags contain: security
    precision:
    - high
    - very-high

Agrega reusable-instructions.yml en el mismo paquete de CodeQL que el conjunto de consultas actual. Después, en uno o varios conjuntos de consultas, usa la instrucción apply para aplicar las instrucciones reutilizables en el conjunto de consultas actual. Por ejemplo:

- queries: queries/cpp/custom
- apply: reusable-instructions.yml

Esto filtrará las consultas en queries/cpp/custom para incluir solo las que coincidan con las condiciones reutilizables.

También puedes crear una definición de conjunto mediante reusable-instructions.yml en consultas en un paquete de CodeQL distinto. Si el archivo .qls está en el mismo paquete de CodeQL que las consultas, puedes agregar un campo from inmediatamente después de la instrucción apply:

# load queries from the default suite of my-org/my-other-custom-queries
- qlpack: my-org/my-other-custom-queries

# apply the reusable instructions from the my-org/my-custom-instructions CodeQL pack
- apply: reusable-instructions.yml
  from: my-org/my-custom-instructions
  version: ^1.2.3 # optional

Un caso de uso común para una instrucción import es aplicar un filtro adicional a las consultas desde otro conjunto de consultas. Por ejemplo, este conjunto filtrará aún más el conjunto cpp-security-and-quality y excluirá las consultas de precisión low y medium:

- import: codeql-suites/cpp-security-and-quality.qls
  from: codeql/cpp-queries
- exclude:
    precision:
      - low
      - medium

Si quieres que las consultas include se importen desde otro conjunto, la sintaxis es un poco diferente:

- import: codeql-suites/cpp-security-and-quality.qls
  from: codeql/cpp-queries
- exclude: {}
- include:
    precision:
      - very-high
      - high

Observe la instrucción exclude vacía. Esto es necesario para garantizar que la instrucción include posterior pueda filtrar las consultas del conjunto importado.

Nomenclatura de un conjunto de consultas

Puedes proporcionar un nombre para el conjunto de consultas especificando una instrucción description:

- description: <name-of-query-suite>

Almacenamiento de un conjunto de consultas

Guarda el conjunto de consultas en un archivo con una extensión .qls y agrégalo a un paquete de CodeQL. Para más información, consulta Personalización del análisis con paquetes de CodeQL.

Uso de conjuntos de consultas con CodeQL

Puedes especificar conjuntos de consultas en la línea de comandos para cualquier comando que acepte archivos .qls. Por ejemplo, puedes compilar las consultas que ha seleccionado una definición de conjunto mediante query compile o bien usar las consultas de un análisis mediante database analyze. Para más información sobre cómo analizar bases de datos de CodeQL, consulta Análisis del código con consultas de CodeQL.

Información adicional