GitLab push rules and deploy keys

Push rules let you reject commits from unverified committers and files that look like secrets, and project deploy keys replace broad, shared SSH keys for automation. This page explains how to configure both on self-managed GitLab and what to audit afterward.

On this page

Push rules and deploy keys: controlling what enters GitLab and who can read it

Push rules are project-level checks that GitLab runs on every push, so a commit can be rejected before it reaches the branch. They can require verified commit signatures, block committers whose email is not on an allowed list, and reject files whose names match patterns such as private keys or credential files. Project deploy keys are SSH keys attached to a single project, granted read or write access, instead of a personal key or a shared public key that anyone with a copy can use. A security or platform team needs both when a self-managed instance already holds regulated or production code and the team cannot yet say who committed what, or which automation can read which repository. Push rules and deploy keys sit alongside the sign-up, SSH key type and CI/CD secrets controls in this hardening group: they decide what enters the instance and which machine identities can pull or push, while those other sections decide who can register and which credentials are accepted.

Before you enable anything, confirm in the GitLab documentation for your edition and version which push rule options and deploy key settings are available, since availability and behavior depend on the GitLab tier and release you run. Check which rules are in the Free tier and which need Premium or Ultimate, and whether pattern matching or signature checks behave as your policy assumes. Then run an inventory: list every project-level and instance-level deploy key, note the ones created as public keys, and map each key to its owner. Keys that still belong to users who have been blocked or removed are a common gap, because they can keep working until someone removes them. Ask your GitLab administrators to report keys tied to blocked accounts and to confirm the audit view they can use to find them.

Treat push rules as a guardrail, not a complete control. Rules that reject unverified committers depend on the identity data your instance holds, so verify that email addresses and signing keys are maintained through your identity provider. Rules that block sensitive file names will not catch secrets embedded in ordinary files, so pair them with secret detection in your pipelines and with the variable handling covered in the CI/CD secrets section. Document each rule, its owner, the exception process and the evidence you would show an auditor, and test rules against a sandbox project first, because a rule that is too broad will block legitimate pushes and drive teams toward workarounds.

What push rules check before a push is accepted

Push rules run on the GitLab server when a push arrives, so they apply to every client, including ones that bypass local hooks. Each check targets a different way unreviewed or sensitive content can reach a repository, and none of them replaces code review or secret rotation.

Committer email verification

This check rejects commits whose committer email is not a verified address on the GitLab account pushing them. It stops a user from impersonating a colleague in history, but it only validates the email field, not the identity behind it. Confirm how the check treats commits authored by others during a merge or cherry-pick, since those flows change the committer.

Author restrictions by pattern

Author restrictions match commit author names or emails against an allowed pattern, which helps enforce corporate identities on internal repositories. Authors are self-declared, so a pattern proves only that the string matches. Use it to catch mistakes and policy drift, not to establish who actually wrote a change.

Commit message patterns

A commit message pattern can require a ticket reference or change identifier, which links code to change records that auditors and release managers read. The check only confirms that text exists in the message. It cannot tell whether the referenced ticket is real, approved or related to the change.

Branch name rules

Branch name rules limit which branch names a user can create, for example by requiring a prefix tied to a team or ticket. They shape naming discipline and help protected-branch policies target the right refs. They do not stop anyone with push access from pushing to an existing branch that already matches the rule.

File name and size restrictions

File name restrictions block paths or extensions, such as private key formats or database dumps, and file size limits stop very large binaries from entering history. Both checks run on new content only, so files already in history remain. Confirm the exact pattern syntax and size limit options in the documentation for your version.

Secret detection on push

Secret detection scans pushed content for credential patterns such as tokens and private keys before the commit lands. It reduces accidental exposure but depends on pattern coverage, so it misses custom secrets and anything encoded or split across files. Confirm which detection rules and tiers apply to your instance, and plan rotation for any secret that was pushed before the check was enabled.

Where push rules apply: project, group and instance scope

Push rules in self-managed GitLab are configured per project, so the first decision is which projects a rule set must cover. Each project carries its own push rules page under its settings, and that page is where the controls for committer verification, commit message patterns, and blocked file names are applied. Confirm in your own instance, before you rely on it, whether a rule set set at a group level is inherited by the projects beneath it, and whether a project owner can override or relax an inherited setting. Test this with a throwaway project in a group you control rather than assuming the behavior from another GitLab version or tier.

