Skip to main content

Erstellen von CodeQL-Abfragesammlungen

Du kannst Abfragesammlungen für Abfragen erstellen, die du häufig in deinen CodeQL-Analysen verwendest.

Wer kann dieses Feature verwenden?

GitHub CodeQL wird nach der Installation auf Benutzerbasis lizenziert. Du kannst CodeQL nur für bestimmte Aufgaben unter den Lizenzeinschränkungen verwenden. Weitere Informationen findest du unter Informationen zur CodeQL-CLI.

Wenn du über eine GitHub Advanced Security-Lizenz verfügst, kannst du CodeQL für eine automatisierte Analyse sowie für Continuous Integration und Continuous Delivery verwenden. Weitere Informationen findest du unter Informationen zu GitHub Advanced Security.

Informationen zum Erstellen von CodeQL-Abfragesammlungen

CodeQL-Abfragesammlungen bieten eine Möglichkeit, Abfragen basierend auf ihrem Dateinamen, Speicherort auf dem Datenträger oder in einem CodeQL-Paket oder Metadateneigenschaften auszuwählen. Erstelle Abfragesammlungen für die Abfragen, die du häufig in deinen CodeQL-Analysen verwenden möchtest.

Abfragesammlungen ermöglichen es dir, mehrere Abfragen an CodeQL zu übergeben, ohne den Pfad zu jeder Abfragedatei einzeln angeben zu müssen. Abfragesammlungsdefinitionen werden in YAML-Dateien mit der Erweiterung .qls gespeichert. Eine Sammlungsdefinition ist eine Sequenz von Anweisungen, wobei jede Anweisung eine YAML-Zuordnung mit (normalerweise) einem einzelnen Schlüssel ist. Die Anweisungen werden in der Reihenfolge ausgeführt, in der sie in der Abfragesammlungsdefinition vorliegen. Nachdem alle Anweisungen in der Sammlungsdefinition ausgeführt wurden, ist das Ergebnis ein Satz ausgewählter Abfragen.

Hinweis: Alle benutzerdefinierten Abfragen, die du einer Abfragesammlung hinzufügen möchtest, müssen sich in einem CodeQL-Paket befinden und die richtigen Abfragemetadaten enthalten. Weitere Informationen findest du unter Verwenden benutzerdefinierter Abfragen mit der CodeQL CLI.

Suchen nach Abfragen, die einer Abfragesammlung hinzugefügt werden sollen

Beim Erstellen einer Abfragesammlung musst du zunächst die Speicherorte der Abfragen angeben, die du auswählen möchtest. Du kannst Folgendes verwenden, um den Speicherort einer oder mehrerer Abfragen zu definieren:

  • query-Anweisung: CodeQL wird angewiesen, nach einer oder mehreren angegebenen .ql-Dateien zu suchen:

    - query: <path-to-query>
    

    Das Argument muss einem oder mehreren Dateipfaden entsprechen, relativ zum CodeQL-Paket, das die Sammlungsdefinition enthält.

  • queries-Anweisung: CodeQL wird angewiesen, ein Verzeichnis rekursiv auf .ql-Dateien zu überprüfen:

    - queries: <path-to-subdirectory>
    

    Der Pfad des Verzeichnisses muss relativ zum Stamm des CodeQL-Pakets sein, das die Sammlungsdefinitionsdatei enthält. Um die Abfragen relativ zu einem anderen CodeQL-Paket zu finden, füge ein from-Feld hinzu:

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

    Das version-Feld ist optional und gibt einen Bereich kompatibler Versionen dieses CodeQL-Pakets an. Wenn du keine Version angibst, wird die aktuellste Version des Pakets verwendet.

  • qlpack-Anweisung: CodeQL wird angewiesen, Abfragen in der Standardsammlung des genannten CodeQL-Pakets aufzulösen:

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

    Die Standardsammlung eines Abfragepakets enthält eine empfohlene Gruppe von Abfragen innerhalb dieses Abfragepakets. Nicht alle Abfragepakete verfügen über eine Standardsammlung. Wenn das angegebene Abfragepaket keine Standardsammlung definiert, wird die qlpack-Anweisung in alle Abfragen innerhalb des Pakets aufgelöst.

    Das version-Feld ist optional und gibt einen Bereich kompatibler Versionen dieses CodeQL-Pakets an. Wenn du keine Version angibst, wird die aktuellste Version des Pakets verwendet.

