-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Is your feature request related to a problem? Please describe.
GitLab security scanners (SAST, DAST, Secret Detection, etc.) use predefined CI/CD variables to configure their behavior. An attacker who can modify the .gitlab-ci.yml can override these variables to:
- Neutralize scanners: Set
SECURE_ANALYZERS_PREFIXto a registry serving fake scanner images that always report "0 vulnerabilities" - Exclude paths from scanning: Set
SAST_EXCLUDED_PATHSto cover the entire codebase - Disable scanners entirely: Set
SECRET_DETECTION_DISABLED: "true"orSAST_DISABLED: "true"
This attack is particularly insidious because the pipeline continues to run and appears successful — security checks pass, but no actual scanning occurs.
Describe the solution you'd like
Add a new control pipelineMustNotOverrideSecurityVariables that:
- Scans global
variables:and per-jobvariables:for known GitLab security variables - Reports when these variables are redefined in the CI configuration file (they should only be set in GitLab CI/CD Settings as protected variables)
- Provides a configurable list of protected variable names
Configuration in .plumber.yaml
controls:
pipelineMustNotOverrideSecurityVariables:
enabled: true
# Variables that must not be defined in .gitlab-ci.yml
# They should only be set in GitLab CI/CD Settings > Variables
protectedVariables:
- SECURE_ANALYZERS_PREFIX
- SAST_DISABLED
- SAST_EXCLUDED_PATHS
- SAST_EXCLUDED_ANALYZERS
- SECRET_DETECTION_DISABLED
- SECRET_DETECTION_EXCLUDED_PATHS
- CONTAINER_SCANNING_DISABLED
- DAST_DISABLED
- DEPENDENCY_SCANNING_DISABLED
- LICENSE_SCANNING_DISABLEDImplementation Hints
These are just ideas. Feel free to change the implementation.
- Data source: The
PipelineOriginDatacollector provides the merged CI config that contains allvariables:blocks (global and per-job). The raw YAML may need to be inspected rather than the merged result, to distinguish variables set in the file vs. inherited from GitLab settings. - New control file: Create
control/controlGitlabPipelineSecurityVariables.go. - Logic:
- Parse the CI configuration's
variables:sections (global + per-job) - For each variable, check if its key matches any entry in
protectedVariables - If found, create an issue with the variable name, its value, and the location (global or job name)
- Parse the CI configuration's
- Compliance: 0% if any protected variable is overridden, 100% otherwise.
- Nuance: Some variables like
SECURE_ANALYZERS_PREFIXmight legitimately be set to the project's own registry. Consider allowing anallowedValuesmap for specific variables in a future iteration.
Files Touched
control/controlGitlabPipelineSecurityVariables.go(new control)control/types.go(add result field toAnalysisResult)control/task.go(wire the new control inRunAnalysis())configuration/plumberconfig.go(add config struct and getter).plumber.yaml(add default config section with sensible defaults)cmd/analyze.go(add output formatting)
Why It's Valuable
This attack can completely neutralize an organization's security scanning investment while maintaining a false sense of security ("all pipelines are green"). It's especially dangerous because it doesn't trigger any visible error — the scanners simply don't scan. This complements the existing containerImageMustComeFromAuthorizedSources control which detects untrusted registries but doesn't specifically target the scanner override pattern.