For administrators managing many projects, the practical question is how much of the estate you can change in one place. Inheritance from groups and instance-level settings reduces the number of places a rule must be maintained, but it also means a single change can affect repositories that owners did not expect to be touched. Before you roll out a rule, list the groups and subgroups it will reach, record which projects already hold custom values, and agree with project owners who may change those values. Ask your GitLab administrator or vendor to show you, for your version, exactly where each push rule setting is stored and which level wins when two settings conflict.

Push rules act on pushes that arrive after the rule is in place. They do not rewrite or remove commits that already exist in the repository history, so a secret or an unverified commit that landed before enforcement stays in the history and must be handled separately, for example by rotating the credential and reviewing the history. A rejected push is also a preventive control, not a code review: it stops a specific class of change at the door but does not check the logic, security or intent of the code that passes. Keep push rules alongside protected branches, merge request approvals and secret scanning so that each control covers a gap the others leave.

Push rule options and when each fits

This table compares the main push rules and deploy key options by the control each gives, the failure it addresses and the friction it adds for developers. Read each row against your own threat model and team workflow. The main takeaway is that content and identity rules catch the most common mistakes with the least cost, while deploy key scope decides how far a leaked credential can reach.

OptionControl providedTypical failure addressedFriction and when it fits
Verified committer checkRejects commits whose signature does not match a verified identity on the instanceCommits pushed under another person's name or from an unregistered accountDevelopers must sign commits and verify keys. Fits teams with regulated change evidence
Commit author email patternAccepts only author addresses that match an approved domain or patternCommits from personal or unmanaged addresses that bypass identity recordsLow friction, but contributors with other addresses must fix their Git config. Fits most corporate instances
Commit message patternRequires messages to match a regular expression, such as a ticket referenceUntraceable changes with no link to a request or review recordDevelopers must reword messages before push. Fits teams that audit change history by ticket
Branch name patternLimits which branch names can be created or pushedStray branches that bypass naming or release conventionsMinor friction when names are renamed. Fits release trains with predictable branch naming
File name restrictionsBlocks pushes that add files matching listed names or extensionsAccidental commits of binaries, archives, keys or local configuration filesCan block legitimate files, so exceptions need a review path. Fits repositories with known file types
Maximum file sizeBlocks files above a set size limitLarge binaries and dumps that bloat history and slow clonesTeams with large assets must move them to artifact or LFS storage. Fits code-only repositories
Prevent secretsScans pushed content for credential patterns and blocks matching commitsTokens, passwords and private keys committed to source historyPossible false positives that need triage. Fits every repository, and pairs with secret rotation
Project deploy key with read-only accessGrants a single project read access through one registered SSH keyPipelines or servers pulling code that could push if the key leaksSetup per project adds administration. Fits deployment pulls and mirrors
Public deploy keyRegisters one key usable across projects that enable itBroad access from one credential that is hard to trace to a single projectEasy to share, but weakens scope and audit. Avoid for regulated or multi-team instances, and review existing use

Why project deploy keys replace public deploy keys

A deploy key registered at the instance level, or copied into several projects, is a broad grant of trust. One public key then authenticates to every repository it has been attached to, and anyone holding the matching private key can clone those repositories and, where write access was enabled, push to them. The damage a leaked key can do depends on how far the key reaches. The control to apply is to create a separate key for each deployment job or server, attach it to one project, and grant only the access that job needs. A read-only project deploy key cannot push, so a leaked copy exposes one repository's code and nothing else.

Migrating is a sequence, and the order matters. First, inventory every existing key at the instance and project level, and record which projects, pipelines and servers depend on each one. Second, create a project deploy key for each dependency, enabling write access only where a job truly pushes. Third, update the pipeline variables and server configuration that hold the private keys, and confirm that jobs and deployments authenticate with the new keys. Fourth, remove the old keys only after the logs show they are no longer used. Confirm the exact menu paths and the behavior of each access level against your GitLab version in the GitLab authentication and authorization documentation before you change production pipelines.

Keys that remain tied to a blocked or departed user need a decision before removal. Ask who owns each key, which automation depends on it, and whether a replacement project deploy key can carry the same job without a person's account behind it. Record the owner and purpose of every new key in your change records so that a later review can tie each key to one project and one job. Plan the cutover for a window where the owning team can watch the first deployments, and keep the old key available only until that check passes.

