Available since 1.14.0 (EE), with the early access flag fe_security_scan_policies
Preliminary version. The functionality may change, and an upgrade may require manual migration actions.
Deckhouse Code adds integrations of its own for the tools behind its mandated security scans and for the system that collects their findings. A scanner integration holds what a scan job needs and a policy must not carry in a repository: the server address, the token, the certificate trust and the defaults for every scan of the project. The DefectDojo integration holds the connection to the server the security reports of a pipeline are sent to.
| Integration | What it serves | Configured on |
|---|---|---|
| “CodeScoring” | The codescoring scan | A project or a group |
| “Positive Technologies Application Inspector” | The ptai scan | A project or a group |
| “AppSec.Hub” | The appsec_hub scan and uploading project scanner reports | A project |
| “DefectDojo” | Every scan that publishes a security report | The instance, a group or a project |
Project and group integrations are available under “Settings” → “Integrations”. A group integration applies to each project in the group that has not configured its own integration.
Integration configuration and availability:
- Opengrep and Trivy: Scanners behind the mandated SAST and Trivy scans. They require no integration configuration and do not appear in the integrations list.
- CodeScoring and PT AI: The integrations are available when the
fe_security_scan_policiesfeature flag is enabled. - DefectDojo: The integration is available when the
defect_dojo_integrationfeature flag is enabled. - AppSec.Hub: The integration is available only at the project level when the
appsec_hub_integrationfeature flag is enabled and the instance has a license covering security scanning. Running theappsec_hubscan from a policy also requires thefe_security_scan_policiesfeature flag.
For instructions on enabling feature flags, see Early access.
The scan itself is set in the scan execution policy: which modules run, what is scanned and what fails the pipeline. The policy editor offers the PT AI and CodeScoring scans only while an integration of that scanner is active for the project or for a group above it; the greyed-out choice links to the integration page. An integration’s variables reach every job of the pipeline; its tokens reach only the scan job a policy mandated for that scanner. A variable the policy sets outranks the same variable from the integration. The policy editor and the options of the SAST scan are described on the SAST scanning page.
Opengrep
Opengrep is the scanner behind the mandated SAST scan, opengrep_sast. It is a command-line tool that runs inside the job: there is no server to reach, no token to hold and no certificate to trust. Everything about the scan belongs to the policy, including the image the scan runs in, so there is no integration to set up: “Opengrep” is absent from the “Integrations” lists, from the settings pages and from the REST API, and the scan jobs receive no variable from an integration record.
The image the scan runs in is resolved by the server while the job is rendered and written into the job as a literal value. The server takes:
- the reference in the “Scanner image” field of the
opengrep_sastaction, when the policy names one; - otherwise the image named in the instance environment variable
FE_SCANS_OPENGREP_IMAGE; - otherwise the image this release pins,
opengrep-scan:1.30.0-fe2from the product registry.
The image never becomes a CI/CD variable, so the scanned project’s own settings cannot point the scan at another scanner. The “Scanner image” field of the policy shows the image an empty field runs, and the hint beside it names the Opengrep version and the rule set that ship with this product.
The rules, the rule levels, the subjects left out, the blocking threshold, the ignored paths and the additional arguments are the “Rules”, “Rule levels”, “Subjects to leave out”, “Blocking threshold”, “Ignored paths” and “Additional arguments” groups of the same action. The scan, its jobs and these groups are described on the SAST scanning page.
Trivy
Trivy is the scanner behind the mandated trivy scan. It runs inside the job and reaches no server of its own, so there is no integration to set up: “Trivy” is absent from the “Integrations” lists, from the settings pages and from the REST API, and the scan jobs receive no variable from an integration record.
Everything about the scan belongs to the policy: the modules it runs, their options and the image it runs in. The server writes the image into the job while the job is rendered: the reference in the “Scan image” field of the trivy action, or, when the policy names none, the image this release pins, trivy-with-db:0.74.0 from the product registry. The container module reads registry credentials from the CI/CD variables of the scanned project.
The scan, its modules and their options are described on the Scanning with Trivy page.
CodeScoring
The full setup, the SCA and Secrets modules and the troubleshooting of this integration are on the CodeScoring integration page.
The CodeScoring integration connects a project to a CodeScoring server and delivers the johnny agent to the jobs of the codescoring scan. The scan has two modules, each turned on in the policy: composition analysis, which the codescoring_sca job runs and which publishes the dependency scanning report, the code quality report, the test report and the CycloneDX SBOM gl-sbom.cdx.json; and the secret search, which the codescoring_secrets_gitleaks, codescoring_secrets_trufflehog and codescoring_secrets_kingfisher jobs run, one per engine, and which publishes a secret detection report. The findings reach the vulnerability report, the dependency list and DefectDojo like those of every other scanner; the SBOM is what the Dependency list and license compliance pages read.
The integration is configured on a project or a group, in “Settings” → “Integrations” → “CodeScoring”. The policy editor offers the codescoring scan while the integration is active for the project or a group above it. The form holds the connection, the trust and the defaults of the scan jobs; what the agent scans and how is set in the policy:
| Field | Content |
|---|---|
| “Server URL” | Base URL of the CodeScoring server, for example https://codescoring.example.com. Required. Section “Connection”. |
| “API token” | Token the jobs authenticate with and download the johnny agent by. Required. Section “Connection”. |
| “Scan stage” | The policy stage the scan reports as on the server: build, dev, source, stage, test or prod. Default: build. The agent takes one stage, so the scan reports as one. Section “Connection”. |
| “Certificate trust” | How the scan job decides whether to trust the server: “Trust what the job already trusts” (default), “Trust the certificate authority below”, “Do not verify the certificate”. The setting applies to the requests the job makes with curl (downloading the agent) and to the connection test; the johnny agent verifies no certificate and offers no way to make it. Section “Certificate trust”. |
| “Certificate authority” | PEM certificate of the authority that signed the server’s certificate. Read only with “Trust the certificate authority below”, and required then. Section “Certificate trust”. |
| “Scan job image” | Image the CodeScoring scan jobs run in, with registry and tag or digest. It needs curl, ca-certificates, jq, ruby and git; the agent is downloaded into it at run time. Empty: codescoring-scan:2026.08.30 from the product registry, the image this release ships. Section “Scan jobs”. |
| “Registry login”, “Registry password” | Login and password or token for the registry of the scan job image, or references to the CI/CD variables that hold them. The credentials are passed only when both are filled in. The password is not shown after saving. Section “Scan jobs”. |
| “Expand $ in the registry login and password” | On (default): the login and the password are $NAME references to CI/CD variables of the scanned project or its group. Off: they are the values themselves. Section “Scan jobs”. |
| “SBOM format” | CycloneDX version the SBOM is written in: cyclonedx_v1_4_json, cyclonedx_v1_5_json, cyclonedx_v1_6_json, cyclonedx_v1_6_ext_json (CodeScoring’s extension of 1.6 with its GOST properties) or cyclonedx_v1_7_json. Every version lists the same components. Empty here and in the policy: CycloneDX 1.6 JSON. Section “Scan jobs”. |
“Test settings” asks the server for the agent version with the token and the trust setting of the form, so the address, the token and the certificate are checked at once. It also checks that the scan job image can be pulled, unless the jobs use the default image or the registry login and password are references to CI/CD variables.
The jobs receive FE_SCANS_CODESCORING_URL, FE_SCANS_CODESCORING_TLS_MODE and, with an authority named, FE_SCANS_CODESCORING_CA_CERT; FE_SCANS_CODESCORING_SCAN_STAGE and FE_SCANS_CODESCORING_BOM_FORMAT when the fields are filled in. FE_SCANS_CODESCORING_TOKEN is masked and reaches the mandated CodeScoring jobs only. Every job downloads the agent from the server on each run, so the agent version is the one the server publishes. The composition analysis reports into the CodeScoring project named after the project path slug and creates it when it is missing.
“Scan job image” is read while the job is rendered and written into the job as a literal value; the image and the registry login and password are read only from the integration on a group that mandates the scan (the group the policy is linked to, or a group above it), and a value on the scanned project’s own integration is ignored. “Scan stage” and “SBOM format” are project-wide defaults: a policy that names its own value wins, and the policy’s “SBOM format” list carries “Take it from the integration” to hand the decision back.
The policy’s “SCA” group sets the scan mode and target, the ignored paths, whether the dependency tree is resolved on the server, the stage, the SBOM format and extra agent arguments; the “Secrets” group picks the engines (gitleaks, trufflehog, kingfisher) and gives each a configuration and an ignore list.
PT AI
The full setup, the scan options and the troubleshooting of this integration are on the PT AI integration page.
The “Positive Technologies Application Inspector” integration serves the ptai scan. Its job, ptai_scan, uploads the sources of the commit to a PT AI server with the aictl client, into a project named after the full project path with : in place of /, waits for the scan and publishes a test report and a SAST security report, so the findings reach the vulnerability report. White box and black box are parts of one scan: the white-box modules always run, and a website address adds the black box to them. There is no findings threshold: the job fails when the scan fails or the project’s security policy on the PT AI server rejects it.
The integration is configured on a project or a group, in “Settings” → “Integrations” → “Positive Technologies Application Inspector”, and holds the connection only: “Server URL”, “API token”, “Certificate trust” with “Certificate authority”, and the “Scan jobs” section with the job image and the registry login and password. The “Scan jobs” section is read from the integration of the group that owns the policy; the connection from the scanned project’s integration. The job receives FE_SCANS_PTAI_SERVER_URL, FE_SCANS_PTAI_TLS_MODE and, with an authority named, FE_SCANS_PTAI_CA_CERT; FE_SCANS_PTAI_TOKEN is masked and reaches the mandated ptai_scan job only.
What is scanned is set in the policy: the modules and languages, .gitignore, the dependency download, a settings file of your own, and the black box with its sign-in and proxy. The policy names passwords and cookies as $NAME references to CI/CD variables of the scanned project. The integration’s settings are refused in a policy.
DefectDojo
The full setup, the entity mapping and the troubleshooting of this integration are on the DefectDojo integration page.
The DefectDojo integration sends the security reports of a pipeline to a DefectDojo server. The reports go as the jobs published them, in the native report formats, through the server’s reimport endpoint:
| Report type of the artifact | Scan type in DefectDojo |
|---|---|
sast | GitLab SAST Report |
secret_detection | GitLab Secret Detection Report |
dependency_scanning | GitLab Dependency Scanning Report |
container_scanning | GitLab Container Scan |
dast | GitLab DAST Report |
The mandated scans publish these types (Opengrep and PT AI a sast report, Trivy dependency_scanning, secret_detection and container_scanning, CodeScoring dependency_scanning and secret_detection), and a job of the project’s own .gitlab-ci.yml that publishes one is uploaded the same way. PT AI’s report is not imported: PT AI writes scan.status: failure into it even for a finished scan.
The integration is configured on a project or a group in “Settings” → “Integrations” → “DefectDojo”, and for the whole instance in “Admin” → “Settings” → “Integrations” → “DefectDojo”. Its “Import defaults” are the mapping every upload uses:
| Field | Content |
|---|---|
| “DefectDojo URL” | Base URL of the DefectDojo server, for example https://defectdojo.example.com. Required. Section “Connection”. |
| “API token” | Token the uploads authenticate with. Required. Section “Connection”. |
| “Certificate trust” | How this instance decides whether to trust the server: “Trust what this instance already trusts” (default), “Trust the certificate authority below”, “Do not verify the certificate”. The connection is made from the instance, so verification can be switched off; the upload is then open to interception, and the reports carry everything the scanners found. Section “Certificate trust”. |
| “Certificate authority” | PEM certificate of the authority that signed the server’s certificate. Read only with “Trust the certificate authority below”, and required then. Section “Certificate trust”. |
| “Product name” | The DefectDojo product the reports go into. Empty: the full path of the project. Section “Import defaults”. |
| “Product type name” | The product type a product is created in when it is missing. Section “Import defaults”. |
| “Engagement name” | The engagement the reports go into. Empty: the branch or tag the pipeline ran on. Section “Import defaults”. |
| “Minimum severity” | Findings below it are left out of the import: Info (default), Low, Medium, High, Critical. Section “Import defaults”. |
| “Auto-create context” | “Create the product and engagement if they do not exist”. On by default. Section “Import defaults”. |
| “Imported findings” | “Mark imported findings as active”. On by default. Section “Import defaults”. |
| “Verified findings” | “Mark imported findings as verified”. Off by default. Section “Import defaults”. |
| “Close old findings” | “Close findings that are no longer reported”. On by default. Section “Import defaults”. |
Saving a form with settings of its own asks the server whether the mapping can be used: a rejected token, a missing product while “Auto-create context” is off, a missing product type while it is on, and a missing engagement while it is off are each refused with a message naming the product or the engagement. A server that cannot be asked does not block the save. “Test settings”, offered on a project integration, asks the same questions and reports a server that cannot be asked as well.
An upload starts when a job that published one of the report types above finishes in a project with an active DefectDojo integration, its own or inherited. One upload runs per pipeline; a further job finishing in the same pipeline reruns it once. Every report of the latest run of each job goes into the product and engagement of the form, into a test named after the job, dated by the day the job finished, so a rerun of a scan updates the same test, and its findings are not filed twice. The commit, the branch, the pipeline number, the short commit as the version and the project address are written onto the engagement. A report of a scan that did not run, a placeholder the job published so that the pipeline widgets show something, is not imported, because “Close old findings” would otherwise close every finding of the last real scan.
A server answer of 429 or 5xx and a timeout are retried after 60, 120 and 240 seconds; an upload waits up to 600 seconds for one report. Any other refusal is final, and only the project can act on it: the pipeline page shows the alert “Security report upload warnings” with one line per report that did not reach the server:
DefectDojo did not receive the report of job "opengrep_sast_junit" (GitLab SAST Report): DefectDojo returned HTTP 400: Product "group/project" does not exist and no product_type_name provided to create the new product inThe reason is the server’s own message, up to 500 characters, or one of blocked URL: … for an address the instance is not allowed to reach, certificate authority: … for a certificate that could not be read, and the scan did not run, so its placeholder report was not imported. Once the retries are spent, the page shows one more line: DefectDojo upload of this pipeline's security reports failed and the retries are spent: …. A line about a report is removed when a later run delivers that report. The full answer of the server is in the application log.
Severity in a custom JUnit report
The scan jobs write the severity of each finding into their JUnit test report, and the pipeline’s “Tests” tab shows it next to the test case. The “Severity” column is also shown for JUnit reports that jobs from the project’s .gitlab-ci.yml publish, when their test cases carry a severity property:
<testcase classname="custom" name="Hard-coded password [config/app.yml:12]">
<properties>
<property name="severity" value="high"/>
</properties>
<failure message="Hard-coded password"/>
</testcase>The tab reads the severity from this property only; severity labels at the beginning of test case names are ignored. The property name and its value are case-insensitive, and a valid value is one of critical, high, medium, low, info and unknown. The tab shows the “Severity” column for a suite where at least one test case has a valid value. In such a suite, test cases with a missing or invalid severity value (such as severe, or high with leading and trailing spaces) are shown as “Unknown”. The “Severity” column is not displayed for suites with no valid severity values.
When at least one test case in the suite has a valid severity and at least one test case failed or errored, the tab shows the “Vulnerabilities” block. It groups the failed and errored test cases by severity. A test case with a missing or invalid severity is counted there as “Unknown”.
In the pipeline summary, the “Vulnerabilities” block appears only when at least one failed or errored test case has a severity other than “Unknown”. It counts the failed and errored test cases of every job. A test case of a job whose report has no severity, an RSpec or Jest job for example, is counted as “Unknown”.