Restricting GitLab outbound requests and webhook targets

Self-managed GitLab sends webhooks and integration calls from its own servers, so it can reach internal services unless you restrict where those requests may go. This page explains the settings, the trade-offs and how to verify them.

On this page

Why GitLab outbound requests need restricting on your network

This page covers how to stop webhooks, integrations and import URLs on a self-managed GitLab instance from reaching internal services that were never meant to be called by users. Outbound requests leave from the GitLab server itself, not from a user's browser, so they can reach hosts the requester could never contact directly, such as an internal admin console, a cloud metadata endpoint or a database management interface. Any instance where users or projects can configure webhooks, integrations or import URLs needs this review. That covers most production instances, because project owners routinely add webhooks for chat, deployments and issue trackers, and administrators may enable integrations across whole groups.

The core decision is how much of your internal network the GitLab server should be allowed to call. Start by listing the internal hosts and address ranges near the GitLab server and the external or internal integration targets that teams legitimately need. Local network request settings are the first control to review. A common pattern is to block requests to the local network by default, then add specific hosts to an allowlist only when a named integration needs them. Allowlist entries also depend on DNS, so plan for DNS rebinding protection, which checks the address a hostname resolves to at request time, and for TLS verification on system hooks. Confirm the exact setting names and defaults for your GitLab version before you make changes.

The GitLab hardening documentation says these settings should be rolled out in stages. That advice matters because a blanket block can quietly break deployment hooks, chat notifications and import jobs that teams depend on. Before changing anything, record which webhooks and integrations exist, who owns them and what they call. Apply the change on a test instance, watch for failed deliveries, and tell project owners before the change reaches production. Ask whoever runs your GitLab instance to confirm which settings apply to your version and which integrations will need documented exceptions.

Outbound request options and when each fits

This table compares the four main controls for outbound requests from GitLab: blocking local network targets, allowing specific hosts or address ranges, DNS rebinding protection and TLS settings for system hooks. Read each row for its purpose, the instance profile it suits and the cost of using it, then confirm exact setting names in the GitLab documentation for your version.

ControlPurposeTypical fitMain trade-off
Block local network requests entirelyStops webhooks, integrations and imports from calling addresses on your private network or loopback interfaceLocked-down instances with few integrations and no internal webhook consumersBreaks legitimate internal integrations such as self-hosted chat, internal CI or secrets services
Allow specific hosts or IP rangesLets administrators permit named internal destinations while the rest of the local network stays blockedInstances with a known list of internal services that must receive webhooks or API callsEvery allowed entry widens reach, and the list needs review when services move or change addresses
DNS rebinding protectionChecks the address a hostname resolves to at request time, so a name that later points to an internal address is refusedAny instance that accepts webhook URLs from project maintainers or other untrusted usersCan block hostnames that resolve to internal addresses on purpose, so split-horizon DNS setups need testing
Allowlist of hostnames for outbound callsRestricts outbound calls to named external services such as a chat tool or ticketing systemRegulated instances that must document every external destination for assessorsRequires ongoing maintenance as integrations are added, and missing entries cause silent integration failures
TLS verification settings for system hooksControls whether GitLab checks certificates when it calls system hook endpointsInstances that notify internal endpoints signed by a private certificate authorityDisabling verification removes protection against interception, so trust the internal CA instead where possible
Keep defaults and monitor webhook logsRelies on current defaults and reviews failed or unexpected webhook deliveriesSmall internal instances with trusted users and no regulated data flowsGives less assurance to assessors and may not catch a misconfigured target until it matters

How to restrict outbound requests in six steps

