Security Policies, Scan Execution, Pipeline Execution, Approval Policies, and Compliance Controls: Concepts, Architecture, and Mental Model
Build a precise mental model of GitLab security policy projects, policy scope and inheritance, scan and pipeline enforcement, merge-request approval policies, compliance frameworks, evidence, and separation of duties.
Learning objectives
- Separate a security policy project from an ordinary application project and from project-owned .gitlab-ci.yml.
- Explain policy linking, inheritance, policy_scope, update propagation, and separation of duties.
- Distinguish scan execution, pipeline execution, scheduled pipeline execution, and merge request approval policies by enforcement point.
- Place compliance frameworks and controls correctly relative to security policies.
- Inspect policy state and expected evidence before making any governance change.
1. The practical problem: one project can be configured correctly while the organization is still unsafe
Earlier chapters taught scanners, vulnerability evidence, pipelines, protected resources, and approvals inside individual projects. Large organizations need something stronger than copying the same YAML into hundreds of repositories. A central requirement such as “every default-branch pipeline must run a trusted security check” must survive project refactors, onboarding of new repositories, and ordinary maintainer changes.
GitLab security policies solve that organizational problem by separating policy intent and ownership from the application project’s ordinary CI configuration. This separation is powerful, but it creates new failure modes: a policy can exist without being linked, inherit farther than expected, conflict with project CI, depend on a file users cannot read, or silently become an unaudited exception process.
2. Mental model: requirement → policy project → assignment → evaluation → evidence
A security policy project is a special GitLab
project that stores policy-as-code in
.gitlab/security-policies/policy.yml. Linking that
policy project to a group, subgroup, or project makes the linked
objects enforceable. The link establishes the organizational
relationship; each policy’s policy_scope can then
narrow which descendants are actually affected.
flowchart TD A[Security / compliance requirement] --> B[Policy intent] B --> C[Security policy project policy.yml] C --> D[Link to group / subgroup / project] D --> E[Inheritance + policy_scope] E --> F[Scan execution policy] E --> G[Pipeline execution policy] E --> H[MR approval policy] F --> I[Security scan jobs] G --> J[Enforced CI/CD jobs] H --> K[Approval / merge constraints] I --> L[Evidence] J --> L K --> L L --> M[Audit / exception review]
The policy project does not become the application repository. It contributes centrally governed behavior at evaluation time. The application project still owns its source, merge requests, ordinary CI jobs, runners, packages, and environments. The trust boundary is therefore explicit: policy maintainers govern constraints; project maintainers build software inside those constraints.
3. Linking, inheritance, and scope are three different concepts
Linking associates a security policy project with an organizational unit. Inheritance means a linked group policy applies to descendant subgroups and projects by default. Policy scope narrows a specific policy to selected projects, groups, or compliance frameworks.
projects: { including: [] } is treated like the scope
field was omitted; it does not mean “apply to zero
projects.” To disable a policy, set enabled: false.
| Question | Correct GitLab surface |
|---|---|
| Which organizational units know about this policy project? | Policy-project link. |
| Which descendants receive enforcement by default? | Inheritance from the linked group/subgroup. |
| Which subset should this policy actually target? | policy_scope. |
| Who is allowed to change the link? |
Owner or custom role with
manage_security_policy_link.
|
4. Choose the enforcement mechanism by the thing you must control
All of the following are Ultimate security-policy types, but they solve different problems:
| Policy type | What it enforces | When it is the right tool |
|---|---|---|
| Scan execution | GitLab security scans in pipelines or on a schedule. | You need a supported GitLab scanner applied consistently with relatively little customization. |
| Pipeline execution | Custom CI/CD configuration/jobs injected or used to replace project CI according to strategy. | You need custom compliance jobs, third-party tools, pre/post gates, or stronger CI behavior control. |
| Scheduled pipeline execution | Independent policy-created pipelines on daily/weekly/monthly cadence. | You need centrally scheduled CI even when a project has no new commits; GA since GitLab 19.2. |
| MR approval | Approval rules and project settings based on scanner/branch conditions. | You need merge prevention or approvals after completed evidence is evaluated. |
Do not use a merge-request approval policy to “run” a scanner. It consumes completed pipeline evidence. Conversely, a scan execution policy runs a scanner but does not by itself express every merge-approval decision.
5. Evaluation timing explains many surprises
Policy evaluation is not one single moment. Scan and pipeline execution policies affect future pipeline creation. Merge request approval policies evaluate completed pipeline evidence and can require approvals when required scanner reports are missing. Protected-branch policy rules synchronize with a short delay. Policy changes merged through a security-policy-project merge request take effect after merge; direct commits to the policy YAML can take up to about ten minutes to propagate.
That timing matters during incidents: a pipeline already in progress is not rewritten because you changed policy. Record the policy commit SHA, target project/ref, pipeline ID, and observed enforcement state before concluding that GitLab ignored the change.
6. Separation of duties is part of the control, not an organizational preference
A control is weak if the same project maintainer being constrained
can silently change or unlink it. GitLab recommends central policy
ownership, protected default branches in security policy projects,
approval rules for policy changes, and restricted policy-management
permissions. Linking requires Owner or a custom role with
manage_security_policy_link. Policy creation/management
roles also depend on whether enforcement is at group or project
scope.
7. Compliance frameworks label scope; security policies enforce behavior
A compliance framework is a top-level-group construct that labels projects with compliance requirements. Frameworks are Premium/Ultimate. In Ultimate, frameworks can be used as policy scope and can carry GitLab compliance controls. This makes a useful operating model: framework answers “which projects are regulated?” while a security policy answers “what must GitLab enforce for those projects?”
On Self-Managed/Dedicated Ultimate, administrators can also designate a centralized compliance and security policy group for instance-wide policy/framework governance. That is an administrative platform feature, not a mandatory developer exercise.
8. Read-only inspection comes before policy editing
On an Ultimate environment, inspect
Secure → Policies for current policy status and
linked policy project; inspect the security policy project default
branch and policy.yml; inspect the target project’s
framework labels; and inspect recent pipelines/MRs for
policy-originated jobs or approvals. On Free, use the same checklist
against the fixtures in Lesson 2.
# Read-only Git evidence in a policy fixture repository
git rev-parse HEAD
git log -1 --oneline -- .gitlab/security-policies/policy.yml
git diff -- .gitlab/security-policies/policy.yml
# Never print tokens or dump complete environments while collecting policy evidence.
9. DevOps connection: central policy expands capability and blast radius
A central policy can protect hundreds of projects, but one bad scope, inaccessible policy file, duplicated job, or incorrect approval condition can also stop hundreds of delivery pipelines. Treat policy changes like production code: version them, review them, test them on a small disposable scope, predict affected projects, collect audit evidence, and roll them out incrementally.
Knowledge check
What is the difference between linking a security policy project and setting policy_scope?
The link establishes which organizational units can be enforced by that policy project; policy_scope narrows a particular policy within that linked/inherited population.
Does projects: { including: [] } mean the policy applies to no projects?
No. An empty collection is treated like the scope was omitted, so it is unrestricted for that dimension. Use enabled: false to disable a policy.
Which policy type should enforce a custom license-validation script before project jobs run?
A pipeline execution policy, because it can enforce custom CI/CD jobs and scripts.
Why can an MR approval policy block when scanner reports are missing?
It relies on completed evidence. Missing required reports leave insufficient comparison evidence, so approval is required by default to fail safely.
Why is protecting the security policy project default branch important?
Otherwise users who should be constrained by the policy may be able to alter the policy itself, defeating separation of duties.
Summary and bridge
Policy intent, assignment, scope, enforcement type, evidence, and ownership are separate dimensions. Lesson 2 turns this model into a disposable Free-compatible policy-as-code exercise, with an optional Ultimate live path only if a safe trial or licensed sandbox already exists.
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.
- GitLab 19.3 release
- Security policies
- Policy enforcement
- Security policy projects
- Scan execution policies
- Pipeline execution policies
- Scheduled pipeline execution policies
- Merge request approval policies
- Compliance frameworks
- Compliance and security policy groups
- Compliance and policy settings API
- Audit event types
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.