glsec

Rules / GL008

GL008 Security scan job silenced

Severity: warn
OWASP: CICD-SEC-1 – Insufficient Flow Control Mechanisms

What glsec checks

glsec flags any of GitLab's predefined security scan jobs that has been silenced — its failures ignored, or the job kept from running at all:

Form Effect
allow_failure: true The scan runs, but its failure does not block the pipeline
when: manual (job has no rules:) The scan never runs on its own
rules: whose only entry is an unconditional when: never The job is switched off in every context
rules: whose only entry is an unconditional when: manual The job never runs on its own

The job names, and the templates that define them:

Job name Template
sast (configuration-only, not checked) Security/SAST.gitlab-ci.yml
iac-sast, kics-iac-sast Security/SAST-IaC.gitlab-ci.yml
secret_detection Security/Secret-Detection.gitlab-ci.yml
dast Security/DAST.gitlab-ci.yml
dast_api Security/DAST-API.gitlab-ci.yml
container_scanning Security/Container-Scanning.gitlab-ci.yml
dependency_scanning (configuration-only, not checked) Security/Dependency-Scanning.gitlab-ci.yml
semgrep-sast, gitlab-advanced-sast, gitlab-advanced-sast-cpp, gitlab-advanced-sast-ext, gosec-sast, spotbugs-sast, bandit-sast, eslint-sast, kubesec-sast, pmd-apex-sast, security-code-scan-sast, sobelow-sast Security/SAST.gitlab-ci.yml
gemnasium-dependency_scanning, gemnasium-maven-dependency_scanning, gemnasium-python-dependency_scanning Security/Dependency-Scanning.gitlab-ci.yml
coverage_fuzzing Security/Coverage-Fuzzing.gitlab-ci.yml
api_fuzzing Security/API-Fuzzing.gitlab-ci.yml
license_scanning Security/License-Scanning.gitlab-ci.yml

The analyzer jobs are the ones that actually run the scan, so switching one of them off is the same as switching the scan off. The names are taken from the current templates on gitlab.com; the analyzers deprecated in GitLab 16.8 are not listed. (sast-iac is the template file SAST-IaC.gitlab-ci.yml, not a job — the jobs it creates are iac-sast and kics-iac-sast.)

The two base jobs, sast and dependency_scanning, are configuration-only and are not checked at all. In the current templates both carry rules: - when: never and a script that just exits 1; the analyzers inherit from them through .sast-analyzer / .ds-analyzer, which set allow_failure: true themselves. So sast: allow_failure: true changes nothing, and sast: rules: [when: never] is already the template default and switches no analyzer off, since every analyzer carries its own rules:. Switching a scan off is covered by the analyzer jobs above and by SAST_DISABLED and friends (GL082).

The allow_failure: {exit_codes: [...]} form (exit-code-specific) is not flagged — that is a deliberate choice, not a blanket suppression.

Neither is a template-defaulted allow_failure: true. .sast-analyzer, .ds-analyzer, .secret-analyzer, container_scanning and iac-sast already set it, and every analyzer job above extends one of those hidden jobs, so a pipeline that sets it again on semgrep-sast or secret_detection changes nothing and is not reported. The two configuration-only base jobs are absent from that list because they are not checked at all, which is a stronger statement than an exemption from this one check.

What is deliberately not flagged

The rules: check is narrow, because most when: never entries on a scan job are legitimate:

secret_detection:
  rules:
    - if: $SECRET_DETECTION_DISABLED   # the template's own kill switch — keeping
      when: never                      # it in an override is idiomatic
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

dast:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - when: never                      # "otherwise don't run" — scoping, not disabling

A conditional when: never scopes the job; only a lone, unconditional entry disables it outright. The dangerous half of the first example — actually setting SECRET_DETECTION_DISABLED — is GL082's job.

Trigger example

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/DAST.gitlab-ci.yml
  - template: Security/DAST-API.gitlab-ci.yml

dast:
  allow_failure: true   # scan failures are silently ignored
  script:
    - ./build.sh

semgrep-sast:
  rules:
    - when: never       # the analyzer that actually scans, switched off
  script:
    - ./build.sh

secret_detection:
  when: manual          # never runs unless somebody clicks it
  script:
    - ./build.sh

dast_api:
  rules:
    - when: never       # switched off outright
  script:
    - ./build.sh

Safe alternative

Remove allow_failure: true so the pipeline fails when the security scan fails:

include:
  - template: Security/SAST.gitlab-ci.yml

# No allow_failure override — pipeline fails if SAST finds issues

If you need the pipeline to pass during a transition period, use a GitLab security policy to enforce scan requirements separately from pipeline status, rather than silencing failures.

Why this matters

When a GitLab security scan job has allow_failure: true:

This is especially dangerous when the job fails due to a misconfiguration (wrong image, expired token) rather than an actual scan finding — the failure is invisible.

Documentation for glsec 1.23.0. Source of this page · Rule implementation