This sequence shows how to inventory every outbound path from GitLab, keep only the internal targets you need, block the rest, and prove the restriction works with recorded test results before production changes.

  1. Inventory every outbound request source

    Before changing any setting, list every project webhook, group webhook, system hook, integration, import source and CI/CD job that sends requests from the instance. Ask each project owner and the GitLab administrators to confirm their entries, and record the target URL, owner and purpose in a shared register. The step is done when every entry has an owner and a stated purpose, and any target with no clear owner is flagged for review before enforcement.

  2. Decide which internal targets must stay reachable

    Work through the register and mark each internal address or service that a legitimate integration needs, such as an internal chat relay or a self-hosted issue tracker. Everything else is treated as blocked by default. Record the decision and approver for each exception so that later requests to add one go through the same review. The output is a short, approved list of internal destinations, which may be empty.

  3. Apply local network restrictions in a test environment

    On a non-production GitLab instance, enable the local network request restriction in the Admin Area's outbound request settings so that webhooks and integrations cannot target local or private network addresses. Confirm the exact setting names and behavior for your GitLab version in the official hardening and administration documentation, because labels and defaults can change between releases. Save the configuration and note the time and version in your change record.

  4. Add allowlist entries for required hosts only

    Add only the approved internal hosts from step two to the outbound request allowlist, using the narrowest host or address form the documentation supports. Do not add broad ranges to make a failing integration work. Illustrative check: point a test webhook at a required host and confirm it is delivered, then point one at an unlisted internal address and confirm it is refused. Record both results with the request ID or log entry.

  5. Verify DNS rebinding protection behavior

    Test a hostname that resolves to a public address at first and then to an internal address, using a test domain you control. Send a webhook to that hostname from a test project and confirm that the request is refused rather than delivered to the internal address. Also test a hostname that resolves directly to a blocked address. Confirm the behavior in the documentation for your version, then record the test name, expected result and observed result.

  6. Confirm system hook TLS verification and test both hook types

    Check that system hooks are configured to verify TLS certificates for their receiving endpoints, and that no setting disables verification. Then send a test event from a project webhook and from a system hook to a blocked internal address and to an allowed endpoint. The restriction is confirmed when blocked targets are refused in both cases, allowed endpoints receive the event over verified TLS, and the results, log locations and approver are recorded before the change moves to production.

How the settings differ for single-node, multi-node and air-gapped instances

A single Linux package instance is the simplest case. The Linux package bundles PostgreSQL, Redis and Sidekiq on one host, so webhook, integration and system hook traffic leaves from the same machine that serves Git and the web interface. Confirm your install method first, because the installation methods page lists the Linux package alongside the Helm chart, the Operator, Docker and source installs, and each one places the network path differently.

  • One egress point to review: Every outbound request starts from one host, so the allowlist can be written against one set of source addresses and reviewed in one place.
  • Local services are the main risk: Webhook targets that resolve to the database, Redis, a monitoring agent or an admin panel on the same host or subnet are the cases to block by default.
  • Test on the instance itself: Create test hooks that point at a loopback address and at an internal hostname, then confirm each is refused or allowed as the policy states.
  • Re-test after DNS changes: A hostname that resolved to a public address at approval time can later point to an internal one, so retest allowlisted hosts whenever their DNS records change.

Check that the allowlist still matches the hosts your integrations call, and record the test results alongside the configuration change.

Security risks this control reduces and what it does not cover

Outbound request restrictions close a specific set of server-side paths, mostly through webhooks and integrations that the GitLab server calls on its own. Each card below names one risk, how it works, and what the restriction does to it, followed by the paths it leaves open.

Server-side request forgery through webhooks

A user who can set a webhook URL can make the GitLab server send requests to any address it can reach, including hosts on your internal network that no outside client could touch. The local network request setting blocks webhook targets that resolve to private or loopback addresses unless an administrator allows them. Check the setting in the admin area and test it with a webhook pointed at an internal address to confirm the block.

Access to cloud metadata endpoints

Cloud instances expose metadata services on link-local addresses that return instance credentials to anything on the host. A webhook that reaches that address could retrieve temporary tokens for the GitLab server's cloud role. Blocking local and link-local targets removes this path, but confirm that your cloud provider's metadata address falls inside the ranges you block, and that the GitLab host uses an instance profile with the smallest role it needs.

Probing of internal admin panels

