Sec section analyzer development
Analyzers are shipped as Docker images to execute within a CI pipeline context. This guide describes development and testing practices across analyzers.
Shared modules
There are a number of shared Go modules shared across analyzers for common behavior and interfaces:
- The
commandGo package implements a CLI interface. - The
commonproject provides miscellaneous shared modules for logging, certificate handling, and directory search capabilities. - The
reportGo package'sReportandFindingstructs marshal JSON reports. - The
templateproject scaffolds new analyzers.
How to use the analyzers
Analyzers are shipped as Docker images. For example, to run the Semgrep Docker image to scan the working directory:
-
cdinto the directory of the source code you want to scan. -
Run
docker login registry.gitlab.comand provide username plus personal or project access token with at least theread_registryscope. -
Run the Docker image:
docker run \ --interactive --tty --rm \ --volume "$PWD":/tmp/app \ --env CI_PROJECT_DIR=/tmp/app \ -w /tmp/app \ registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep:latest /analyzer run -
The Docker container generates a report in the mounted project directory with a report filename corresponding to the analyzer category. For example, SAST generates a file named
gl-sast-report.json.
Analyzers development
To update the analyzer:
- Modify the Go source code.
- Build a new Docker image.
- Run the analyzer against its test project.
- Compare the generated report with what's expected.
Here's how to create a Docker image named analyzer:
docker build -t analyzer .
For example, to test Secret Detection run the following:
wget https://gitlab.com/gitlab-org/security-products/ci-templates/-/raw/master/scripts/compare_reports.sh
sh ./compare_reports.sh sd test/fixtures/gl-secret-detection-report.json test/expect/gl-secret-detection-report.json \
| patch -Np1 test/expect/gl-secret-detection-report.json && Git commit -m 'Update expectation' test/expect/gl-secret-detection-report.json
rm compare_reports.sh
You can also compile the binary for your own environment and run it locally
but analyze and run probably won't work
since the runtime dependencies of the analyzer are missing.
Here's an example based on SpotBugs:
go build -o analyzer
./analyzer search test/fixtures
./analyzer convert test/fixtures/app/spotbugsXml.Xml > ./gl-sast-report.json
Secure stage CI/CD Templates and components
The secure stage is responsible for maintaining the following CI/CD Templates and Components:
- Composition Analysis
-
Static Analysis (SAST)
- CI/CD Templates
- CI/CD Components
-
Secret Detection
- CI/CD Templates
- CI/CD Components
Changes must always be made to both the CI/CD template and component for your group, and you must also determine if the changes need to be applied to the latest CI/CD template.
Analyzers are also referenced in the Secure-Binaries.gitlab-ci.yml file for offline environments. Ensure this file is also kept in sync when doing changes.
Execution criteria
Enabling SAST requires including a pre-defined template to your GitLab CI/CD configuration.
The following independent criteria determine which analyzer needs to be run on a project:
- The SAST template uses
rules:existsto determine which analyzer will be run based on the presence of certain files. For example, the Brakeman analyzer runs when there are.rbfiles and aGemfile. - Each analyzer runs a customizable match interface before it performs the actual analysis. For example: Flawfinder checks for C/C++ files.
- For some analyzers that run on generic file extensions, there is a check based on a CI/CD variable. For example: Kubernetes manifests are written in YAML, so Kubesec runs only when
SCAN_KUBERNETES_MANIFESTSis set to true.
Step 1 helps prevent wastage of compute quota that would be spent running analyzers not suitable for the project. However, due to technical limitations, it cannot be used for large projects. Therefore, step 2 acts as final check to ensure a mismatched analyzer is able to exit early.
How to test the analyzers
Video walkthrough of how Dependency Scanning analyzers are using downstream pipeline feature to test analyzers using test projects:
How Sec leverages the downstream pipeline feature of GitLab to test analyzers end to end
Testing local changes
To test local changes in the shared modules (such as command or report) for an analyzer
you can use the
go mod replace
directive to load command with your local changes instead of using the version of command that has been
tagged remotely. For example:
go mod edit -replace gitlab.com/gitlab-org/security-products/analyzers/command/v3=/local/path/to/command
Alternatively you can achieve the same result by manually updating the go.mod file:
module gitlab.com/gitlab-org/security-products/analyzers/awesome-analyzer/v2
replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /path/to/command
require (
...
gitlab.com/gitlab-org/security-products/analyzers/command/v3 v2.19.0
)
Testing local changes in Docker
To use Docker with replace in the go.mod file:
- Copy the contents of
commandinto the directory of the analyzer.cp -r /path/to/command path/to/analyzer/command. - Add a copy statement in the analyzer's
Dockerfile:COPY command /command. - Update the
replacestatement to make sure it matches the destination of theCOPYstatement in the step above:replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /command
Testing container orchestration compatibility
Users may use tools other than Docker to orchestrate their containers and run their analyzers, such as containerd, Podman, or skopeo. To ensure compatibility with these tools, we periodicically test all analyzers using a scheduled pipeline. A Slack alert is raised if a test fails.
To avoid compatibility issues when building analyzer Docker images, use the OCI media types instead of the default proprietary Docker media types.
In addition to the periodic test, we ensure compatibility for users of the ci-templates repo:
-
Analyzers using the
ci-templatesdocker-test.ymltemplate includeteststo ensure our Docker images function correctly with supported Docker tools.These tests are executed in Merge Request pipelines and scheduled pipelines, and prevent images from being released if they break the supported Docker tools.
-
The
ci-templatesdocker.ymltemplate specifiesoci-mediatypes=truefor thedocker buildxcommand when building analyzer images. This builds images using OCI media types rather than Docker proprietary media types.
When creating a new analyzer, or changing the location of existing analyzer images,
add it to the periodic test, or consider using the shared ci-templates which includes an automated test.
Analyzer scripts
The analyzer-scripts repository contains scripts that can be used to interact with most analyzers. They enable you to build, run, and debug analyzers in a GitLab CI-like environment, and are particularly useful for locally validating changes to an analyzer.
For more information, refer to the project README.
Versioning and release process
GitLab Security Products use an independent versioning system from GitLab MAJOR.MINOR. All products use a variation of Semantic Versioning and are available as Docker images.
Major is bumped with every new major release of GitLab, when breaking changes are allowed. Minor is bumped for new functionality, and Patch is reserved for bugfixes.
The analyzers are released as Docker images following this scheme:
- each push to the default branch will override the
edgeimage tag - each push to any
awesome-featurebranch will generate a matchingawesome-featureimage tag - each Git tag will generate the corresponding
Major.Minor.Patchimage tag. A manual job allows to override the correspondingMajorand thelatestimage tags to point to thisMajor.Minor.Patch.
In most circumstances it is preferred to rely on the MAJOR image,
which is automatically kept up to date with the latest advisories or patches to our tools.
Our included CI templates pin to major version but if preferred, users can override their version directly.
To release a new analyzer Docker image, there are two different options:
The following diagram describes the Docker tags that are created when a new analyzer version is released:
graph LR
A1[git tag v1.1.0]--> B1(run CI pipeline)
B1 -->|build and tag patch| D1[1.1.0]
B1 -->|tag minor| E1[1.1]
B1 -->|retag major| F1[1]
B1 -->|retag latest| G1[latest]
A2[git tag v1.1.1]--> B2(run CI pipeline)
B2 -->|build and tag patch| D2[1.1.1]
B2 -->|retag minor| E2[1.1]
B2 -->|retag major| F2[1]
B2 -->|retag latest| G2[latest]
A3[push to default branch]--> B3(run CI pipeline)
B3 -->|build and tag edge| D3[edge]
Per our Continuous Deployment flow, for new components that do not have a counterpart in the GitLab Rails application, the component can be released at any time. Until the components are integrated with the existing application, iteration should not be blocked by our standard release cycle and process.
Manual release process
- Ensure that the
CHANGELOG.mdentry for the new analyzer is correct. - Ensure that the release source (typically the
masterormainbranch) has a passing pipeline. - Create a new release for the analyzer project by selecting the Deployments menu on the left-hand side of the project window, then selecting the Releases sub-menu.
- Select New release to open the New Release page.
- In the Tag name drop down, enter the same version used in the
CHANGELOG.md, for examplev2.4.2, and select the option to create the tag (Create tag v2.4.2here). - In the Release title text box enter the same version used above, for example
v2.4.2. - In the
Release notestext box, copy and paste the notes from the corresponding version in theCHANGELOG.md. - Leave all other settings as the default values.
- Select Create release.
- In the Tag name drop down, enter the same version used in the
After following the above process and creating a new release, a new Git tag is created with the Tag name provided above. This triggers a new pipeline with the given tag version and a new analyzer Docker image is built.
If the analyzer uses the analyzer.yml template, then the pipeline triggered as part of the New release process above automatically tags and deploys a new version of the analyzer Docker image.
If the analyzer does not use the analyzer.yml template, you'll need to manually tag and deploy a new version of the analyzer Docker image:
- Select the CI/CD menu on the left-hand side of the project window, then select the Pipelines sub-menu.
- A new pipeline should currently be running with the same tag used previously, for example
v2.4.2. - After the pipeline has completed, it will be in a
blockedstate. - Select the
Manual jobplay button on the right hand side of the window and selecttag versionto tag and deploy a new version of the analyzer Docker image.
Use your best judgment to decide when to create a Git tag, which will then trigger the release job. If you can't decide, then ask for other's input.
Automatic release process
The following must be performed before the automatic release process can be used:
-
Configure
CREATE_GIT_TAG: trueas aCI/CDenvironment variable. -
Check the
Variablesin the CI/CD project settings:- If the project is located under the
gitlab-org/security-products/analyzersnamespace, then it automatically inherits theGITLAB_TOKENenvironment variable and nothing else needs to be done. - If the project is not located under the
gitlab-org/security-products/analyzersnamespace, then you'll need to create a new masked and hiddenGITLAB_TOKENCI/CDenvironment variable and set its value to the Personal Access Token for the @gl-service-dev-secure-analyzers-automation account described in the Service account used in the automatic release process section below.
- If the project is located under the
After the above steps have been completed, the automatic release process executes as follows:
- A project maintainer merges an MR into the default branch.
- The default pipeline is triggered, and the
upsert git tagjob is executed.- If the most recent version in the
CHANGELOG.mdmatches one of the Git tags, the job is a no-op. - Else, this job automatically creates a new release and Git tag using the releases API. The version and message is obtained from the most recent entry in the
CHANGELOG.mdfile for the project.
- If the most recent version in the
- A pipeline is automatically triggered for the new Git tag. This pipeline releases the
latest,major,minorandpatchDocker images of the analyzer.
Service account used in the automatic release process
| Key | Value |
|---|---|
| Account name | @gl-service-dev-secure-analyzers-automation |
| Purpose | Used for creating releases/tags |
| Member of | gitlab-org/security-products |
| Maximum role | Developer |
Scope of the associated GITLAB_TOKEN
|
api |
Expiry date of GITLAB_TOKEN
|
December 3, 2025 |
Any changes to the service account's access token scopes or the GITLAB_TOKEN
variable permissions should be announced in the section's Slack channel.
Token rotation for service account
The GITLAB_TOKEN for the @gl-service-dev-secure-analyzers-automation service account must be rotated before the Expiry Date listed above by doing the following:
-
Log in as the
gl-service-dev-secure-analyzers-automationuser.The list of administrators who have credentials for this account can be found in the service account access request.
Administrators can find the login credentials in the shared GitLab
1passwordvault. -
Create a new Personal Access Token with
apiscope for thegl-service-dev-secure-analyzers-automationservice account. -
Update the
passwordfield of theGitLab API Token - gl-service-dev-secure-analyzers-automationaccount in the shared GitLab1passwordvault to the new Personal Access Token created in step 2 (above), and set theExpires atfield to indicate when the token expires. -
Update the expiry date of the
GITLAB_TOKENfield in the Service account used in the automatic release process table. -
Set the following variables to the new Personal Access Token created in step 2 above:
It's crucial to mask and hide the following variables.
-
GITLAB_TOKENCI/CD variable for thegitlab-org/security-products/analyzersgroup.This allows all projects under the
gitlab-org/security-products/analyzersnamespace to inherit thisGITLAB_TOKENvalue. -
GITLAB_TOKENCI/CD variable for thegitlab-org/security-products/ci-templatesproject.This must be explicitly configured because the
ci-templatesproject is not nested under thegitlab-org/security-products/analyzersnamespace, and therefore does not inherit theGITLAB_TOKENvalue.The
ci-templatesproject requires theGITLAB_TOKENto allow certain scripts to execute API calls. This step can be removed after allow JOB-TOKEN access to CI/lint endpoint has been completed. -
GITLAB_TOKENCI/CD variable forgitlab-org/security-products/license-dbgroup.This must be explicitly configured because the
license-dbproject is not nested under thegitlab-org/security-products/analyzersnamespace, and therefore does not inherit theGITLAB_TOKENvalue. -
SEC_REGISTRY_PASSWORDCI/CD variable forgitlab-advanced-sast.This allows our tagging script to pull from the private container registry in the development project
registry.gitlab.com/gitlab-org/security-products/analyzers/<analyzer-name>/tmp, and push to the publicly accessible container registryregistry.gitlab.com/security-products/<analyzer-name>.
-
Steps to perform after releasing an analyzer
-
After a new version of the analyzer Docker image has been tagged and deployed, test it with the corresponding test project.
-
Announce the release on the relevant group Slack channel. Example message:
FYI I've just released
ANALYZER_NAMEANALYZER_VERSION.LINK_TO_RELEASE
Never delete a Git tag that has been pushed as there is a good chance that the tag will be used and/or cached by the Go package registry.
Backporting a critical fix or patch
To backport a critical fix or patch to an earlier version, follow the steps below.
- Create a new branch from the tag you are backporting the fix to, if it doesn't exist.
- For example, if the latest stable tag is
v4and you are backporting a fix tov3, create a new branch calledv3.
- For example, if the latest stable tag is
- Submit a merge request targeting the branch you just created.
- After its approved, merge the merge request into the branch.
- Create a new tag for the branch.
- If the analyzer has the automatic release process enabled, a new version will be released.
- If not, you have to follow the manual release process to release a new version.
- NOTE: the release pipeline will override the latest
edgetag so the most recent release pipeline'stag edgejob may need to be re-ran to avoid a regression for that tag.
Preparing analyzers for a major version release
This process applies to the following groups:
Other groups are responsible for documenting their own major version release process.
Choose one of the following scenarios based on whether the major version release contains breaking changes:
Major version release without breaking changes
Assuming the current analyzer release is v{N}:
- Configure protected tags and branches.
- During the milestone of the major release, when there are no more changes to be merged into the
defaultbranch:-
Create a
v{N}branch from thedefaultbranch. -
Create and merge a new Merge Request in the
defaultbranch containing only the following change to theCHANGELOG.mdfile:## v{N+1}.0.0 - Major version release (!<MR-ID>) -
Bump major analyzer versions in the CI/CD templates and components
-
Major version release with breaking changes
Assuming the current analyzer release is v{N}:
-
Create a new branch
v{N+1}to "stage" breaking changes. -
In the milestones leading up to the major release milestone:
-
Merge non-breaking changes to the
defaultbranch (akamasterormain) -
Merge breaking changes to the
v{N+1}branch, and create a separaterelease candidateentry in theCHANGELOG.mdfile for each change:## v{N+1}.0.0-rc.0 - some breaking change (!123)Using
release candidatesallows us to release all breaking changes in a single major version bump, which follows the semver guidance of only making breaking changes in a major version update.
-
-
During the milestone of the major release, when there are no more changes to be merged into the
defaultorv{N+1}branches:-
Create a
v{N}branch from thedefaultbranch. -
Create a Merge Request in the
v{N+1}branch to squash all therelease candidatechangelog entries into a single entry forv{N+1}.For example, if the
CHANGELOG.mdcontains the following 3release candidateentries for versionv{N+1}:## v{N+1}.0.0-rc.2 - yet another breaking change (!125) ## v{N+1}.0.0-rc.1 - another breaking change (!124) ## v{N+1}.0.0-rc.0 - some breaking change (!123)Then the new Merge Request should update the
CHANGELOG.mdto have a single major release forv{N+1}, by combining all therelease candidateentries into a single entry:## v{N+1}.0.0 - yet another breaking change (!125) - another breaking change (!124) - some breaking change (!123) -
Create a Merge Request to merge all the breaking changes from the
v{N+1}branch into thedefaultbranch. -
Delete the
v{N+1}branch, since it's no longer needed, as thedefaultbranch now contains all the changes from thev{N+1}branch. -
Bump major analyzer versions in the CI/CD templates and components.
-
Configure protected tags and branches
-
Ensure the wildcard
v*is set as both a Protected Tag and Protected Branch for the project. -
Verify the gl-service-dev-secure-analyzers-automation service account is
Allowed to createprotected tags.See step
3.1of the Officially supported images section for more details.
Configure scheduled pipelines
- Ensure three scheduled pipelines exist, creating them if necessary, and set
PUBLISH_IMAGES: truefor all of them:-
Republish images v{N}(against thev{N}branch)This scheduled pipeline needs to be created
-
Daily build(against thedefaultbranch)This scheduled pipeline should already exist
-
Republish images v{N-1}(against thev{N-1}branch)This scheduled pipeline should already exist
-
- Delete the scheduled pipeline for the
v{N-2}branch (if it exists), since we only support two previous major versions.
Bump major analyzer versions in the CI/CD templates and components
When images for all the v{N+1} analyzers are available under registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>, create a new merge request to bump the major version for each analyzer in the Secure stage CI/CD templates and components belonging to your group.
Development of new analyzers
We occasionally need to build out new analyzer projects to support new frameworks and tools. In doing so we should follow our engineering Open Source guidelines, including licensing and code standards.
In addition, to write a custom analyzer that will integrate into the GitLab application a minimal feature set is required:
Checklist
Verify whether the underlying tool has:
- A permissive software license.
- Headless execution (CLI tool).
- Bundle-able dependencies to be packaged as a Docker image, to be executed using GitLab Runner's Linux or Windows Docker executor.
- Compatible projects that can be detected based on filenames or extensions.
- Offline execution (no internet access) or can be configured to use custom proxies and/or CA certificates.
- The image is compatible with other container orchestration tools (see testing container orchestration compatibility).
Dockerfile
The Dockerfile should use an unprivileged user with the name GitLab.
This is necessary to provide compatibility with Red Hat OpenShift instances,
which don't allow containers to run as an admin (root) user.
There are certain limitations to keep in mind when running a container as an unprivileged user,
such as the fact that any files that need to be written on the Docker filesystem will require the appropriate permissions for the GitLab user.
See the following merge request for more details:
Use GitLab user instead of root in Docker image.
Minimal vulnerability data
See our security-report-schemas for a full list of required fields.
The security-report-schema repository contains JSON schemas that list the required fields for each report type:
Compatibility with report schema
Security reports uploaded as artifacts to GitLab are validated before being ingested.
Security report schemas are versioned using SchemaVer: MODEL-REVISION-ADDITION. The Sec Section
is responsible for the
security-report-schemas project,
including the compatibility of GitLab and the schema versions. Schema changes must follow the
product-wide deprecation guidelines.
When a new MODEL version is introduced, analyzers that adopt the new schema are responsible for
ensuring that GitLab deployments that do not vendor this new schema version continue to ingest
security reports without errors or warnings.
This can be accomplished in different ways:
- Implement support for multiple schema versions in the analyzer. Based on the GitLab version, the
analyzer emits a security report using the latest schema version supported by GitLab.
- Pro: analyzer can decide at runtime what the best version to utilize is.
- Con: implementation effort and increased complexity.
- Release a new analyzer major version. Instances that don't vendor the latest
MODELschema version continue to use an analyzer version that emits reports using versionMODEL-1.- Pro: keeps analyzer code simple.
- Con: extra analyzer version to maintain.
- Delay use of new schema. This relies on
additionalProperties=true, which allows a report to include properties that are not present in the schema. A new analyzer major version would be released at the usual cadence.- Pro: no extra analyzer to maintain, keep analyzer code simple.
- Con: increased risk and/or effort to mitigate the risk of not having the schema validated.
If you are unsure which path to follow, reach-out to the
security-report-schemas maintainers.
Location of Container Images
Container images for secure analyzers are published in two places:
-
Officially supported images in the
registry.gitlab.com/security-productsnamespace, for example:registry.gitlab.com/security-products/semgrep:5 -
Temporary development images in the project namespace, for example:
registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep/tmp:d27d44a9b33cacff0c54870a40515ec5f2698475
Officially supported images
The location of officially supported images, as referenced by our secure templates is:
registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>
For example, the semgrep-sast job in the SAST.gitlab-ci.yml template references the container image registry.gitlab.com/security-products/semgrep:5.
In order to push images to this location:
-
Create a new project in
https://gitlab.com/security-products/<ANALYZER-NAME>.For example:
https://gitlab.com/security-products/semgrepImages for this project will be published to
registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>.For example:
registry.gitlab.com/security-products/semgrep:5 -
Configure the project
https://gitlab.com/security-products/<ANALYZER-NAME>as follows:-
Add the following permissions:
-
Maintainer:
@gitlab-org/secure/managers,@gitlab-org/govern/managers -
Developer: @gl-service-dev-secure-analyzers-automation
This is necessary to allow the service account used in the automatic release process to push images to
registry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>.
-
-
Configure the following project settings:
-
Settings -> General -> Visibility, project features, permissions-
Project visibilityPublic
-
Additional options-
Users can request accessDisabled
-
-
IssuesDisabled
-
RepositoryOnly Project Members-
Merge RequestsDisabled
-
ForksDisabled
-
Git Large File Storage (LFS)Disabled
-
CI/CDDisabled
-
Container RegistryEveryone with access
-
Analytics,Requirements,Security and compliance,Wiki,Snippets,Package registry,Model experiments,Model registry,Pages,Monitor,Environments,Feature flags,Infrastructure,Releases,GitLab DuoDisabled
-
-
-
-
Configure the following options for the analyzer project, located at
https://gitlab.com/gitlab-org/security-products/analyzers/<ANALYZER_NAME>:-
Add the wildcard
v*as a Protected Tag.Ensure the gl-service-dev-secure-analyzers-automation service account has been explicitly added to the list of accounts
Allowed to createprotected tags. This is required to allow theupsert git tagjob to create new releases for the analyzer project. -
Add the wildcard
v*as a Protected Branch. -
It's crucial to mask and hide the
SEC_REGISTRY_PASSWORDvariable.Key Value SEC_REGISTRY_IMAGEregistry.gitlab.com/security-products/$CI_PROJECT_NAMESEC_REGISTRY_USERgl-service-dev-secure-analyzers-automationSEC_REGISTRY_PASSWORDPersonal Access Token for gl-service-dev-secure-analyzers-automationuser. Request an administrator to configure this token value.The above variables are used by the tag_image.sh script in the
ci-templatesproject to push the container image toregistry.gitlab.com/security-products/<ANALYZER-NAME>:<TAG>.See the semgrep CI/CD Variables for an example.
-
Temporary development images
The location of temporary development images is:
registry.gitlab.com/gitlab-org/security-products/analyzers/<ANALYZER-NAME>/tmp:<TAG>
For example, one of the development images for the semgrep analyzer is:
registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep/tmp:7580d6b037d93646774de601be5f39c46707bf04
In order to
restrict the number of people who have write access to the container registry,
the container registry in the development project must be made private by configuring the following project features and permissions settings for the project located at https://gitlab.com/gitlab-org/security-products/analyzers/<ANALYZER-NAME>:
-
Settings -> General -> Visibility, project features, permissions-
Container RegistryOnly Project Members
-
Each group in the Sec Section is responsible for:
- Managing the deprecation and removal schedule for their artifacts, and creating issues for this purpose.
- Creating and configuring projects under the new location.
- Configuring builds to push release artifacts to the new location.
- Removing or keeping images in old locations according to their own support agreements.
Daily rebuild of Container Images
The analyzer images are rebuilt on a daily basis to ensure that we frequently and automatically pull patches provided by vendors of the base images we rely on.
This process only applies to the images used in versions of GitLab matching the current MAJOR release. The intent is not to release a newer version each day but rather rebuild each active variant of an image and overwrite the corresponding tags:
- the
MAJOR.MINOR.PATCHimage tag (for example:4.1.7) - the
MAJOR.MINORimage tag(for example:4.1) - the
MAJORimage tag (for example:4) - the
latestimage tag
The implementation of the rebuild process may vary depending on the project, though a shared CI configuration is available in our development ci-templates project to help achieving this.
Adding new language support to GitLab Advanced SAST (GLAS)
This guide helps engineers evaluate and add new language support to GLAS. These guidelines ensure consistent quality when expanding language coverage, rather than serving as strict requirements.
Language support readiness criteria
Adapt these guidelines to your specific language while maintaining our analyzer quality standards.
These guidelines come from our experience adding PHP support to GLAS (see issue #514210) and help determine when new language support is ready for production.
Quality readiness
Cross-file analysis capability
- Support the most common dependency management patterns in the target language
- Support common inclusion mechanisms specific to the language
Detection quality
- Precision Rate ≥ 80% across supported CWEs
- Comprehensive test corpus for each supported CWE
- Testing against popular frameworks in the language ecosystem
Coverage readiness
Priority-based coverage
- Must cover critical injection vulnerabilities relevant to the language
- Must cover common security misconfigurations
- Must align with industry standards (OWASP Top 10, SANS CWE Top 25)
- Focus on high-impact vulnerabilities commonly found in the language
Support readiness
Documentation requirements
- Language listed and described in supported languages documentation
- CWE coverage table updated with new language column
- All supported CWEs properly marked
- Known limitations clearly documented
Performance readiness
Standard performance criteria
- Medium-sized applications: < 10 minutes
- Very large applications: < 30 minutes with multi-core options
Benchmark definition
- Define representative codebases for benchmarking
- Include common frameworks and libraries
Security and Build fixes of Go
The Dockerfile of the Secure analyzers implemented in Go must reference a MAJOR release of Go, and not a MINOR revision.
This ensures that the version of Go used to compile the analyzer includes all the security fixes available at a given time.
For example, the multi-stage Dockerfile of an analyzer must use the golang:1.15-alpine image
to build the analyzer CLI, but not golang:1.15.4-alpine.
When a MINOR revision of Go is released, and when it includes security fixes,
project maintainers must check whether the Secure analyzers need to be re-built.
The version of Go used for the build should appear in the log of the build job corresponding to the release,
and it can also be extracted from the Go binary using the strings command.
If the latest image of the analyzer was built with the affected version of Go, then it needs to be rebuilt. To rebuild the image, maintainers can either:
- trigger a new pipeline for the Git tag that corresponds to the stable release
- create a new Git tag where the
BUILDnumber is incremented - trigger a pipeline for the default branch, and where the
PUBLISH_IMAGESvariable is set to a non-empty value
Either way a new Docker image is built, and it's published with the same image tags: MAJOR.MINOR.PATCH and MAJOR.
This workflow assumes full compatibility between MINOR revisions of the same MAJOR release of Go.
If there's a compatibility issue, the project pipeline will fail when running the tests.
In that case, it might be necessary to reference a MINOR revision of Go in the Dockerfile
and document that exception until the compatibility issue has been resolved.
Since it is NOT referenced in the Dockerfile, the MINOR revision of Go is NOT mentioned in the project changelog.
There may be times where it makes sense to use a build tag as the changes made are build related and don't require a changelog entry. For example, pushing Docker images to a new registry location.
Git tag to rebuild
When creating a new Git tag to rebuild the analyzer,
the new tag has the same MAJOR.MINOR.PATCH version as before,
but the BUILD number (as defined in semver) is incremented.
For instance, if the latest release of the analyzer is v1.2.3,
and if the corresponding Docker image was built using an affected version of Go,
then maintainers create the Git tag v1.2.3+1 to rebuild the image.
If the latest release is v1.2.3+1, then they create v1.2.3+2.
The build number is automatically removed from the image tag.
To illustrate, creating a Git tag v1.2.3+1 in the gemnasium project
makes the pipeline rebuild the image, and push it as gemnasium:1.2.3.
The Git tag created to rebuild has a simple message that explains why the new build is needed.
Example: Rebuild with Go 1.15.6.
The tag has no release notes, and no release is created.
To create a new Git tag to rebuild the analyzer, follow these steps:
-
Create a new Git tag and provide a message
git tag -a v1.2.3+1 -m "Rebuild with Go 1.15.6" -
Push the tags to the repo
git push origin --tags -
A new pipeline for the Git tag will be triggered and a new image will be built and tagged.
-
Run a new pipeline for the
masterbranch in order to run the full suite of tests and generate a new vulnerability report for the newly tagged image. This is necessary because the release pipeline triggered in step3.above runs only a subset of tests, for example, it does not perform aContainer Scanninganalysis.
Monthly release process
This should be done on the 18th of each month. Though, this is a soft deadline and there is no harm in doing it within a few days after.
First, create a new issue for a release with a script from this repo: ./scripts/release_issue.rb MAJOR.MINOR.
This issue will guide you through the whole release process. In general, you have to perform the following tasks:
-
Check the list of supported technologies in GitLab documentation.
-
Check that CI job definitions are still accurate in vendored CI/CD templates and all of the ENV vars are propagated to the Docker containers upon
docker runper tool.- SAST vendored CI/CD template
- Dependency Scanning vendored CI/CD template
- Container Scanning CI/CD template
If needed, go to the pipeline corresponding to the last Git tag, and trigger the manual job that controls the build of this image.
Dependency updates
All dependencies and upstream scanners (if any) used in the analyzer source are updated on a monthly cadence which primarily includes security fixes and non-breaking changes.
SAST and Secret Detection
SAST and Secret Detection teams use an internal tool (SastBot) to automate dependency management of SAST and Pipeline-based Secret Detection analyzers. SastBot generates MRs on the 8th of each month and distributes their assignment among team members to take them forward for review. For details on the process, see Dependency Update Automation.
SastBot requires different access tokens for each job. It uses the DEP_GITLAB_TOKEN environment variable to retrieve the token when running scheduled pipeline jobs.
| Scheduled Pipeline | Token Source | Role | Scope |
DEP_GITLAB_TOKEN Token Configuration Location |
Token Expiry |
|---|---|---|---|---|---|
Merge Request Metadata Update |
security-products/analyzers group |
developer |
api |
Settings > CI/CI Variables section (Masked, Protected, Hidden) | Jul 25, 2026 |
Release Issue Creation |
security-products/release project |
planner |
api |
Configuration section of the scheduled pipeline job | Jul 28, 2026 |
| Analyzers |
sast-bot group |
developer |
api |
Configuration section of the scheduled pipeline job | Jul 28, 2026 |