Hinweis: Wenn Pfadnamen in Abfragesammlungsdefinitionen angezeigt werden, müssen sie immer mit einem Schrägstrich (/) als Verzeichnistrennzeichen angegeben werden. Dadurch wird sichergestellt, dass Abfragesammlungsdefinitionen auf allen Betriebssystemen funktionieren.

Du musst deiner Sammlungsdefinition mindestens eine query-, queries- oder qlpack-Anweisung hinzufügen, da andernfalls keine Abfragen ausgewählt werden. Wenn die Sammlung keine weiteren Anweisungen enthält, werden alle Abfragen ausgewählt, die in der Liste der Dateien, im angegebenen Verzeichnis oder im genannten CodeQL-Paket gefunden werden. Wenn weitere Filteranweisungen vorhanden sind, werden nur Abfragen ausgewählt, die den durch diese Anweisungen auferlegten Einschränkungen entsprechen.

Filtern der Abfragen in einer Abfragesammlung

Nachdem du durch Angeben von query-, queries- oder qlpack-Anweisungen die anfänglichen Abfragen definiert hast, die deiner Sammlung hinzugefügt werden sollen, kannst du include- und exclude-Anweisungen hinzufügen. Diese Anweisungen definieren Auswahlkriterien basierend auf bestimmten Eigenschaften:

  • Wenn du eine include-Anweisung für eine Reihe von Abfragen ausführst, werden alle Abfragen, die deinen Bedingungen entsprechen, in der Auswahl beibehalten, und Abfragen, die nicht übereinstimmen, werden entfernt.
  • Wenn du eine exclude-Anweisung für eine Reihe von Abfragen ausführst, werden alle Abfragen, die deinen Bedingungen entsprechen, aus der Auswahl entfernt, und Abfragen, die nicht übereinstimmen, werden beibehalten.

Die Reihenfolge deiner Filteranweisungen ist wichtig. Die erste Filteranweisung, die nach den Suchanweisungen angezeigt wird, bestimmt, ob die Abfragen standardmäßig ein- oder ausgeschlossen werden. Wenn der erste Filter include entspricht, sind die anfänglich gefundenen Abfragen nur dann Teil der Sammlung, wenn sie mit einem expliziten include-Filter übereinstimmen. Wenn der erste Filter exclude entspricht, sind die anfänglich gefundenen Abfragen Teil der Sammlung, es sei denn, sie werden explizit ausgeschlossen.

Nachfolgende Anweisungen werden in der angegebenen Reihenfolge ausgeführt, und Anweisungen, die später in der Datei erscheinen, haben Vorrang vor den vorherigen Anweisungen. include-Anweisungen können daher von späteren exclude-Anweisungen überschrieben werden, die mit derselben Abfrage übereinstimmen. Ebenso kann eine exclude-Anweisung von einer späteren include-Anweisung überschrieben werden.

Für beide Anweisungen ist das Argument ein Einschränkungsblock, also eine YAML-Zuordnung, die die Einschränkungen darstellt. Jede Einschränkung ist ein Zuordnungseintrag, wobei der Schlüssel in der Regel eine Abfragemetadateneigenschaft ist. Der Wert kann Folgendes sein:

  • Eine einzelne Zeichenfolge
  • Ein in / eingeschlossener regulärer Ausdruck
  • Eine Liste mit Zeichenfolgen, regulären Ausdrücken oder beidem

