doc/user/application_security/policies/_index.md
{{< details >}}
{{< /details >}}
Policies provide security and compliance teams with a way to enforce controls globally in their organization.
Security teams can ensure:
Compliance teams can enforce:
The following policy types are available:
policy_scope keywordUse the policy_scope keyword to enforce the policy on only those groups, projects, compliance
frameworks, or a combination, that you specify.
| Field | Type | Possible values | Description |
|---|---|---|---|
match_mode | string | all, any | Introduced in GitLab 18.10. Determines how the policy handles multiple scope conditions. Use all (default) to require that all conditions match, or any to require that at least one condition matches. |
compliance_frameworks | array | Not applicable | List of IDs of the compliance frameworks in scope for enforcement, in an array of objects with key id. |
projects | object | including, excluding | Use excluding: or including: then list the IDs of the projects you wish to include or exclude, in an array of objects with key id. You can also exclude projects by type using type: personal for personal projects or type: archived for archived projects. |
groups | object | including | Use including: then list the IDs of the groups you wish to include, in an array of objects with key id. Only groups linked to the same security policy project can be listed in the policy. |
policy_scopeWhen a policy_scope field is set to an empty collection ([]), it is treated as if the field
were omitted entirely. This means the policy applies to all projects without any restrictions.
Specifically:
projects: { including: [] } applies the policy to all projects, not to zero projects.groups: { including: [] } applies the policy to all groups, not to zero groups.compliance_frameworks: [] applies the policy to all projects, not to projects with no framework.This behavior maintains backward compatibility with existing policies that rely on having empty collections being treated as if the filter was not provided.
To prevent a policy from applying to any project, set enabled: false instead of
using an empty collection:
policy_scope:
projects:
including:
- id: 123
enabled: false # Disables the policy entirely
match_modeWhen you specify multiple scope conditions (for example, both projects and groups), the match_mode
field determines how these conditions are combined:
all (default): The policy applies only to projects that match all of the specified conditions.
This mode is more restrictive and maintains backward compatibility with existing policies.any: The policy applies to projects that match any of the specified conditions.
This mode is more permissive and useful when you want to target different sets of projects with a single policy.For example, if you specify both a list of including projects and a list of including groups:
match_mode: all, a project must be in the projects list and belong to one of the specified groups.match_mode: any, a project is in scope if it's in the projects list or belongs to one of the specified groups.When you combine excluding and including conditions with match_mode: any, be aware that
the excluding condition broadens the policy's reach. Because OR logic means the policy applies
if any condition matches, an excluding groups condition (which matches all projects
except those in the excluded groups) means the policy applies to most projects,
regardless of what is specified in including conditions.
For example, a policy that excludes group-2 from the groups list and includes specific projects group-1/project-1-1 and group-2/project-2-1:
policy_scope:
match_mode: any
groups:
excluding:
- id: 200 # group-2
projects:
including:
- id: 101 # group-1/project-1-1
- id: 201 # group-2/project-2-1
With this configuration, the policy applies not only to the two explicitly included projects, but
also to all other projects outside group-2 (such as group-1/project-1-2, which is not
listed in the including projects). The excluding groups condition matches any
project not in group-2, and with OR logic, a single match is sufficient for the policy to
apply.
In this example, the scan execution policy enforces a SAST scan in every release pipeline, on
every project with the compliance frameworks with an ID either 2 or 11 applied to them.
---
scan_execution_policy:
- name: Enforce specified scans in every release pipeline
description: This policy enforces a SAST scan for release branches
enabled: true
rules:
- type: pipeline
branches:
- release/*
actions:
- scan: sast
policy_scope:
compliance_frameworks:
- id: 2
- id: 11
In this example, the scan execution policy enforces a secret detection and SAST scan on pipelines
for the default branch, on all projects in the group with ID 203 (including all descendent
subgroups and their projects), excluding the project with ID 64.
- name: Enforce specified scans in every default branch pipeline
description: This policy enforces secret detection and SAST scans for the default branch
enabled: true
rules:
- type: pipeline
branches:
- main
actions:
- scan: secret_detection
- scan: sast
policy_scope:
groups:
including:
- id: 203
projects:
excluding:
- id: 64
In this example, the scan execution policy enforces a SAST scan on all projects except archived projects. This is useful when you have many archived projects that should not be scanned.
- name: Enforce SAST scan excluding archived projects
description: This policy enforces SAST scans but excludes archived projects
enabled: true
rules:
- type: pipeline
branches:
- main
actions:
- scan: sast
policy_scope:
projects:
excluding:
- type: archived
In this example, the scan execution policy uses match_mode: any to enforce a secret detection
scan on either specific high-priority projects or on all projects within specific groups. Without
match_mode: any, a project must be in the projects list and in one of the specified
groups for the policy to apply.
- name: Enforce secret detection on priority projects or security groups
description: This policy enforces secret detection on specific projects or all projects in security-focused groups
enabled: true
rules:
- type: pipeline
branches:
- main
actions:
- scan: secret_detection
policy_scope:
match_mode: any
projects:
including:
- id: 123 # High-priority project outside of security groups
- id: 456 # Another critical project
groups:
including:
- id: 78 # Security team's group
- id: 90 # Compliance team's group
Separation of duties is vital to successfully implementing policies. Implement policies that achieve the necessary compliance and security requirements, while allowing development teams to achieve their goals.
Security and compliance teams:
Development teams:
To enforce a security policy project on a group, subgroup, or project, you must have either:
manage_security_policy_link permission.The Owner role and custom roles with the manage_security_policy_link permission follow the standard hierarchy rules across groups, subgroups, and projects:
| Organization unit | Group owner or group manage_security_policy_link permission | Subgroup owner or subgroup manage_security_policy_link permission | Project owner or project manage_security_policy_link permission |
|---|---|---|---|
| Group | {{< yes >}} | {{< no >}} | {{< no >}} |
| Subgroup | {{< yes >}} | {{< yes >}} | {{< no >}} |
| Project | {{< yes >}} | {{< yes >}} | {{< yes >}} |
To create and manage security policies:
[!note] If you're not a group member, you may face limitations in adding or editing policies for your project. The ability to create and manage policies requires permissions to create projects in the group. Make sure you have the required permissions in the group, even when working with project-level policies.
When implementing policies, consider the following recommendations.
When specifying branch names in a policy, use a generic category of protected branches, such as default branch or all protected branches, not individual branch names.
A policy is enforced on a project only if the specified branch exists in that project. For example,
if your policy enforces rules on branch main but some projects in scope are using production as
their default branch, the policy is not applied for the latter.
In GitLab 17.3 and earlier, if you use push rules to
validate branch names
ensure they allow creation of branches with the prefix update-policy-. This branch naming prefix
is used when a security policy is created or amended. For example, update-policy-1659094451, where
1659094451 is the timestamp. If push rules block the creation of the branch the following error
occurs:
Branch name `update-policy-<timestamp>` does not follow the pattern `<branch_name_regex>`.
In GitLab 17.4 and later, security policy projects are excluded from push rules that enforce branch name validation.
To prevent the exposure of sensitive information that was intended to remain private in your security policy project, when you link security policy projects to other projects:
These recommendations prevent sensitive information exposure for the following reasons:
.gitlab/security-policies/policy.yml file. This includes linking a private security policy project to a public project, which can expose the policy contents to anyone who can access the public project.Project maintainers can create policies for projects that interfere with the execution of policies for groups. To limit who can modify policies for groups and ensure that compliance requirements are being met, when you implement critical security or compliance controls:
The Policies page displays deployed policies for all available environments. You can check a policy's information (for example, description or enforcement status), and create and edit deployed policies:
A green checkmark in the first column indicates that the policy is enabled and enforced on all groups and projects within its scope. A gray checkmark indicates that the policy is currently not enabled.
The policy editor has two modes:
You can switch between rule mode and YAML mode at any time. If your YAML has errors or unsupported data, rule mode turns off automatically. Fix the YAML first to use rule mode again.
Use the policy editor to create, edit, and delete policies:
In the top bar, select Search or go to and find your project.
Select Secure > Policies.
Select Configure with a merge request to save and apply the changes.
The policy's YAML is validated and any resulting errors are displayed.
Review and merge the resulting merge request.
If you are a project owner and a security policy project is not associated with this project, a security policy project is created and linked to this project when the merge request is created.
{{< history >}}
{{< /history >}}
The policy editor has two layouts that determine how rule mode and YAML mode are presented:
Standard editor: Displays rule mode and YAML mode as separate tabs. Select a tab to switch between views. When in rule mode, a read-only YAML preview appears in the sidebar.
Advanced editor: Displays rule mode and YAML mode side by side in a resizable split view. Changes in one panel are reflected in the other in real time. You can:
Your preferred panel size is saved across sessions.
To switch between the standard and advanced editor layouts:
In the top bar, select Search or go to and find your project.
Select Secure > Policies.
At the top of the policy editor, select Enable advanced editor or Enable standard editor.
Your preference is saved to your user account and persists across sessions.
policy.yml{{< details >}}
Status: Experiment
{{< /details >}}
{{< history >}}
annotate_ids option defined in the policy.yml file.{{< /history >}}
To simplify your policy.yml file, GitLab can automatically add comments after IDs, such as project IDs, group IDs, user IDs, or compliance framework IDs. The annotations help users identify the meaning or origin of each ID, which makes the policy.yml file easier to understand and maintain.
To enable this experimental feature, add an annotate_ids section to the experiments section in the .gitlab/security-policies/policy.yml file for your security policy project:
experiments:
annotate_ids:
enabled: true
After you enable the option, any change to the security policies made with the GitLab policy editor creates annotation comments next to the IDs in the policy.yml file.
[!note] To apply the annotations, you must use the policy editor. If you edit the
policy.ymlfile manually (for example, with a Git commit), the annotations are not applied.
For example:
# Example policy.yml with annotated IDs
approval_policy:
- name: Your policy name
# ... other policy fields ...
policy_scope:
projects:
including:
- id: 361 # my-group/my-project
actions:
- type: require_approval
approvals_required: 1
user_approvers_ids:
- 75 # jane.doe
group_approvers_ids:
- 203 # security-approvers
[!note] When you apply annotations for the first time, GitLab creates the annotations for all IDs in the
policy.ymlfile, including those in policies that you aren't editing.
GitLab Security Policy Bot is an internal user that executes security policies across your GitLab instance. This bot is essential for security policies and scheduled pipelines to function properly.
The Security Policy Bot is responsible for:
type: schedule rules.latest tag.The Security Policy Bot has the following characteristics:
The Security Policy Bot operates with minimal but essential permissions:
Be aware of the following limitations for the GitLab Security Policy Bot:
[!warning] Vulnerability with abuse reports: GitLab Security Policy Bot instances can be banned or deleted through the abuse reporting system, which can prevent scheduled pipelines from running. Administrators should be aware that:
- Reporting a Security Policy Bot for abuse can lead to the bot being banned or deleted.
- Banning or deleting the bot causes scheduled pipelines to fail.
- Once banned, you cannot restore the bot through standard administrative actions.
- Security policy enforcement is completely disrupted until the bot is restored.
To prevent accidental disruption of security policies, administrators should exercise caution when processing abuse reports for internal user accounts.
If you experience issues with Security Policy Bot functionality:
If the scheduled pipelines are not running as configured:
If the policy job are failing:
If container scanning is not triggering as configured:
latest tag push triggered the expected policy rules.If the bot account no longer exists:
When working with security policies, consider these troubleshooting tips:
severity_levels nor the array
vulnerability_states in the scan_finding rule
can be left empty. For a working rule, at least one entry must exist for each array.If you are still experiencing issues, you can view recent reported bugs and raise new unreported issues.
If you notice inconsistencies in any of the policies, such as policies that aren't being enforced or approvals that are incorrect, you can manually force a resynchronization of the policies with the GraphQL resyncSecurityPolicies mutation:
mutation {
resyncSecurityPolicies(input: { fullPath: "group-or-project-path" }) {
errors
}
}
Set fullPath to the path of the project or group to which the security policy project is assigned.