GitLab HTTP_V2 Client Ignores Proxy Configuration During DNS Resolution for License Activation

Summary

GitLab's Gitlab::HTTP_V2::UrlBlocker performs DNS resolution for customers.gitlab.com despite correctly detecting proxy configuration, causing license activation to fail with "execution expired" timeout in proxy environments with restricted DNS resolution.

Can access customers.gitlab.com outside of GitLab via curl.

Environment

  • GitLab Version: 18.3.0 EE (Omnibus)
  • Operating System: RedHat Enterprise 8.10
  • Network: Corporate proxy environment with restricted DNS resolution

Expected Behavior

When proxy environment variables are correctly configured and detected (uri_under_proxy_setting? returns true), GitLab should:

  1. Skip DNS resolution for external domains
  2. Use the configured proxy for all HTTP requests to customers.gitlab.com
  3. Allow the proxy to handle DNS resolution

Actual Behavior

Despite correct proxy detection, GitLab attempts DNS resolution for customers.gitlab.com before using the proxy, causing a 15-second timeout when internal DNS servers cannot resolve external domains.

Steps to Reproduce

  1. Configure GitLab in a corporate environment with:

    • HTTP proxy configured via environment variables
    • Internal DNS servers that cannot resolve external domains
    • Proxy correctly configured and working for other traffic
  2. Set proxy environment variables:

    gitlab_rails['env'] = { 'http_proxy' => 'http://proxy.company.com:80', 'https_proxy' => 'http://proxy.company.com:80', 'no_proxy' => 'company.com,localhost' }

  3. Verify proxy detection works:

    # Test the proxy detection logic

    uri = URI('https://customers.gitlab.com/graphql')\ puts "URI: #{uri}"\ puts "Hostname: #{uri.hostname}"\ puts "Port: #{uri.port}"

    Output:

    URI: https://customers.gitlab.com/graphql

    Hostname: customers.gitlab.com

    Port: 443

     

    # Check environment variables

    puts "\n=== Environment Variables ==="\ %w[http_proxy https_proxy HTTP_PROXY HTTPS_PROXY].each do |var|\ puts "#{var}: #{ENV[var] || 'NOT SET'}"\ end

    puts "no_proxy: #{ENV['no_proxy'] || 'NOT SET'}"\ puts "NO_PROXY: #{ENV['NO_PROXY'] || 'NOT SET'}"

    Output:

    http_proxy: http://<proxy>:80

    https_proxy: http://<proxy>80

    HTTP_PROXY: http://<proxy>:80

    HTTPS_PROXY: http://<proxy>:80

    => ["http_proxy", "https_proxy", "HTTP_PROXY", "HTTPS_PROXY"]

    no_proxy: domain.de,localhost

    NO_PROXY: domain.de,localhost

     

    # Test GitLab's proxy detection

    puts "\n=== GitLab Proxy Detection ==="\ puts "http_proxy_env?: #{Gitlab::HTTP_V2::UrlBlocker.send(:http_proxy_env?)}"\ puts "no_proxy_env: #{Gitlab::HTTP_V2::UrlBlocker.send(:no_proxy_env)}"

    Output:

    http_proxy_env?: true

    no_proxy_env: domain.de,localhost

     

    # Test URI proxy logic

    no_proxy = Gitlab::HTTP_V2::UrlBlocker.send(:no_proxy_env)\ if no_proxy\ puts "use_proxy? result: #{::URI::Generic.use_proxy?(uri.hostname, nil, uri.port, no_proxy)}"\ end

    Output:

    use_proxy? result: true

     

    # Test the full proxy detection

    puts "uri_under_proxy_setting?: #{Gitlab::HTTP_V2::UrlBlocker.send(:uri_under_proxy_setting?, uri, nil)}"

    Output:

    uri_under_proxy_setting?: true

  4. Attempt license activation:

    gitlab-rails runner "GitlabSubscriptions::ActivateService.new.execute('ACTIVATION_CODE')"

  5. Observe timeout error:

    Gitlab::HTTP_V2::BlockedUrlError: URL is blocked: execution expired

Evidence

Network Traffic Analysis (tcpdump)

The tcpdump shows the problematic behavior:

`# DNS queries being made despite proxy configuration 08:56:37.640836 IP GITLAB_HOST.PORT > DNS_SERVER.domain: 42847+ A? customers.gitlab.com. (38) 08:56:37.640840 IP GITLAB_HOST.PORT > DNS_SERVER.domain: 22365+ AAAA? customers.gitlab.com. (38)

Successful proxy usage for other domains

08:56:36.732646 IP GITLAB_HOST.PORT > PROXY_SERVER.http: HTTP: CONNECT example-domain.com:443 HTTP/1.1 08:56:36.738915 IP PROXY_SERVER.http > GITLAB_HOST.PORT: HTTP: HTTP/1.1 200 Connection Established `

Proxy Detection Verification

# All proxy detection logic works correctly http_proxy_env?: true no_proxy_env: company.com,localhost use_proxy? result: true uri_under_proxy_setting?: true

Root Cause Analysis

The issue is in gems/gitlab-http/lib/gitlab/http_v2/url_blocker.rb in the get_address_info method:

def get_address_info(uri) Timeout.timeout(GETADDRINFO_TIMEOUT_SECONDS) do # 15 seconds Addrinfo.getaddrinfo(uri.hostname, get_port(uri), nil, :STREAM) end rescue Timeout::Error => e raise Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError, e.message # "execution expired" end

This method is called from validate_resolved_uri even when uri_under_proxy_setting? returns true, indicating that DNS resolution should be bypassed when using a proxy.

Code Location

  • Filegems/gitlab-http/lib/gitlab/http_v2/url_blocker.rb
  • Methodget_address_info (line ~218)
  • Called fromvalidate_resolved_uri (line ~123)

Workaround

Adding customers.gitlab.com to /etc/hosts bypasses the DNS resolution issue:

echo "104.18.36.112 customers.gitlab.com" >> /etc/hosts gitlab-rails runner "GitlabSubscriptions::ActivateService.new.execute('ACTIVATION_CODE')" sed -i '/customers.gitlab.com/d' /etc/hosts

Proposed Fix

According to GitLab DUO the validate_resolved_uri method should check if a proxy is being used before attempting DNS resolution:

`def validate_resolved_uri(uri, ...)

Skip DNS resolution if proxy is configured and should be used

proxy_in_use = uri_under_proxy_setting?(uri, nil)

if proxy_in_use return Result.new(uri, nil, proxy_in_use) end

Continue with existing DNS resolution logic...

begin address_info = get_address_info(uri) rescue SocketError # existing error handling... end end `

Impact

  • Severity: High - Blocks license activation in corporate proxy environments
  • Affected Users: Customers with proxy configurations and restricted DNS resolution
  • Workaround Available: Yes (manual /etc/hosts entry)

Related Issues

This appears related to issue Skip DNS rebinding protection when HTTP_PROXY environment is set which was closed in GitLab 15.11, but the fix may not cover all code paths or may have regressed.

Additional Information

  • The issue affects specifically the license activation flow via GitlabSubscriptions::ActivateService
  • Other HTTP traffic correctly uses the proxy (as evidenced by tcpdump)
  • The proxy detection logic works correctly - the issue is that DNS resolution happens regardless of proxy detection results
Edited by John Lyttle