Um einer Einschränkung zu entsprechen, muss ein Metadatenwert mit einer der Zeichenfolgen oder einem der regulären Ausdrücke übereinstimmen. Wenn mehrere Metadatenschlüssel vorhanden sind, muss jeder Schlüssel abgeglichen werden. Dies sind die verfügbaren Standardmetadatenschlüssel: description, id, kind, name, tags, precision und problem.severity. Weitere Informationen zu Abfragemetadateneigenschaften findest du unter Metadaten für CodeQL-Abfragen.

Zusätzlich zu Metadatentags können die Schlüssel im Einschränkungsblock auch Folgendes sein:

  • query filename: Entspricht der letzten Pfadkomponente des Abfragedateinamens
  • query path: Entspricht dem Pfad zur Abfragedatei relativ zum einschließenden CodeQL-Paket
  • tags contain: Eine der angegebenen Übereinstimmungszeichenfolgen muss mit einer der durch Leerzeichen getrennten Komponenten des Werts der @tags-Metadateneigenschaft übereinstimmen.
  • tags contain all: Jede der angegebenen Übereinstimmungszeichenfolgen muss mit einer der Komponenten der @tags-Metadateneigenschaft übereinstimmen.

Beispiele für das Filtern, welche Abfragen ausgeführt werden

Ein häufiger Anwendungsfall besteht darin, eine Abfragesammlung zu erstellen, die alle Abfragen in einem CodeQL-Paket ausführt (mit Ausnahme einiger spezifischer Abfragen, die Benutzer*innen nicht ausführen möchten). Allgemein wird empfohlen, nach der Abfrage id zu filtern, bei der es sich um einen eindeutigen und stabilen Bezeichner für jede Abfrage handelt. Die folgenden drei Abfragesammlungsdefinitionen sind semantisch identisch und filtern nach der Abfrage id:

Dieser Filter stimmt mit allen Abfragen in der Standardsammlung von codeql/cpp-queries überein (mit Ausnahme der beiden Abfragen mit den ausgeschlossenen Bezeichnern):

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

In diesem Beispiel wird für jede Abfrage eine separate exclude-Anweisung verwendet:

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

In diesem Beispiel schließt ein regulärer Ausdruck die gleichen beiden Abfragen aus. Außerdem werden alle zukünftigen Abfragen ausgeschlossen, die der Sammlung mit Bezeichnern hinzugefügt werden, die mit cpp/cleartext- beginnen:

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

Verwende Folgendes, um eine Sammlung zu definieren, die alle Abfragen in der Standardsammlung des CodeQL-Pakets codeql/cpp-queries auswählt und dann so optimiert, dass nur Sicherheitsabfragen eingeschlossen werden:

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

Verwende Folgendes, um eine Sammlung zu definieren, die alle Abfragen mit @kind problem und @precision high aus dem Verzeichnis my-custom-queries auswählt:

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

Beachte, dass sich die folgende Abfragesammlungsdefinition anders verhält als die obige Definition. Bei dieser Definition werden Abfragen ausgewählt, die @kind problem oder @precision very-high entsprechen:

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

Verwende Folgendes, um eine Sammlung zu erstellen, die alle Abfragen mit @kind problem aus dem my-custom-queries-Verzeichnis auswählt (mit Ausnahme der Abfragen mit @problem.severity recommendation):

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

Verwende Folgendes, um eine Sammlung zu erstellen, die alle Abfragen mit @tag security und @precision high oder very-high aus dem CodeQL-Paket codeql/cpp-queries auswählt:

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

Hinweis: Du kannst den codeql resolve queries /path/to/suite.qls-Befehl verwenden, um zu ermitteln, welche Abfragen von einer Abfragesammlungsdefinition ausgewählt werden. Weitere Informationen findest du unter resolve queries.

Wiederverwenden vorhandener Abfragesammlungsdefinitionen

