Skip to content

✨ gitlab: add 12 supply-chain security checks for push rules, CI/CD, and webhooks#2976

Open
tas50 wants to merge 1 commit into
mainfrom
worktree-gitlab-tier1-checks
Open

✨ gitlab: add 12 supply-chain security checks for push rules, CI/CD, and webhooks#2976
tas50 wants to merge 1 commit into
mainfrom
worktree-gitlab-tier1-checks

Conversation

@tas50

@tas50 tas50 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

Adds 12 Tier 1 security checks to mondoo-gitlab-security covering three GitLab subsystems the policy did not previously touch: push rules, CI/CD variables/tokens, and webhooks/merge controls. Every check ships with a GitLab runtime variant plus Terraform HCL/plan/state variants and verified compliance tags. Policy bumped to 1.9.0.

Checks added

Push Rules (Premium+, gitlab_project_push_rules)

  • push-rule-prevent-secrets (impact 90) — reject files matching secret patterns
  • push-rule-reject-unsigned-commits (80) — require signed commits
  • push-rule-committer-check (70) — committer must be a verified GitLab user
  • push-rule-member-check (70) — commit author must be a GitLab user

Secret detection

  • secret-push-protection (85, Ultimate) — pre-receive secret detection (pre_receive_secret_detection_enabled)

CI/CD Security

  • ci-variables-masked (80) — variables masked in job logs
  • ci-variables-protected (70) — variables scoped to protected refs
  • job-token-scope-enabled (80) — restrict inbound CI/CD job-token access (lateral-movement prevention)
  • webhook-ssl-verification (70) — enforce TLS verification on webhook delivery
  • no-public-jobs (70) — job logs/artifacts not public to non-members

Merge Request Security

  • no-merge-on-skipped-pipeline (80) — block merge when the pipeline is skipped
  • discussions-resolved (60) — all threads resolved before merge

Compliance tags

Mapped across the 13 frameworks the policy already tags, by control objective (each verified against the framework control text, false where no strict fit):

  • Secret prevention → ISO 8.12 (DLP), NIST CSF PR.DS-5, 800-53 IA-5, PCI 8.6.2, CCM DSP-17
  • Commit authenticity / change control → 800-53 SI-7, ISO 8.9, SOC 2 CC6.8.2 (integrity family, matching existing MR-approval checks)
  • Least privilege → 800-53 AC-6, 800-171 3.1.5 (matching existing deploy-key check)
  • TLS in transit → 800-53 SC-8, ISO 8.24, HIPAA 164.312(e)(1), NIS2 21.2(h), SOC 2 CC6.7.1
  • Info disclosure → 800-53 AC-3, ISO 8.3 (access-control family, matching visibility checks)

Validation

  • cnspec policy lint content/mondoo-gitlab-security.mql.yaml → valid
  • python3 content/validation/validate_remediation_commands.py gitlab → all glab commands PASS
  • The three newest provider fields (jobTokenScope, publicJobs, preReceiveSecretDetectionEnabled) required a local gitlab provider rebuild from ~/dev/mql; they are present in the provider source and Go implementation.

🤖 Generated with Claude Code

…and webhooks

Adds Tier 1 hardening checks across three previously-uncovered GitLab
subsystems, each with GitLab runtime + Terraform HCL/plan/state variants
and verified compliance tags:

Push rules (Premium+):
- push-rule-prevent-secrets      reject files matching secret patterns
- push-rule-reject-unsigned-commits
- push-rule-committer-check      committer is a verified GitLab user
- push-rule-member-check         author is a GitLab user

Secret detection:
- secret-push-protection         pre-receive secret detection (Ultimate)

CI/CD security:
- ci-variables-masked            variables hidden in job logs
- ci-variables-protected         variables scoped to protected refs
- job-token-scope-enabled        restrict inbound job-token access
- webhook-ssl-verification       enforce TLS verification on webhooks
- no-public-jobs                 job logs not public to non-members

Merge controls:
- no-merge-on-skipped-pipeline   block merge when pipeline is skipped
- discussions-resolved           all threads resolved before merge

Registered under new "Push Rules" and "CI/CD Security" groups plus the
existing Merge Request Security and Security Scanning groups. Bumps the
policy to 1.9.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@mondoo-code-review mondoo-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well-structured bulk addition of 12 GitLab security checks following consistent patterns with one minor inconsistency.

### Audit via Console

1. In GitLab, navigate to your project.
2. Go to **Settings** > **Repository**.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 suggestion — The Terraform HCL/Plan/State variants for secret-push-protection filter on gitlab_project (a broad resource), whereas the other new checks that have dedicated resource types (e.g., gitlab_project_push_rules, gitlab_project_variable, gitlab_project_hook) correctly filter on those specific types. This means the secret-push-protection Terraform checks will match any gitlab_project resource and assert pre_receive_secret_detection_enabled == true on all of them — which may be intentional since this is a project-level attribute, but it could cause false positives for projects where this Ultimate-only feature doesn't apply. Consider whether the Terraform variants should also gate on the plan (like the GitLab variant gates on gitlab.namespace.plan == "ultimate").


A passing project returns `false`. A failing project returns `true`.
remediation:
- id: gitlab

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 warning — The no-public-jobs Terraform HCL check uses arguments["public_jobs"] == false, but Terraform treats an omitted attribute as its default value (which for public_jobs in the GitLab provider is true). If a user doesn't set public_jobs at all, the attribute won't appear in arguments and the check could pass vacuously via .all() on an empty match. The same pattern affects no-merge-on-skipped-pipeline HCL variant with allow_merge_on_skipped_pipeline. Consider whether omitted attributes should be treated as a failure.

This check ensures that the project requires all merge request discussions to be resolved before a merge request can be merged. This guarantees that review comments, including those raising security concerns, are addressed rather than merged past.

**Why this matters**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 suggestion — The no-merge-on-skipped-pipeline Terraform variants use != true while the GitLab variant uses == false. The != true pattern is more permissive (also passes for null/absent). This is likely intentional for Terraform where the field may be absent, but it's worth confirming this asymmetry is deliberate, as == false would be more strict and consistent with the GitLab variant's intent.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Test Results

  1 files  ±0   44 suites  ±0   1m 33s ⏱️ +8s
856 tests ±0  855 ✅ ±0  1 💤 ±0  0 ❌ ±0 
857 runs  ±0  856 ✅ ±0  1 💤 ±0  0 ❌ ±0 

Results for commit 3ebbfcf. ± Comparison against base commit 65c926f.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant