Add the following step to your workflow configuration:
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
or add the Entur Shared Workflow CodeQL Scan. Go to the Actions tab in your repository, click on New workflow and select the button Configure on the CodeQL Scan workflow.
INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
---|---|---|---|---|
use_setup_gradle | boolean | false | false |
Use "gradle/action/setup-gradle" before running autobuild (Java/Kotlin only). Potentially speeds up build times if cache from main branch is utilized |
- Workflow must be named
codeql.yml
.
# codeql.yml
name: "CodeQL"
on:
pull_request:
branches:
- main
push:
branches:
- main
paths-ignore:
- '**/README.md'
schedule:
- cron: "0 3 * * MON"
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
Code vulnerability scans of Java and Kotlin are done by running autobuild, which runs any identified build systems, like Gradle.
If the project uses the gradle/actions/setup-gradle action, you can set code scanning to utilize any available cache from the 'main' branch. This potentially speeds up code analysis jobs.
Caching is deactivated by default.
To activate caching, set input use_setup_gradle
to true
.
Example:
# codeql.yml
name: "CodeQL"
...
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
with:
use_setup_gradle: true
The reusable workflow uses CodeQL to scan the codebase for vulnerabilities. Any discovered vulnerabilities will be published in the Security tab for the repository, under the Code Scanning section. If you believe a finding is a false positive or otherwise not relevant, you can either manually dimiss the alert, or create a allowlist file (YAML-file) that dismisses all alerts that matches a vulnerability ID. This list is then used in the current repo, but can also be shared and used with other repos.
Requirements:
- The allowlist file MUST adhere to the format specified later in this document.
- The allowlist file MUST be named either
codescan.yml
orcodescan.yaml
. - The file MUST be placed in
.entur/security
, relative to the root of the repository.
Note: If the scan is performed on a pull request, remember to filter the Code Scanning results by pull request number and not the branch name.
Shared allowlists works by referencing it in when you define an allowlist for your project. The contents of that list is then combined with the one in your repo. The contents of the "local" allowlist takes presedence of the "external" list.
To use an external allowlist create a YAML file in a different repository, reference the name of the repository in the .spec.inherit
field of your allowlist.
Read Permissions of the repo containing any external allowslists are REQUIRED. It is important to note that a fine-grained access token must be created, with READ CONTENT permissions to the repository. The token then MUST be added as a secret to the repository where the workflow is executed, and MUST be named EXTERNAL_REPOSITORY_TOKEN
.
You can find documentation on how to create a fine-grained access token here, and how to add it as a secret to your repository here.
Requirements for referencing external allowlists
- A fine-grained access token must be created to access the external allowlist file, with READ CONTENT permissions to the external repository.
- The token must be added as a secret to the repository where the workflow is run, and be named
EXTERNAL_REPOSITORY_TOKEN
. - Any repository using an external allowlist file for inheritance, must still define an allowlist referencing the name of the repo containing the external list. See schema for more info.
apiVersion: entur.io/securitytools/v1
kind: CodeScanConfig
metadata:
id: {unique identifier}
name: {human readable name}
owner: {responsible team or developer}
spec:
inherit: {repository where the external allowlist file is placed}
allowlist:
- cwe: {cwe-id}
comment: {comment explaining why the vulnerability is dismissed}
reason: {reason for dismissing the vulnerability}
Metadata:
All fields in metadata
are REQUIRED.
The id
field MUST be a unique alphanumeric (no special characters) string identifing the allowlist. This can be anything, but when in doubt use your app ID.
The name
field under the metadata section SHOULD be the name of the project.
The owner
field MUST be whomever's responsible for the list, like team or a single developer.
Spec:
The OPTIONAL inherit
field MUST be the name of containing repository where containing a valid allow list you wish to inherit from. Only used when using an external allowlist.
The OPTIONAL allowlist
field MUST be a list of vulnerabilities that you want to dismiss/allow. For each vulnerability you want to dismiss, you MUST add a new item to the list. Each item is an object and MUST contain the following fields: cwe
, comment
, and reason
.
- The
cwe
field corresponds to the CWE-ID of the vulnerability you want to dismiss, - The
comment
field is a comment explaining why the vulnerability is dismissed. - The
reason
field MUST be one of the following types:false_positive
This alert is not validwont_fix
This alert is not relevanttest
This alert is not in production code
Note: inherit
and allowlist
are NOT mutually exclusive. Any items in allowlist
takes presedence over an inherited allowlist.
apiVersion: entur.io/securitytools/v1
kind: CodeScanConfig
metadata:
id: myprojectconfig
name: my-project-config
owner: team-supreme
spec:
inherit: other-repo-name
allowlist:
- cwe: "cwe-080"
comment: "This alert is a false positive"
reason: "false_positive"
- cwe: "cwe-916"
comment: "Wont be able to fix this in the near future"
reason: "wont_fix"
- cwe: "cwe-400"
comment: "Used for testing purposes"
reason: "test"
Some potential pitfalls and solutions with CodeQL
This can happen if you previously had earlier commit(s) in main branch that had an analysis that included the configuration(s).
CodeQL tries looking for the analysis with the configuration it warns about in the PR, but does not find it.
To fix this error it requires deleting all previous analysis for the configuration.
They should be in their own set by the unique category set and ref set.
Example of analysis with a kotlin configuration:
{
"ref": "refs/heads/main",
"commit_sha": "...",
"analysis_key": ".github/workflows/codeql.yml:codeql-analysis",
"environment": "{\"language\":\"kotlin\"}",
"category": "/language:kotlin",
"error": "",
"created_at": "2025-01-03T12:42:17Z",
"results_count": 0,
"rules_count": 74,
"id": 0,
"url": "https://api.github.com/repos/entur/repository_name/code-scanning/analyses/....",
"sarif_id": "...",
"tool": {
"name": "CodeQL",
"guid": null,
"version": "2.20.0"
},
"deletable": true,
"warning": ""
}
See Github documentation for how to delete code scanning analysis for the configuration.
This can happen if Autobuild detects the wrong version of the JVM to run Gradle with. This can be solved by statically setting the JVM version in the Gradle toolchain:
...
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(<JVM_VERSION>)) // Replace with correct JVM Version
}
}
...
Autobuild checks the root project file for which JVM version to set based on the version set on the JVM toolchain. Github also has a page that explains it in more detail: Autodetection for java
Autodetect will not find the correct version from child project files, if you have a root project file that does not compile JVM code. To fix this, you can trick autobuild with a comment.
The comment needs to be set on first line of the root project file (build.gradle)
// Hint for the CodeQL autobuilder: sourceCompatibility = <JVM_VERSION>
...
More detail about this fix in the Github Issues thread
See Security rulesets for how to setup code scanning merge protection ruleset.