Skip to content

Fix panic when PKCS7-encoded payload has no certificate

Stan Hu requested to merge sh-fix-pkcs7-panic into master

Some customers (ZenDesk: https://gitlab.zendesk.com/agent/tickets/191894) have certificate issuers that point to the US Federal Government CA via https://fpki.idmanagement.gov/crls/. Prior to this merge request, jobs that attempted to resolve the issuer certificate for this CA would fail:

Checking for jobs... received job=968529 repo_url=https://gitlab.example.com/group/project.git runner=26c23a42

Processing chain chain-leaf=[0xc0009fd080] context=certificate-chain-build

<snip>
Appending the certificate to the chain Issuer= IssuerCertURL=[http://pki.treasury.gov/noca_aia.p7c] Serial=1312391446 Subject= context=certificate-chain-build method=fetchIssuerCertificate newCertIssuer= newCertIssuerCertURL=[http://pki.treasury.gov/cacertsissuedtotrca.p7c] newCertSerial=1460481024 newCertSubject=
Checking for jobs... nothing runner=Jhy85A8N
Appending the certificate to the chain Issuer= IssuerCertURL=[http://pki.treasury.gov/cacertsissuedtotrca.p7c] Serial=1460481024 Subject= context=certificate-chain-build method=fetchIssuerCertificate newCertIssuer=Federal Common Policy CA newCertIssuerCertURL=[http://http.fpki.gov/fcpca/caCertsIssuedTofcpca.p7c] newCertSerial=29515 newCertSubject=
panic: runtime error: index out of range [0] with length 0
goroutine 194 [running]:
gitlab.com/gitlab-org/gitlab-runner/helpers/tls/ca_chain.decodeCertificate(0xc0007a6000, 0x29, 0x200, 0xc0007a6000, 0x29, 0x200)
/builds/gitlab-org/security/gitlab-runner/helpers/tls/ca_chain/helpers.go:66 +0x2be

This was happening because while the issuer certificate, as shown in newCertIssuerCertURL=[http://http.fpki.gov/fcpca/caCertsIssuedTofcpca.p7c], has a valid PKCS7 payload, it is empty:

$ curl -O http://http.fpki.gov/fcpca/caCertsIssuedTofcpca.p7c
$ openssl pkcs7 -print_certs -in caCertsIssuedTofcpca.p7c -inform DER -noout -print
PKCS7:
  type: pkcs7-signedData (1.2.840.113549.1.7.2)
  d.sign:
    version: 1
    md_algs:
      <EMPTY>
    contents:
      type: pkcs7-data (1.2.840.113549.1.7.1)
      d.data: <ABSENT>
    cert:
      <EMPTY>
    crl:
      <EMPTY>
    signer_info:
      <EMPTY>

pkcs7.Parse() can return a nil payload if no certs were decoded: https://github.com/fullsailor/pkcs7/blob/d7302db945fa6ea264fb79d8e13e931ea514a602/pkcs7.go#L187

Instead of throwing up an error or crashing due to a nil access error, we ignore this issuer certificate and stop resolving credentials. If this root cert is trusted by the system, jobs will go through.

Edited by Stan Hu

Merge request reports