Internal services such as database consoles, monitoring dashboards and older admin interfaces often trust any request from the internal network. A webhook can act as a proxy that lets an external attacker scan these ports and paths indirectly. Allowlisting only the specific hosts and ports that integrations need keeps the GitLab server from becoming a scanning relay. List every internal endpoint your integrations use and confirm that nothing else is reachable from the GitLab host.

DNS rebinding after validation

A hostname can pass validation on the first lookup and then resolve to an internal address when the request is actually sent. This gap between checking and connecting is what DNS rebinding exploits. Protection against rebinding in the outbound settings re-checks the resolved address at request time. Test this with a hostname you control that alternates its answer, and record the result as part of your acceptance evidence.

Unencrypted or unverified system hook delivery

System hooks send event data about users, projects and groups to an external receiver, so an unverified or plaintext endpoint can expose that data in transit or accept forged events. Requiring TLS for the receiver and verifying its certificate protects both directions. Confirm the receiver's certificate chain against your internal CA where one is used, and check that the webhook secret token is set and rotated.

Traffic from CI jobs and runners

Outbound request settings govern webhooks and integrations called by the GitLab application, not the network path of jobs running on runners. A pipeline script can reach any host its runner can reach, so runner egress needs firewall rules, separate network segments or egress proxies. Review runner placement and egress policy as a separate control, and note that the content returned by allowed integrations is not inspected by this setting.

Questions teams ask before restricting GitLab outbound requests

How much effort does restricting outbound requests take?

The effort scales with how many integrations and webhook targets your GitLab instance already calls, and how many internal services sit behind the same network. A single-node instance with a handful of chat, issue tracker and deployment integrations is a small exercise. A multi-node layout with many projects sending webhooks to internal endpoints takes longer, because each target has to be identified, justified and either allowlisted or blocked. The main drivers are:

  • The number of distinct webhook and integration destinations in use today
  • How many of those destinations resolve to private or internal addresses
  • Whether system hooks, group webhooks and project webhooks all need review
  • How many people must sign off on each allowlist entry

Ask any partner to size the work from a written integration inventory rather than from the instance name.

Can our own team restrict GitLab outbound requests without a partner?

Yes, many teams can do this in-house, provided someone on the team administers GitLab and understands the network paths from the instance to internal services. The work involves reading the administrator settings for local network requests, building allowlists for specific hosts, checking DNS behavior, and confirming TLS settings for system hooks. The skills that matter most are GitLab administration, Linux and DNS networking, and a clear view of how internal services are reached. A partner is useful when the team lacks time for testing, needs an outside review of the design, or wants the change documented as evidence for an assessment. DeployOpen implements and documents this work inside the client's own infrastructure, and the scope is agreed in writing before work starts.

How long does testing outbound request restrictions usually take?

Testing usually takes longer than the configuration change itself, because each integration has to be exercised from the GitLab side to confirm it still works and that blocked targets really are blocked. Duration depends on the number of integrations, the number of distinct environments (for example, staging and production), and whether integrations depend on other teams to verify their endpoints. Testing typically covers a positive case for every allowlisted host, a negative case for an internal address that should be refused, and a check that DNS changes cannot redirect an allowed host to a private address. No general duration is given here because it depends on your inventory. Ask any provider to state the testing steps and the environments they will use before agreeing to a timeline.

What do we need from our internal team before the work starts?

The work needs a few inputs from your side before anyone changes settings. Most engagements ask for a current network diagram showing where GitLab, its runners and internal services sit, and an integration inventory listing every webhook, system hook and external service GitLab calls. Your change approval process also needs to be agreed, because allowlist changes can break integrations that teams depend on. Expect to name a contact for each integration owner who can confirm whether a destination is still needed. Clear answers to these questions keep the testing short and reduce surprises after release.

What recurring work follows after the restrictions are in place?

Restrictions need ongoing review because integrations change. Each time a team adds, moves or retires a webhook target, the allowlist may need an update. GitLab upgrades and new integration features can also change how requests are sent, so the settings and test cases should be rechecked after each upgrade. A practical routine includes reviewing allowlist entries on a fixed schedule, checking the integration inventory against live webhook configuration, and rerunning the negative tests after upgrades. The cost of this recurring work depends on how often integrations change in your organization. Plan an owner for it, because an unowned allowlist tends to grow stale.

