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: inheritor 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 |
|---|---|---|---|---|
| additional_build_secrets | string | false | Comma-separated list of secrets for CodeQL autobuild / Semgrep Dependency Graph generation |
|
| codeql_queries | string | false | "security-extended" |
Comma-separated list of queries for CodeQL to run. By default is set to security-extended. |
| expose_github_token_and_actor | boolean | false | false |
Expose GITHUB_TOKEN and GITHUB_ACTOR to support Github packages for CodeQL and Semgrep |
| gradle_opts | string | false | "-Dorg.gradle.jvmargs=-Xmx4g" |
Gradle build options to pass on to the CodeQL scanner |
| ignore_language | string | false | Comma-separated list of languages for CodeQL or Semgrep to ignore. See CodeQL Languages or "scala" for Semgrep |
|
| java_distribution | string | false | "temurin" |
Java distribution for "actions/setup-java" to use |
| java_server_id_artifactory | string | false | Java server id for "actions/setup-java" to use. This will setup maven server with artifactory credentials for CodeQL autobuild to use. |
|
| java_version | string | false | "21" |
Java version for "actions/setup-java" to use |
| job_runner | string | false | "ubuntu-24.04" |
Customizable job runner for CodeQL or Semgrep jobs that require a little extra performance/memory. List of runners is available in Confluence. |
| use_maven_cache | boolean | false | false |
Uses "actions/cache" to cache local maven repository, and can speed up autobuild times for CodeQL |
| use_setup_gradle | boolean | false | false |
OBSOLETE. This is now autodetected and enabled if build.gradle(.kt(s)) is found. Uses "gradle/action/setup-gradle" before running autobuild (Java/Kotlin/Scala only). |
| use_setup_java | boolean | false | false |
Uses "actions/setup-java" before running CodeQL or Gradle Dependency Graph (Java/Kotlin/Scala only). CodeQL autobuild / Gradle Dependency Graph will use the Java version from "actions/setup-java". |
| SECRET | REQUIRED | DESCRIPTION |
|---|---|---|
| ARTIFACTORY_AUTH_TOKEN | false | Token for the Artifactory repository. Secret is fetched from Entur GitHub organization if secrets are inherited. |
| ARTIFACTORY_AUTH_USER | false | The username for the Artifactory repository. Secret is fetched from Entur GitHub organization if secrets are inherited. |
| SLACK_BOT_TOKEN | false | Slack bot token is used for notifications. Secret is fetched from Entur GitHub organization if secrets are inherited. |
| SOFTPAY_NEXUS_PASSWORD | false | The password for Softpay. Secret is fetched from Entur GitHub organization if secrets are inherited. |
| SOFTPAY_NEXUS_USERNAME | false | The username for Softpay. Secret is fetched from Entur GitHub organization if secrets are inherited. |
| external_repository_token | false | Token to access the external repository mentioned in the codescan.yml file. Must have read access to the repository. |
- 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: inheritCode Scan have been developed with Gradle in mind, so we can't guarantee every Maven project to work with default setup.
Maven uses .m2/settings.xml to setup server credentials for repository artifactory.
Use setup below and replace server_id_here with the server id for repository artifactory.
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
with:
use_setup_java: true
java_version: "21"
java_distribution: "temurin"
java_server_id_artifactory: "server_id_here"To cache maven dependencies use the setup below.
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
with:
use_maven_cache: truenote: workflow input use_maven_cache is required for workflow to cache Maven dependencies.
Code vulnerability scans of Java and Kotlin are done by running autobuild, which runs any identified build systems, like Gradle.
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 scanner config file (YAML-file) with allowlist spec 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.
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.
See Code Scan config for how to setup allowlist in config.
Notifications will be sent out when there are alerts with severity equal or higher than threshold set. By default, high alerts will be notified under pull requests.
Notifications for Code Scan supports alerts from tool(s):
- CodeQL
Support for alerts from semgrep will be added soon.
Severity threshold:
Severity threshold is by default set to high, all alert with severity that equals the threshold or higher will trigger notifications. The threshold can be set to one of the following values:
- low
- medium
- high
- critical
Slack:
Slack notifications are by default disabled, but can be enabled by creating a scanner config in repository or inheriting a shared config.
Note: The slack channel used for notifications needs to have Github Actions bot in the channel, see gha-slack prereqs on how to invite the bot. Additionally, you MUST specify secrets: inherit when calling the code-scan reusable-workflow.
The format and location of the config can be found in the section below.
Pull Request:
Pull request notifications (comments) are enabled by default, but can be disabled by creating a scanner config in repository or inheriting a shared config.
The format and location of the config can be found in the section below.
Requirements for Code Scan config:
- The config file MUST adhere to the format specified later in this document.
- The config file MUST be named either
codescan.ymlorcodescan.yaml. - The file MUST be placed in
.entur/security, relative to the root of the repository.
Shared config works by referencing it in when you define a spec for your project. The contents of the spec in config is then combined with the one in your repo. The contents of the "local" config takes presedence of the "external" config.
To use an external config create a YAML file in a different repository, reference the name of the repository in the .spec.inherit field of your config file.
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 an external config
- A fine-grained access token must be created to access the external Code Scan config 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 Code Scan config file for inheritance, must still define
inheritunder spec referencing the name of the repo containing the external config file. See schema for more info.
apiVersion: entur.io/securitytools/v1
kind: CodeScanConfig
metadata:
id: {unique identifier}
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}
notifications:
severityThreshold: {threshold for notifications}
outputs:
slack:
enabled: {boolean for enabling slack notifications}
channelId: {slack channel with github actions bot}
pullRequest:
enabled: {boolean for enabling pull request notifications}Metadata:
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.
Spec:
The OPTIONAL inherit field MUST be the name of containing repository where containing a valid spec you wish to inherit from.
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
cwefield corresponds to the CWE-ID of the vulnerability you want to dismiss, - The
commentfield is a comment explaining why the vulnerability is dismissed. Comments longer than 280 characters will be truncated. - The
reasonfield MUST be one of the following types:false_positiveThis alert is not validwont_fixThis alert is not relevanttestThis alert is not in production code
Note: inherit and items under spec are NOT mutually exclusive. Any items under allowlist and notifications takes precedence over an inherited spec.
The OPTIONAL notifications field
- The
severityThresholddefines the threshold for when notifications are sent out.
The field MUST be one of the following typeslowmediumhighcritical
- The
outputsfield corresponds to notification outputs.- The
slackfield SHOULD include:enabledboolean for enabling slack notificationschannelIdchannelId for slack channel with github actions bot
- The
pullRequestfield SHOULD include:enabledboolean for enabling pull request notifications
- The
apiVersion: entur.io/securitytools/v1
kind: CodeScanConfig
metadata:
id: myprojectconfig
spec:
inherit: other-repo-name
notifications:
severityThreshold: "high"
outputs:
slack:
enabled: true
channelId: "SLACK_CHANNEL_ID"
pullRequest:
enabled: false
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" See Security rulesets for how to setup code scanning merge protection ruleset.
Some potential pitfalls and solutions with CodeQL
Configuration errors such as the one above, can occasionally pop-up if no new analyses have been submitted for a long time. To fix the error, either trigger a new codescan, or delete the old configuration.
This can happen if you have a previous analysis referencing earlier commits on the main branch for a configuration which is no longer valid. Typically this occurs to due a major change in the programming languages used in the codebase.
To fix this error it requires deleting all previous analysis for the invalid configuration. Example of such an 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": ""
}Invalid configurations can either be deleted through the API, or the UI.
See [Github documentation](https://docs.github.com/en/rest/code-scanning/code-scanning?apiVersion=2022-11-28#delete-a-code-scanning-analysis-from-a-repository
5. Select the failing configuration and click the "Delete configuration" button in the ellipsis list
This can happen if Autobuild detects the wrong version of the JVM to run Gradle with. This can be solved by
updating workflow configuration to use use_setup_java
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
with:
use_setup_java: true
java_version: "21"
java_distribution: "temurin"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
It is now possible to override the runner used by GitHub to one with more cpu/ram. Input JOB_RUNNER.
The list of options is available in Confluence
Gradle build options can also be overridden to increase jvm memory. Input GRADLE_OPTS.
When CodeQL is triggered, the environment variable IS_CODEQL_SCAN is set to true which could be used to skip certain tests during build.
Recent changes to CodeQL will make analysis fail if a project has HTML file(s) without javascript/typescript, and no additional javascript/typescript files is found.
To fix this you can add dummy javascript to a HTML file, or add html to workflow input ignore_language.
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
with:
ignore_language: "html"Note Following extensions is part of our HTML file extension detection
- .vue
- .ejs
- .htm
- .html
- .xhtm
- .xhtml
The CodeQL autobuild and Semgrep dependency graph steps run in an isolated environment that does not expose your repository or organization secrets by default. If your build needs one (for example, to download dependencies from a private registry), pass a comma-separated list of secret names to the additional_build_secrets input.
Each named secret is exported as an environment variable for the build/autobuild step and cleared again afterward. The names must match the secrets available to the workflow, so secrets: inherit is required.
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
with:
additional_build_secrets: "TOKEN_SECRET,TOKEN_SECRET_2"The build can then read them as regular environment variables, e.g. $TOKEN_SECRET.
Enable expose_github_token_and_actor to expose GITHUB_TOKEN and GITHUB_ACTOR in CodeQL/Semgrep steps.
These variables can be used to authenticate to Github, so the build process can download required dependencies from Github Packages.
jobs:
code-scan:
name: Code Scan
uses: entur/gha-security/.github/workflows/code-scan.yml@v2
secrets: inherit
with:
expose_github_token_and_actor: true
...