How to configure push rules and project deploy keys

This sequence tightens who can push code and which keys can reach repositories, starting with a pilot project and ending with a verified access inventory. Each step closes with a check so the team can prove the controls work before wider rollout.

  1. Confirm edition, version and admin access

    The administrator records the GitLab version and edition in use, then confirms which push rule and deploy key features that version exposes. Push rules are configured in the project settings, and some related controls depend on the tier, so check the GitLab pricing page and the feature documentation for your version. Confirm exact menu paths in your own GitLab version, since labels move between releases. Confirm that you hold Owner or Maintainer rights on the pilot project and the group that will be rolled out. Done when you have written down the version, the tier, and the list of administrators who will make changes.

  2. Set push rules on a pilot project

    Choose one low-risk project that has active contributors and a stable default branch. In its repository push rule settings, enable the option that rejects commits from committers whose email is not verified, and add a file name pattern that blocks secret-bearing files such as private key or environment files. Keep the rule scoped to the pilot so that a mistake does not interrupt other teams. Record the exact pattern and the time of change in your change log. Done when the settings page shows the rule as saved and the project owner has acknowledged it in writing.

  3. Test with a known-good and a known-bad push

    From a developer account with a verified email, push a harmless commit and confirm it is accepted. Then, using a test branch, push a commit that adds a file matching the blocked pattern, such as a dummy private key file that contains no real secret. The push should be rejected with a message that names the rule. Also push from an account with an unverified email if you use that check, and confirm rejection. Remove the test branch afterward. Done when the good push succeeds, the bad push is rejected with the rule message, and both results are recorded in the change log.

  4. Roll out push rules by group

    Apply the same settings to the remaining projects in one group at a time, using the group-level or project-level option your version provides. Ask project owners to tell you about any legitimate files that the pattern blocks, such as sample keys in test fixtures, and decide whether to narrow the pattern or move those files. Keep a list of which projects have the rule and which do not. Done when each group has a recorded date of rollout, a named owner, and a check that a test push to one project in the group is rejected as expected.

  5. Inventory existing deploy keys

    Using an administrator account, list the deploy keys attached to each project and group, and export the list if your version allows it. For each key, record the project, the key title, whether it is a project key or a public key shared across projects, the write access flag, and the user who created it. Flag any public deploy key that is attached to many projects, any key with write access that does not need it, and any key whose creator is blocked or no longer employed. Done when the inventory covers every project in scope and each flagged key has an owner who must justify it or replace it.

  6. Replace public keys with project deploy keys

    For each flagged public key, create a new project deploy key on the project that needs it, generated for that single purpose, with read-only access unless the job truly pushes. Update the consuming system, such as a CI job or deployment tool, to use the new key, and run the job once. Then remove the old public key from the project. Store the private half in the secrets location your team already uses, not in a repository. Done when the old key no longer appears in the project list, the replacement key works, and the change is recorded against the owner.

  7. Audit keys tied to blocked users and verify access

    Review the inventory again for keys whose creator account is blocked, deactivated or removed, and revoke or replace each one, because a key tied to a removed user can keep working for the project as long as it remains attached. Then run a test pipeline in a pilot project that uses the replaced key, confirm it can clone or push only as the scope requires, and confirm that a request using a removed key fails. Keep the inventory and test output as evidence for your next access review. Done when no in-scope key is tied to a blocked user, the test pipeline passes with the new key, and the audit record is filed.

Auditing SSH keys that still tie to blocked users

An SSH key that belongs to a blocked, deactivated or departed user can still be a working credential if the key was never removed, because the key is attached to the account rather than to the person's current access. Blocking an account stops the user from signing in through the web interface, but it does not by itself mean every key on that account has been reviewed, moved or retired. Before you tighten the rules in this section, run an audit of keys tied to inactive accounts so you know which repositories and pipelines depend on them. Confirm the exact steps for your version in the GitLab documentation on SSH keys and on blocking users, since admin and user key views have changed across releases.

