Chapter 27Lesson 04~310 minutes

Security Policies, Scan Execution, Pipeline Execution, Approval Policies, and Compliance Controls: Diagnostics, Failure Modes, Security, and Performance

Diagnose unassigned policies, permission and separation-of-duties failures, duplicated jobs, blocked merge requests, stale policy propagation, tier/version mismatches, and unaudited exceptions.

DiagnosticsPolicy assignmentMR approvalsAudit evidenceFailure modes

Learning objectives

  • Use a repeatable policy diagnostic sequence that preserves scope, version, permissions, pipeline/MR evidence, and policy commit identity.
  • Diagnose a policy that exists but is not assigned or is scoped incorrectly.
  • Explain how local project policy, duplicated CI, missing reports, and inaccessible policy content can break enforcement.
  • Separate syntax errors from Ultimate/tier/version/role limitations.
  • Treat exceptions, bypasses, policy changes, and unlink/delete operations as security-sensitive changes.
Availability baseline — verified 2026-08-22 against GitLab 19.3. Security policies (scan execution, pipeline execution, merge request approval, scheduled pipeline execution, vulnerability management) and security policy projects are currently Ultimate across GitLab.com, Self-Managed, and Dedicated. Compliance frameworks are Premium/Ultimate; using frameworks as policy-enforcement scope and broader security/compliance controls is an Ultimate operating model. Instance-wide compliance and security policy groups are Ultimate on Self-Managed/Dedicated and administrator-controlled. Therefore the mandatory chapter path is a Free-compatible local/CI fixture simulation; live enforcement is optional only when a disposable Ultimate/trial environment and required roles already exist.

1. Diagnostic sequence: preserve identity before changing policy

Use the same sequence every time:

  1. Preserve evidence: GitLab version/offering/tier, linked unit, target project/ref/MR, pipeline/job IDs, policy-project path and policy commit SHA.
  2. Identify scope: which group/project/framework should match and which should not?
  3. Inspect ownership: who can change the policy link, policy branch, target project CI, bypass, and approval state?
  4. Inspect evaluation evidence: policy page, job graph/logs, completed scanner reports, MR approval state, audit events.
  5. Choose the least destructive correction.
  6. Verify independently: new pipeline/MR plus read-back of policy/link/audit state.

2. Failure: the policy exists but is not assigned to the intended scope

Symptom: the security policy project contains valid YAML, but the target project shows no policy-originated job or approval rule. Do not edit the policy first. Check whether the security policy project is linked to the correct group/project and whether inheritance reaches the target. Then check policy_scope against concrete project/group/framework IDs.

# Evidence worksheet
policy_project: training/security-policy-management
target_project: training/platform/payments-api
expected_link: training/platform
expected_project_id: 101
observed_policy_job: absent
observed_mr_rule: absent
next_check: link + scope before YAML semantics

3. Failure: the project maintainer can alter the control that should constrain the project

This is a design failure even if pipelines are green. Check whether the policy lives in a separate security-owned project, whether its default branch is protected, whether policy changes require independent approval, and whether custom roles restrict project-level policy creation or modification where that could interfere with group policy.

GitLab explicitly warns that project maintainers can create project policies that interfere with group policy execution. Critical controls therefore need deliberate permission design and monitoring—not merely a central YAML file.

4. Failure: policy unexpectedly duplicates jobs or blocks safe changes

Common causes include project CI already defining an equivalent job, multiple policy layers injecting similar jobs, old compliance-pipeline configuration coexisting with pipeline execution policies, or incompatible stage definitions. Current pipeline execution policies default suffix: on_conflict so name collisions are renamed, but duplicate work can still run.

Production pattern: inventory existing project/shared/compliance CI before rollout. GitLab warns that legacy compliance pipelines combined with pipeline execution policies can create duplicated jobs, missing checks, or unpredictable behavior. Migrate rather than stack two enforcement systems.

5. Intentionally broken example: policy content file renamed

Suppose the policy still references policy-ci.yml, but the security CI project renamed the file to policy-ci-v2.yml. Current GitLab documents that deleting or renaming the referenced pipeline execution file can prevent pipelines in enforced projects from working.

