Three guards guarding art in a museum

Create a central CodeQL configuration file

Nicholas Liffen
Nicholas Liffen // Director, GitHub Advanced Security // GitHub

In the essentials and intermediate modules of this guide, we focused on getting started with and configuring code scanning. Now, let’s create a centralized configuration where you can tailor your code security management at scale, with one file to manage settings across multiple repositories or your entire organization. This way, teams don’t have to manually update workflows in potentially hundreds of repositories every time a security policy changes.

GitHub principal field security specialist Keith Hoodlet has some insight into why you might want to do this, especially at a larger organization:

Centralizing your CodeQL configuration is an important way to manage the tool at scale. At my previous job, our security team was responsible for more than 3,000 developers. We often worked closely with developers, and for some teams we were very prescriptive. But we couldn't do that for every single repository. By offering a centralized configuration, every repository across the organization can instantly adopt our recommended configuration, and it will always be up-to-date with our current guidance.

Keith Hoodlet
Keith Hoodlet // Principal Field Security Specialist, CodeQL // GitHub

There are a few different ways you could create and manage organization-wide configurations, but we recommend creating a configuration file in a private repository that security managers can control, and using it with every CodeQL workflow your organization creates. This way you can follow a good Git flow practice which ensures traceable changes. 


In this guide, you will learn:

  • Why and how to create a central CodeQL configuration file

  • How to provide access to your central file

  • How to tell repositories to use the central file


1. Create a new repository to store the configuration file.

Create a new private repository in your organization. This is where your security team will store the default configuration that all your other repositories can use. Only people who should have access to set an organization-wide security policy should have write access, but everyone should have read access. Let’s call it security-team-codeql-config

We recommend that you create a single repository to manage CodeQL and use separate folders for your configuration files and CodeQL queries, packs, and suites.

2. Create the configuration file.

Create a folder in the security-team-codeql-config repository named codeql. 

In the new codeql folder, create a file named codeql-config.yml.

Let’s add the following to the file:

name: "My CodeQL config"



disable-default-queries: true

This sets a name for our configuration file and disables the default CodeQL queries so we can specify what to run ourselves.

3. Add CodeQL packs to the configuration file.

Let’s add GitHub’s Field team core and extended Java/Kotlin and JavaScript/TypeScript packs to the config file by adding the following:

packs:
    # > Java/Kotlin queries
    - advanced-security/codeql-java
    - advanced-security/codeql-java-extensions
    # security-extended
    - codeql/java-queries:codeql-suites/java-security-extended.qls



    # JavaScript/TypeScript queries
    - advanced-security/codeql-javascript
    - advanced-security/codeql-javascript-extensions
    # security-extended
    - codeql/javascript-queries:codeql-suites/javascript-security-extended.qls

Now let’s add some more customizations:

paths-ignore:
    # JavaScript
    - 'node_modules'
    - '**/*.test.js'
    # JavaScript Frameworks/Libraries
    - '**/bootstrap.js'
    - '**/boostrap.min.js'
    - '**/jquery-*.js'



query-filters:
- exclude:
    tags:
        -/cwe/-029/
    problems.severity:
    	- warning
    	- recommendation

This code tells CodeQL to ignore several files and file directories, and excludes a well-known common weakness enumeration (CWE) so that we don’t see a warning for it every time CodeQL runs. It also ignores the severity levels “warning” and “recommendation” to keep our logs limited to just the important alerts.

The whole thing should look like this:

name: "My CodeQL config"
disable-default-queries: true



packs:
    # > Java/Kotlin queries
    - advanced-security/codeql-java
    - advanced-security/codeql-java-extensions
    # security-extended
    - codeql/java-queries:codeql-suites/java-security-extended.qls



    # JavaScript/TypeScript queries
    - advanced-security/codeql-javascript
    - advanced-security/codeql-javascript-extensions
    # security-extended
    - codeql/javascript-queries:codeql-suites/javascript-security-extended.qls



paths-ignore:
    # JavaScript
    - 'node_modules'
    - '**/*.test.js'
    # JavaScript Frameworks/Libraries
    - '**/bootstrap.js'
    - '**/boostrap.min.js'
    - '**/jquery-*.js'



query-filters:
- exclude:
    tags:
        -/cwe/-029/
    problems.severity:
    	- warning
    	- recommendation

You can use the above configuration as a template for your own configuration.

4. Create an external repository token.

Now that we have our centralized configuration file, we need to point our other repositories to it. If your configuration repository is private, which we recommend, the other repositories in your organization will need an external repository to access the custom CodeQL file.

On the GitHub.com page of the organization that owns the security-team-codeql-config repository, select the Settings tab.

Click Secrets and variables from the sidebar, then select the Actions option. 

Let’s give our new secret the name ACCESS_TOKEN and enter a value. You’ll need to enter it again shortly. Remember to follow your organization’s standards for secrets when working in production.

Make sure that Private and internal repositories is selected and click Add secret.

On the GitHub.com page for your Web Goat repository, select the Settings tab. Click Secrets and variables in the sidebar, then select the Actions option.

Add a token called ACCESS_TOKEN with the same value you entered above.

5. Add the centralized configuration file to the repository’s CodeQL workflow.

Now go to your Web Goat repository and open the .github/workflows/codeql.yml file. Find the following:

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        languages: ${{ matrix.language }}

Paste the following lines after it to point it at our configuration file:

        config-file: 
 owner/security-team-codeql-config/codeql/codeql-config.yml
 external-repository-token: ${{ secrets.ACCESS_TOKEN }}

Be sure to change the owner to your own organization name.

If you added the following lines as part of the intermediate module, comment them out like this for now:

        # paths-ignore:
        #    - '**/*.test.js'
        # config: |
        #  queries:
        #    - uses: security-and-quality

The section should now look like this:

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        languages: ${{ matrix.language }}
        config-file: organization/security-team-codeql-config/codeql/codeql-config.yml        external-repository-token: ${{ secrets.ACCESS_TOKEN }}

Commit the change.

That’s it! Now any time you change the codeql-config.yml file in the security-team-codeql-config repository, the changes will be reflected in your Web Goat repository.

You can check that it’s working using the tool status page covered in the intermediate module to see if it's working. You can find it by selecting the Security tab on your Web Goat repository, then selecting Code scanning and then Tool status.

Up next: Understanding your end-to-end software supply chain

We’ll return to CodeQL shortly, but first let’s take a look at two powerful supply chain security capabilities. In the next guide, we’ll look at how you can use the GitHub Dependency Submission API to create a map of all of your dependencies, including your dependencies’ dependencies, and how to generate a software bill of materials (SBOMs) so you can report on all your dependencies.