Vorhandene Abfragesammlungsdefinitionen können wiederverwendet werden, indem Folgendes angegeben wird:

  • import-Anweisung: Der aktuellen Sammlung werden die von einer zuvor definierten .qls-Datei ausgewählten Abfragen hinzugefügt:

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

    Der Pfad zur importierten Sammlung muss relativ zum CodeQL-Paket sein, das die aktuelle Sammlungsdefinition enthält. Wenn sich die importierte Abfragesammlung in einem anderen QL-Paket befindet, kannst du Folgendes verwenden:

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

    Das version-Feld ist optional und gibt einen Bereich kompatibler Versionen dieses CodeQL-Pakets an. Wenn du keine Version angibst, wird die aktuellste Version des Pakets verwendet.

    Mithilfe einer import-Anweisung hinzugefügte Abfragen können unter Verwendung von nachfolgenden exclude-Anweisungen gefiltert werden.

  • apply-Anweisung: Der aktuellen Sammlung werden alle Anweisungen aus einer zuvor definierten .qls-Datei hinzugefügt. Die Anweisungen in der angewendeten .qls-Datei werden so ausgeführt, als ob sie anstelle von apply angezeigt würden. Alle include- und exclude-Anweisungen aus der angewendeten Sammlung gelten auch für Abfragen, die durch frühere Anweisungen hinzugefügt wurden:

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

    Die apply-Anweisung kann auch verwendet werden, um eine in einer .yml-Datei gespeicherte Gruppe wiederverwendbarer Bedingungen auf mehrere Abfragedefinitionen anzuwenden. Weitere Informationen findest du in den folgenden Beispielen.

Beispiele für Wiederverwendbarkeit

Um dieselben Bedingungen in mehreren Abfragesammlungsdefinitionen zu verwenden, erstelle eine separate .yml-Datei mit deinen Anweisungen. Speichere beispielsweise Folgendes in einer Datei namens reusable-instructions.yml:

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

Füge demselben CodeQL-Paket reusable-instructions.yml als aktuelle Abfragesammlung hinzu. Verwende dann in einer oder mehreren Abfragesammlungen die apply-Anweisung, um die wiederverwendbaren Anweisungen auf die aktuelle Sammlung anzuwenden. Beispiel:

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

Dadurch werden die Abfragen in queries/cpp/custom gefiltert, um nur diejenigen einzuschließen, die den Bedingungen für die Wiederverwendung entsprechen.

Du kannst auch eine Sammlungsdefinition auch mithilfe von reusable-instructions.yml für Abfragen in einem anderen CodeQL-Paket erstellen. Wenn sich die .qls-Datei im gleichen CodeQL-Paket befindet wie die Abfragen, kannst du unmittelbar nach der apply-Anweisung ein from-Feld hinzufügen:

# 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

Ein häufiger Anwendungsfall für eine import-Anweisung besteht darin, einen weiteren Filter auf Abfragen aus einer anderen Abfragesammlung anzuwenden. Diese Sammlung filtert beispielsweise weiter die cpp-security-and-quality-Sammlung und schließt low- und medium-Genauigkeitsabfragen aus:

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

Wenn du aus einer anderen Sammlung importierte Abfragen einschließen (include) möchtest, ist die Syntax etwas anders:

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

Beachte die leere exclude-Anweisung. Dies ist erforderlich, um sicherzustellen, dass die nachfolgende include-Anweisung Abfragen aus der importierten Sammlung filtern kann.

Benennen einer Abfragesammlung

Du kannst durch Angeben einer description-Anweisung einen Namen für deine Abfragesammlung festlegen:

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

Speichern einer Abfragesammlung

Speichere deine Abfragesammlung mit der Erweiterung .qls, und füge sie einem CodeQL-Paket hinzu. Weitere Informationen findest du unter Anpassen der Analyse mit CodeQL-Paketen.

Verwenden von Abfragesammlungen mit CodeQL

Du kannst Abfragesammlungen in der Befehlszeile für jeden Befehl angeben, der .qls-Dateien akzeptiert. Beispielsweise kannst du die von einer Sammlungsdefinition ausgewählten Abfragen mit query compile kompilieren oder die Abfragen in einer Analyse mit database analyze verwenden. Weitere Informationen zum Analysieren von CodeQL-Datenbanken findest du unter Analysieren des Codes mit CodeQL-Abfragen.

Weiterführende Themen