Skip to content

x509 / TLS signed commits: only the first email address in the subjectAltName list is used for verifying commits

Summary

Support is assisting a customer with x509 / TLS signed commits (GitLab team members can read more in the ticket)

While investigating the code, I noticed that certificate_email does this:

175        get_certificate_extension('subjectAltName').split(',').each do |item|
176          if item.strip.start_with?("email")
177            email = item.split('email:')[1]
178            break
179          end
180        end
181
182        return if email.nil?
183
184        email
  • 175: subjectAltName is a comma separated list that can contain zero, one, or 'n' entries of potentially multiple types, and the list is processed as a loop
  • 176: as it loops over the list, entries which are not prefixed email are skipped
  • 177: entries prefixed email: have that string stripped off
  • 178: I understand the break terminates .each do |item| when an email is found, which would the first one in the list.

The problem is, I would anticipate that certificates can have multiple email addresses in them. I think this code should return them all (ie: a list/array) and then consumers of certificate_email (example: if user.verified_emails.include?(@email) && certificate_email == @email) should expect to be verifying if a given string (@email) is in a list certificate_email.

Companies with multiple top level domains for different brands may assign email addresses to staff across all domains, and staff might use any of them. Or, as a result if mergers and acquisitions, staff might be using the old company's email address plus an email address issued by the acquiring company.

I've looked through RFC5280 and can see no restriction around how many SANs of a particular flavour can appear in the list, including email. The language sometimes uses singular and plural forms, but it does it for types which definitely appear 'n' times in certificates.

Example: gitlab.com has multiple DNS: entries.

X509v3 Subject Alternative Name: 
    DNS:gitlab.com, DNS:auth.gitlab.com, DNS:customers.gitlab.com, DNS:email.customers.gitlab.com, DNS:gprd.gitlab.com, DNS:www.gitlab.com

Steps to reproduce

Example Project

What is the current bug behavior?

Verification is going to fail just because a user isn't signing commits with the first email address in the X509v3 Subject Alternative Name list.

What is the expected correct behavior?

All email addresses in the X509v3 Subject Alternative Name are valid for that certificate and GitLab should support commits signed with any of them.

Relevant logs and/or screenshots

Output of checks

Results of GitLab environment info

Expand for output related to GitLab environment info

(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:env:info`)

(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)

Results of GitLab application Check

Expand for output related to the GitLab application check

(For installations with omnibus-gitlab package run and paste the output of: sudo gitlab-rake gitlab:check SANITIZE=true)

(For installations from source run and paste the output of: sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true)

(we will only investigate if the tests are passing)

Possible fixes