Start from the administrator view of users, filter for blocked and deactivated accounts, then review each account's SSH keys and note the last-used information where your version shows it. For every key, decide one of three outcomes. Remove keys for people who have left and for keys with no clear owner. Rotate keys that are still needed by a person who remains in the organization, which means issuing a new key and retiring the old one. Reassign keys only when the work behind them has a new owner, and then make sure that owner's account is the one that will persist. Record the decision and the reason in your change records so the audit itself becomes evidence.

Automation keys owned by a person create a dependency on that person's account status. When the owner is blocked, scripts, mirrors and deployments can fail without warning, and the temptation is to reactivate the account or copy its key somewhere else. Where the platform supports it, prefer project deploy keys for single-repository access, which are scoped to a project and do not depend on a human account, or a dedicated service account for broader automation. Confirm in your version whether a given automation can use a deploy key with the access it needs, and plan the move before blocking the owner so the audit does not become an outage.

Security and operational risks to plan for

Push rules and deploy keys fail in predictable ways: rules block legitimate work, controls get bypassed through paths nobody tested, and credentials outlive the people and jobs that needed them. The cards below pair each risk with a mitigation you can verify before the rules go live across your instance.

False positives blocking releases

A secret-file pattern or committer-email rule can reject a legitimate push, often during a release window. Before enforcing anything, apply the rules to a pilot project with representative histories and confirm which commits and files they reject. Agree on a documented exception path with a named owner, so a blocked release is resolved through review rather than by quietly disabling the rule.

Bypasses through untested paths

Developers and automation may reach repositories through the web UI, the API, or SSH with different results from the Git client they normally use. Test each path against your rules, including merge requests and service accounts, before you rely on them. Treat any path that behaves differently as a finding to close, not a detail to note.

Deploy keys with unneeded write access

A deploy key created with write access lets any pipeline or host holding it push code, which is more than most build and deploy jobs need. Review each key's scope against what the job actually does, and default to read-only unless a documented job requires writes. Confirm the scope on each key during the change review, not only when it is first created.

Keys copied into scripts and wikis

Private key material pasted into scripts, runbooks, wiki pages or chat threads survives the removal of the original key. Search your repositories, wikis and issue trackers for key headers and fingerprints, and move every key into a secrets store or CI/CD variable marked masked and protected. Confirm with the team which copies exist, because deleting the key does not remove the copies.

Keys tied to blocked users

Keys that belong to a user account can keep working or remain in place after that user is blocked, so access persists silently. Audit keys for every blocked or departed user, then reissue or remove them through a project deploy key owned by the project. Rotate any key that has been exposed, and record the rotation in the change log.

Unlogged and unreviewed rule changes

Changes to push rules, allowed patterns or key settings that nobody reviews leave no record of why access widened. Require review for every rule change, keep rejected push events in your log pipeline, and review those logs on a schedule. Map the change record to your control framework, such as the access control and configuration management families in NIST SP 800-53, and use the GitLab hardening guide as the baseline to compare against.

Questions teams ask before configuring push rules and deploy keys

Can our own team configure push rules and deploy keys without a partner?

Yes, most teams with a GitLab administrator and a few experienced maintainers can make these changes in-house, because push rules and project deploy keys are configured through the GitLab interface and API. The harder part is the inventory and rollout: finding every public deploy key, confirming which pipelines depend on each one, and changing them without breaking releases. Teams that already run GitLab day to day usually handle the settings themselves and bring in outside help when the key inventory is large or the change must be evidenced for an assessor.

What makes the effort for push rules and deploy keys grow?

Effort tracks the amount of existing key sprawl more than the setting changes themselves. The main drivers are the number of projects and groups, how many public or user-owned deploy keys have accumulated, how many pipelines and external systems authenticate with those keys, the GitLab tier and version your instance runs, and how strictly your change control requires review before each setting changes. Each of these adds inventory, testing and approval work, so ask any provider to price the inventory separately from the configuration.

What does the team need to provide for this work?

The work needs administrator access to the instance, a pilot project where push rules and key changes can be tried first, named owners for the pipelines that use deploy keys, and an agreed rollout window. Without pipeline owners, nobody can confirm which keys are still in use, and a key removed too early can stop a deployment. Ask the provider which of these items they expect you to supply and who approves changes to production-facing projects.

Do push rules replace secret scanning or code review?

No. Push rules can reject commits from unverified committers and block files with names that suggest secrets, but they do not inspect file contents for every credential pattern, and they do not judge whether a change is correct. Secret detection and merge request review remain separate controls. Confirm with your GitLab tier and version which secret detection and approval features are available to you, because the features listed for each tier in GitLab pricing differ.