What should a quote for this work include?

A useful quote states the scope in writing: which GitLab instance or instances are covered, the integrations and webhook destinations in scope, and the settings to be changed. It should list each deliverable, such as the configured allowlist, the test plan and results, and the change documentation. It should also state the testing environments, the assumptions about your network diagrams and inventory, and who performs each step. Separate one-time work (design, configuration, testing, documentation) from any recurring support or review you want. Ask the provider to name what is excluded, such as changes to firewalls or internal services owned by other teams, so the price reflects a defined scope. DeployOpen does not publish a price list, and a quote follows from the written scope.

Does restricting outbound requests also require changes outside GitLab?

Often it does. GitLab's settings control what the application will request, but the network around it also determines what is reachable. Firewall rules, DNS zones and internal service access policies may need to match the allowlist so that a blocked request cannot succeed by another route. Runners are a common gap, because jobs running on them can reach internal networks even when the GitLab application itself is restricted. Confirm the network boundary for runners and any integration agents with the team that owns the network. The GitLab hardening guidance in the official documentation is a good starting point for the application-level settings, and the network controls should be designed alongside them.

How to verify the restriction works and keep it working

Treat the outbound restriction as a control that needs proof, not a setting that is assumed to work. Start with negative tests run from a project webhook and from a system hook. Point each one at loopback addresses, private network ranges, a link-local address and the cloud metadata address used in your environment, and confirm that GitLab refuses delivery and records the failure. Run the same tests with a hostname that resolves to an internal address, because a name that passes the first check can resolve differently later. Use a receiver you control so you can see whether any request actually arrived.

Then run positive tests against each host on your allowlist. An allowlisted host should accept delivery, and the test should confirm the TLS validation you configured for system hooks. Repeat the positive tests after any change to DNS records, load balancers, proxies or the integration endpoint behind a name, since a valid allowlist entry can start pointing somewhere unexpected. Schedule a retest after every GitLab upgrade, because the outbound request settings and their defaults can change between releases, and confirm the release notes for your target version before the change window. Confirm the exact upgrade path with the GitLab upgrade documentation.

Record each run as change evidence: the GitLab version, the settings file values in use, the test inputs, the expected and observed result, and the approver. Keep the test scripts in version control so the same tests run each time. For troubleshooting, check the application logs and the Sidekiq logs on the GitLab host, along with the webhook delivery history in the project or system hook settings. Plan log collection and retention with the monitoring and maintenance guidance so these records survive long enough for an audit. Ask your security team to confirm which log sources they need and how long they must be retained.

How DeployOpen scopes and delivers outbound request hardening

DeployOpen plans, implements, hardens and documents self-hosted GitLab inside your own infrastructure, including the settings that control where webhooks and integrations can send requests. We start from a written scope covering your instance, your network layout and the internal services your integrations must never reach, then build and verify the controls before handover.

How we scope

  • We inventory the webhooks, integrations and system hooks that call out from your GitLab instance.
  • We map which internal networks, hosts and services outbound requests must not reach, and which exceptions are approved.
  • Engagements are fixed-scope, with deliverables and timelines agreed in writing before any change is made.

How we build

  • We configure local network request settings and host allowlists in your instance configuration, recording each value and its reason.
  • We verify DNS rebinding protection and system hook TLS behavior against your actual network paths, not assumptions.
  • We test blocked and permitted targets from a representative account, including webhook test requests, and keep the results as evidence.

How we hand over

  • You receive the configuration changes, allowlist register, test cases and results, and a runbook for adding or removing a host.
  • We document how to review allowlist changes and which owner approves each exception before it reaches production.
  • We walk your administrators through the settings so they can confirm the controls after future GitLab upgrades.

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer, covering allowlist reviews after new integrations.
  • We can re-run the outbound request test set after each required upgrade stop, as part of planned GitLab upgrades.
  • Ask any partner to confirm in writing which settings their scope covers and which parts of your environment remain your responsibility.

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.