pipeline_execution_policy:
  - name: Enforce preflight
    enabled: true
    pipeline_config_strategy: inject_policy
    content:
      include:
        - project: training/security-policy-ci
          file: policy-ci.yml   # stale path
          ref: v2.0.0

Preserve the pipeline-creation error, policy commit, referenced project/ref/path, and triggering user. Verify both existence and read access. The least-destructive correction is to publish/restore the intended immutable file or update the policy through review—not grant broad repository access or disable enforcement.

6. Failure: an MR approval policy blocks because evidence is missing

MR approval policies that depend on security scanners require completed reports. If required scanner output is absent, the policy can require approval by default because GitLab lacks a reliable comparison. That is not automatically a policy syntax error. Check the merge-base pipeline, scanner job completion, report artifacts, and target/source branch coverage first.

GitLab also states that MR approval policies do not authenticate the integrity of scanner reports by themselves. Scanner trust and runner isolation still matter.

7. Failure: tier/version/role mismatch is misdiagnosed as YAML syntax

If a Free project cannot open or apply security policy features, that is expected product availability, not invalid YAML. If a Self-Managed instance is older than the behavior documented here, inspect that instance’s versioned docs. Scheduled pipeline execution policies, for example, became GA only in GitLab 19.2. Instance-wide compliance/security policy groups are Ultimate Self-Managed/Dedicated admin features and became GA in 18.5.

8. Failure: exception has no owner, expiry, or audit trail

A bypass can become a shadow policy. Preserve who requested it, why, exact project/branch/token/service-account scope, approval, expiry/review date, compensating control, and evidence that the exception was removed. Current GitLab has audit event types for security-policy create/update/delete, policy-project changes, bypasses, violations, failures, skipped policy pipelines, and invalid YAML; availability of stored/streamed audit events depends on tier and event type.

9. Failure: rollout looks inconsistent during propagation

Group-scale policy assignment and MR synchronization can take time. Direct commits to policy YAML can take up to about ten minutes to propagate, while policy changes merged through an MR take effect after merge. Do not repeatedly toggle policies during this window. Record time, policy SHA, target project, and one controlled pipeline after the expected propagation period.

10. Security-sensitive/destructive actions

Linking/unlinking policy projects, changing policy-project branch protection, granting custom policy permissions, configuring bypasses, deleting policies, changing approval settings, assigning compliance frameworks, designating a Self-Managed compliance/security policy group, and deleting disposable groups/projects are governance changes. Perform them only in disposable environments with before/after state and rollback context.

Never troubleshoot by printing tokens or full environments. Policy YAML is not a secret store, CI logs can expose careless debug output, and bypass credentials should be revoked/rotated if leaked.

11. Verification checklist

  • Policy project/link is the intended one.
  • Target project is inside the effective inheritance + scope set.
  • Policy commit SHA matches the version you intended to test.
  • Triggering user can read referenced policy CI where required.
  • Policy jobs/approvals match the correct pipeline/MR SHA.
  • Missing reports are not mistaken for a policy syntax failure.
  • Exception/bypass has owner, rationale, expiry, and evidence.
  • Audit/read-back state confirms the final result.

Knowledge check

A valid policy YAML has no effect on one project. What should you inspect before changing YAML?

Why can a renamed policy CI file stop target pipelines?

An MR approval policy requires approval because no scanner report exists. Is this necessarily a policy bug?

What is wrong with an exception that says only “temporary bypass”?

Why should old compliance pipelines be inventoried before pipeline execution policy rollout?

If a real bypass token leaks during troubleshooting, what is the first security response?

Summary and bridge

Policy incidents are usually scope, timing, permission, evidence, or composition problems—not just YAML problems. The checkpoint lab now combines policy selection, scope prediction, violation handling, exception governance, and separation of duties into one operating exercise.

Primary sources and version notes

These lessons were finalized against current official GitLab documentation on 2026-08-22. Re-check tier, feature status, policy schema, permission, audit-event, and Self-Managed-version behavior before applying the same design later.

Next lesson

Checkpoint Lab

Design and validate a complete synthetic policy set with one violation, one governed exception, and explicit separation of duties.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.