How do deploy keys tie to blocked users, and why does it matter?

A deploy key is an SSH key with read or write access to a project, and a key uploaded by a user can remain attached to projects after that user is blocked or leaves. That stale access is why auditing keys that map to blocked users is a separate step from changing the defaults. Review the key list for each project, remove keys that belong to inactive accounts, and record the decision so the change can be shown to an auditor.

Which GitLab tier and version do we need before starting?

Start by confirming what your installed tier and version provide, because feature availability differs. GitLab pricing lists Free, Premium and Ultimate as all available for self-managed installations, and it assigns advanced CI/CD and priority support to Premium, with application security testing, supply chain security, vulnerability management and compliance features assigned to Ultimate. Check the feature documentation for your exact version before you promise a control, and plan any upgrade through the required upgrade stops first.

Do we need a partner, and what would they change?

You need a partner when the internal team lacks time, GitLab administration experience, or an independent record of the changes. A partner would normally inventory keys, propose settings, run the pilot, coordinate with pipeline owners, and document the evidence. They do not issue audit reports or certifications, so independent auditors still assess the result. DeployOpen plans and implements these changes inside your own GitLab instance under a written scope agreed before work starts.

Limits to confirm in your environment

Push rules and deploy key behavior depend on the GitLab release, the edition and the path a change takes into the repository. The cards below list the points to test on a non-production instance and confirm against the documentation for your exact version before you write a policy around them.

Push rule options and tier

Confirm which push rule options exist in your release and which edition includes each one. Availability of push rules has differed by tier, so check the pricing comparison for your edition and the feature documentation for your version. Record the result in your change management evidence, because a rule that is missing in your tier leaves the control unenforced without any visible error.

Coverage across push paths

Test whether each rule applies to every route a change can take: a standard git push, the REST and GraphQL APIs, web IDE commits, and file uploads through the web interface. Create a commit on each path that violates the rule and confirm the rejection. A rule that blocks command-line pushes but not API commits is a gap you must document or close.

Handling of existing history

Push rules inspect new changes, so secrets or unsigned commits already present in history are not removed by enabling a rule. Confirm how your version evaluates commits that are pushed later, including branches created from older history. Plan a separate history scan and a rotation process for any credential found, since blocking future pushes does not revoke a leaked value.

Deploy key permissions on protected branches

Confirm how deploy keys with write access interact with protected branch settings in your release. Whether a deploy key can push to a protected branch, and whether it can bypass push rules, must be tested with a key that has write access and a branch that has restrictions. Treat any unexpected write path as a finding and narrow the key before production use.

Audit trail for key changes

Verify that adding, changing and removing deploy keys and SSH keys appears in the audit events your release records, and that the entries name the actor and the target project. Also confirm how a key tied to a blocked user is reported and whether that link survives the user's removal. Export a sample of events to your log store to check that they are readable by your security team.

Retention and access to audit data

Check how long audit events are kept on your instance, who can view them, and whether they can be forwarded to an external log system. Confirm the retention behavior in the documentation for your version and test an export before relying on it for an evidence request. Short default retention can remove the record of a key change before a review takes place.

How DeployOpen scopes and delivers GitLab push rule and deploy key work

DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure, including GitLab. For push rules and deploy keys, we start from a written scope that names the projects, the committer and file rules, and the key inventory, then build and test the changes in your environment before handover.

How we scope

  • We inventory projects, groups and existing deploy keys before agreeing what changes.
  • The written scope names which push rules, secret file patterns and key types are covered.
  • Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.

How we build

  • We configure push rules in a test instance first, then confirm rejected commits behave as intended.
  • We replace public deploy keys with project-scoped deploy keys and map each key to its owning project.
  • We test push rejections and key access with representative branches and pipelines before production change.

How we hand over

  • We document each push rule, its reason, its owner and the change process for updating it.
  • We provide a key register listing every deploy key, its project, its owner and its review date.
  • We walk your team through the audit steps for keys tied to blocked or deactivated users.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers after handover.
  • Retainers can cover periodic key reviews and re-checks of push rules after GitLab upgrades.
  • Confirm with your GitLab version and release schedule which push rule settings your instance supports.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.