gitlab: RequestError: self-signed certificate

Since last weekend I get an error due to self-signed certificate. The setup that did the same job until now was:

docker image: node:18
export GIT_SSL_NO_VERIFY=1
export NODE_TLS_REJECT_UNAUTHORIZED=0
npm install @semantic-release/gitlab @semantic-release/exec @semantic-release/changelog @semantic-release/git
npx semantic-release --generate-notes false --dry-run

ERROR:

$ npx semantic-release --generate-notes false --dry-run
[10:19:28 AM] [semantic-release] › ℹ  Running semantic-release version 20.1.0
(node:47) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/changelog"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/git"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/gitlab"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/exec"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "analyzeCommits" from "@semantic-release/commit-analyzer"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "analyzeCommits" from "@semantic-release/exec"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "verifyRelease" from "@semantic-release/exec"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/changelog"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/git"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/exec"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/gitlab"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/exec"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "addChannel" from "@semantic-release/exec"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "success" from "@semantic-release/gitlab"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "success" from "@semantic-release/exec"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "fail" from "@semantic-release/gitlab"
[10:19:28 AM] [semantic-release] › ✔  Loaded plugin "fail" from "@semantic-release/exec"
[10:19:31 AM] [semantic-release] › ⚠  Run automated release from branch main on repository https://gitlab-ci-token:[secure]@SERVER/PATH_TO_REPO.git in dry-run mode
[10:19:32 AM] [semantic-release] › ✔  Allowed to push to the Git repository
[10:19:32 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/changelog"
[10:19:32 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/changelog"
[10:19:32 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/git"
[10:19:32 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/git"
[10:19:32 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/gitlab"
[10:19:32 AM] [semantic-release] [@semantic-release/gitlab] › ℹ  Verify GitLab authentication (https://SERVER/api/v4)
(node:47) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
[10:19:32 AM] [semantic-release] › ✘  Failed step "verifyConditions" of plugin "@semantic-release/gitlab"
[10:19:32 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/exec"
[10:19:32 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/exec"
[10:19:32 AM] [semantic-release] › ✘  An error occurred while running semantic-release: RequestError: self-signed certificate
    at ClientRequest.<anonymous> (file:///builds/PATH_TO_REPO/node_modules/got/dist/source/core/index.js:789:107)
    at Object.onceWrapper (node:events:628:26)
    at ClientRequest.emit (node:events:525:35)
    at TLSSocket.socketErrorListener (node:_http_client:496:9)
    at TLSSocket.emit (node:events:513:28)
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
    at TLSSocket.onConnectSecure (node:_tls_wrap:1545:34)
    at TLSSocket.emit (node:events:513:28)
    at TLSSocket._finishInit (node:_tls_wrap:959:8)
    at ssl.onhandshakedone (node:_tls_wrap:743:12) {
  input: undefined,
  code: 'DEPTH_ZERO_SELF_SIGNED_CERT',
  timings: {
    start: 1675073972164,
    socket: 1675073972166,
    lookup: 1675073972167,
    connect: 1675073972168,
    secureConnect: undefined,
    upload: undefined,
    response: undefined,
    end: undefined,
    error: 1675073972170,
    abort: undefined,
    phases: {
      wait: 2,
      dns: 1,
      tcp: 1,
      tls: undefined,
      request: undefined,
      firstByte: undefined,
      download: undefined,
      total: 6
    }
  },
  options: {
    request: undefined,
    agent: { http: undefined, https: undefined, http2: undefined },
    h2session: undefined,
    decompress: true,
    timeout: {
      connect: undefined,
      lookup: undefined,
      read: undefined,
      request: undefined,
      response: undefined,
      secureConnect: undefined,
      send: undefined,
      socket: undefined
    },
    prefixUrl: '',
    body: undefined,
    form: undefined,
    json: undefined,
    cookieJar: undefined,
    ignoreInvalidCookies: false,
    searchParams: undefined,
    dnsLookup: undefined,
    dnsCache: undefined,
    context: {},
    hooks: {
      init: [],
      beforeRequest: [],
      beforeError: [],
      beforeRedirect: [],
      beforeRetry: [],
      afterResponse: []
    },
    followRedirect: true,
    maxRedirects: 10,
    cache: undefined,
    throwHttpErrors: true,
    username: '',
    password: '',
    http2: false,
    allowGetBody: false,
    headers: {
      'user-agent': 'got (https://github.com/sindresorhus/got)',
      'private-token': '[secure]',
      accept: 'application/json',
      'accept-encoding': 'gzip, deflate, br'
    },
    methodRewriting: false,
    dnsLookupIpVersion: undefined,
    parseJson: [Function: parse],
    stringifyJson: [Function: stringify],
    retry: {
      limit: 2,
      methods: [ 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' ],
      statusCodes: [
        408, 413, 429, 500,
        502, 503, 504, 521,
        522, 524
      ],
      errorCodes: [
        'ETIMEDOUT',
        'ECONNRESET',
        'EADDRINUSE',
        'ECONNREFUSED',
        'EPIPE',
        'ENOTFOUND',
        'ENETUNREACH',
        'EAI_AGAIN'
      ],
      maxRetryAfter: undefined,
      calculateDelay: [Function: calculateDelay],
      backoffLimit: Infinity,
      noise: 100
    },
    localAddress: undefined,
    method: 'GET',
    createConnection: undefined,
    cacheOptions: {
      shared: undefined,
      cacheHeuristic: undefined,
      immutableMinTimeToLive: undefined,
      ignoreCargoCult: undefined
    },
    https: {
      alpnProtocols: undefined,
      rejectUnauthorized: undefined,
      checkServerIdentity: undefined,
      certificateAuthority: undefined,
      key: undefined,
      certificate: undefined,
      passphrase: undefined,
      pfx: undefined,
      ciphers: undefined,
      honorCipherOrder: undefined,
      minVersion: undefined,
      maxVersion: undefined,
      signatureAlgorithms: undefined,
      tlsSessionLifetime: undefined,
      dhparam: undefined,
      ecdhCurve: undefined,
      certificateRevocationLists: undefined
    },
    encoding: undefined,
    resolveBodyOnly: false,
    isStream: false,
    responseType: 'text',
    url: URL {
      href: 'https://SERVER/api/v4/projects/PATH%2FTO%2FREPO',
      origin: 'https://SERVER',
      protocol: 'https:',
      username: '',
      password: '',
      host: 'SERVER',
      hostname: 'SERVER',
      port: '',
      pathname: '/api/v4/projects/PATH%2FTO%2FREPO',
      search: '',
      searchParams: URLSearchParams {},
      hash: ''
    },
    pagination: {
      transform: [Function: transform],
      paginate: [Function: paginate],
      filter: [Function: filter],
      shouldContinue: [Function: shouldContinue],
      countLimit: Infinity,
      backoff: 0,
      requestLimit: 10000,
      stackAllItems: false
    },
    setHost: true,
    maxHeaderSize: undefined,
    signal: undefined,
    enableUnixSockets: true
  },
  pluginName: '@semantic-release/gitlab'
}
AggregateError: 
    RequestError: self-signed certificate
        at ClientRequest.<anonymous> (file:///builds/PATH_TO_REPO/node_modules/got/dist/source/core/index.js:789:107)
    at file:///builds/PATH_TO_REPO/node_modules/semantic-release/lib/plugins/pipeline.js:54:11
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async pluginsConfigAccumulator.<computed> [as verifyConditions] (file:///builds/PATH_TO_REPO/node_modules/semantic-release/lib/plugins/index.js:87:11)
    at async run (file:///builds/PATH_TO_REPO/node_modules/semantic-release/index.js:106:3)
    at async Module.default (file:///builds/PATH_TO_REPO/node_modules/semantic-release/index.js:275:22)
    at async default (file:///builds/PATH_TO_REPO/node_modules/semantic-release/cli.js:55:5) {
  errors: [
    RequestError: self-signed certificate
        at ClientRequest.<anonymous> (file:///builds/PATH_TO_REPO/node_modules/got/dist/source/core/index.js:789:107)
        at Object.onceWrapper (node:events:628:26)
        at ClientRequest.emit (node:events:525:35)
        at TLSSocket.socketErrorListener (node:_http_client:496:9)
        at TLSSocket.emit (node:events:513:28)
        at emitErrorNT (node:internal/streams/destroy:151:8)
        at emitErrorCloseNT (node:internal/streams/destroy:116:3)
        at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
        at TLSSocket.onConnectSecure (node:_tls_wrap:1545:34)
        at TLSSocket.emit (node:events:513:28)
        at TLSSocket._finishInit (node:_tls_wrap:959:8)
        at ssl.onhandshakedone (node:_tls_wrap:743:12) {
      input: undefined,
      code: 'DEPTH_ZERO_SELF_SIGNED_CERT',
      timings: [Object],
      options: {
        request: undefined,
        agent: { http: undefined, https: undefined, http2: undefined },
        h2session: undefined,
        decompress: true,
        timeout: {
          connect: undefined,
          lookup: undefined,
          read: undefined,
          request: undefined,
          response: undefined,
          secureConnect: undefined,
          send: undefined,
          socket: undefined
        },
        prefixUrl: '',
        body: undefined,
        form: undefined,
        json: undefined,
        cookieJar: undefined,
        ignoreInvalidCookies: false,
        searchParams: undefined,
        dnsLookup: undefined,
        dnsCache: undefined,
        context: {},
        hooks: {
          init: [],
          beforeRequest: [],
          beforeError: [],
          beforeRedirect: [],
          beforeRetry: [],
          afterResponse: []
        },
        followRedirect: true,
        maxRedirects: 10,
        cache: undefined,
        throwHttpErrors: true,
        username: '',
        password: '',
        http2: false,
        allowGetBody: false,
        headers: {
          'user-agent': 'got (https://github.com/sindresorhus/got)',
          'private-token': '[secure]',
          accept: 'application/json',
          'accept-encoding': 'gzip, deflate, br'
        },
        methodRewriting: false,
        dnsLookupIpVersion: undefined,
        parseJson: [Function: parse],
        stringifyJson: [Function: stringify],
        retry: {
          limit: 2,
          methods: [ 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' ],
          statusCodes: [
            408, 413, 429, 500,
            502, 503, 504, 521,
            522, 524
          ],
          errorCodes: [
            'ETIMEDOUT',
            'ECONNRESET',
            'EADDRINUSE',
            'ECONNREFUSED',
            'EPIPE',
            'ENOTFOUND',
            'ENETUNREACH',
            'EAI_AGAIN'
          ],
          maxRetryAfter: undefined,
          calculateDelay: [Function: calculateDelay],
          backoffLimit: Infinity,
          noise: 100
        },
        localAddress: undefined,
        method: 'GET',
        createConnection: undefined,
        cacheOptions: {
          shared: undefined,
          cacheHeuristic: undefined,
          immutableMinTimeToLive: undefined,
          ignoreCargoCult: undefined
        },
        https: {
          alpnProtocols: undefined,
          rejectUnauthorized: undefined,
          checkServerIdentity: undefined,
          certificateAuthority: undefined,
          key: undefined,
          certificate: undefined,
          passphrase: undefined,
          pfx: undefined,
          ciphers: undefined,
          honorCipherOrder: undefined,
          minVersion: undefined,
          maxVersion: undefined,
          signatureAlgorithms: undefined,
          tlsSessionLifetime: undefined,
          dhparam: undefined,
          ecdhCurve: undefined,
          certificateRevocationLists: undefined
        },
        encoding: undefined,
        resolveBodyOnly: false,
        isStream: false,
        responseType: 'text',
        url: URL {
          href: 'https://SERVER/api/v4/projects/PATH%2FTO%2FREPO',
          origin: 'https://SERVER',
          protocol: 'https:',
          username: '',
          password: '',
          host: 'SERVER',
          hostname: 'SERVER',
          port: '',
          pathname: '/api/v4/projects/PATH%2FTO%2FREPO',
          search: '',
          searchParams: URLSearchParams {},
          hash: ''
        },
        pagination: {
          transform: [Function: transform],
          paginate: [Function: paginate],
          filter: [Function: filter],
          shouldContinue: [Function: shouldContinue],
          countLimit: Infinity,
          backoff: 0,
          requestLimit: 10000,
          stackAllItems: false
        },
        setHost: true,
        maxHeaderSize: undefined,
        signal: undefined,
        enableUnixSockets: true
      },
      pluginName: '@semantic-release/gitlab'
    }
  ]
}

Expected behavior (until last week):

$ npx semantic-release --generate-notes false --dry-run
[2:03:42 AM] [semantic-release] › ℹ  Running semantic-release version 20.1.0
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/changelog"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/git"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/gitlab"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/exec"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "analyzeCommits" from "@semantic-release/commit-analyzer"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "analyzeCommits" from "@semantic-release/exec"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "verifyRelease" from "@semantic-release/exec"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/changelog"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/git"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/exec"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/gitlab"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/exec"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "addChannel" from "@semantic-release/exec"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "success" from "@semantic-release/gitlab"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "success" from "@semantic-release/exec"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "fail" from "@semantic-release/gitlab"
[2:03:42 AM] [semantic-release] › ✔  Loaded plugin "fail" from "@semantic-release/exec"
[2:03:46 AM] [semantic-release] › ⚠  Run automated release from branch main on repository https://gitlab-ci-token:[secure]@SERVER/PATH_TO_REPO.git in dry-run mode
[2:03:47 AM] [semantic-release] › ✔  Allowed to push to the Git repository
[2:03:47 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/changelog"
[2:03:47 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/changelog"
[2:03:47 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/git"
[2:03:47 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/git"
[2:03:47 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/gitlab"
[2:03:47 AM] [semantic-release] [@semantic-release/gitlab] › ℹ  Verify GitLab authentication (https://SERVER/api/v4)
(node:37) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
[2:03:47 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/gitlab"

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 26 (11 by maintainers)

Commits related to this issue

Most upvoted comments

And for now I completely understand. NodeJS uses a built-in set of certificates: https://github.com/nodejs/node/blob/main/src/node_root_certs.h Because of this, addition to system list of CAs does not have effect for got.

And I found solution! Instead of NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt we can use more obvious NODE_OPTIONS=--use-openssl-ca.

--use-openssl-ca - This setting forces the application to use the system’s list of CAs. Thats all we need.

having same issue. Probably comes from here: https://github.com/semantic-release/gitlab/commit/ffa17a8dc16eb8b432e72935c1ac76ed1bfcfd8f

the only solution that I found was to downgrade the plugin version( npm install @semantic-release/gitlab@v10.0.1)

Another way without completely disabling security.

OS: Debian 11 (node:19 docker image)

If you have own CA and certificates signed with it.

Add CA to system trusted certs inside /usr/local/share/ca-certificates/, for example /usr/local/share/ca-certificates/MyCA.crt

If you have selfsigned certificates.

Add selfsigned cert:

echo | openssl s_client -servername mydomain.local -connect mydomain.local:443 2>/dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /usr/local/share/ca-certificates/mydomain.local.crt

And then

  • run update-ca-certificates
  • This is enough for usual tools like curl. Don’t know why, but not enough for got.
  • We can add NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt variable to env, and now all is working

This is really strange, why got not use system list of trusted certs. If any body know, please tell me =)

@geigervlad @jagiella @artem-shestakov The previous behavior was restored in https://github.com/semantic-release/gitlab/releases/tag/v10.1.4.

I’ll leave this issue open until it’s clear how we solve this long-term.

having same issue. Probably comes from here: ffa17a8

the only solution that I found was to downgrade the plugin version( npm install @semantic-release/gitlab@v10.0.1)

Downgrading did the trick! Thanks!

But the whole way of using workarounds for dealing with self-signed certificates remains highly unsatisfying in general… An official mechanism, option etc. to enable self-signed certificates would be highly appreciated.

I even tried adding the server certificate to the trusted list:

echo -n | openssl s_client -connect $SERVERNAME:443 -servername $SERVERNAME | openssl x509 | sudo tee /usr/local/share/ca-certificates/$SERVERNAME.crt
sudo update-ca-certificates

That works on my maschine 👍 , but still fails if run in a docker container 👎.

Hi @Teles1

To have semantic-release/gitlab work with NODE_TLS_REJECT_UNAUTHORIZED=0 you need to explicitly install @semantic-release/gitlab@10.1.4 installing the latest version will not work because the underlying libraries have made changes and no longer utilize NODE_TLS_REJECT_UNAUTHORIZED=0

I’m pretty sure I went as far back as 10.0.0 and it didn’t work. The error output was obviously different but when I dug down it pointed at my tls certificate not being valid. I’ll try again soon and let you know. Thank you for taking the time to look into this for me.

edit: Yep. It did indeed work. I had problems with my token itself that didn’t have API permissions. Thank you!

Hi Everyone, thanks for all the great info above.

From what I understand, this issue has been resolved and the current consesus is to either downgrade to semantic-release/gitlab v10.1.4 so that setting NODE_TLS_REJECT_UNAUTHORIZED=0 will work, or use NODE_OPTIONS=--use-openssl-ca along with what was suggested here https://github.com/semantic-release/gitlab/issues/489#issuecomment-1481225666 to get it to trust a self signed certificate? I’ve been trying to get this working on an Alpine distro with v21.5.0 of nodejs but I had absolutely no luck with trusting the self signed certificate. Although, downgrading to v10.1.4 and setting NODE_TLS_REJECT_UNAUTHORIZED=0 worked like a charm.

I thought I would just leave this here for what it is worth, in case this is an Alpine specific issue and it can save someone with a similar setup to mine some time.

Hey, thanks for this discussion. I’m commenting in case someone else finds this w/ the same problem I had.

  • I have an internal website (git.domain.com)
  • it was using a public wildcard cert (*.domain.com) from digicert (the domain.com is public)

I had the node environment variable set, but now obviously not working. I should have not needed it… it turns out that when you send a cert through nginx it must be the full chain cert

<* cert>
<intermediate>
<root>

If it does not come in this order then got will fail.

It was as simple as adding the cert chain into the end my gitlab cert file (/etc/gitlab/ssl/git.domain.com.crt) and then restarting nginx with sudo gitlab-ctl restart nginx

of course in your gitlab config (sudo nano /etc/gitlab/gitlab.rb) the nginx["ssl ... cert"] should be this file…

You can verify it after restarting nginx with echo | /opt/gitlab/embedded/bin/openssl s_client -connect git.domain.com:443

I’d suggest we perform the update, but indicate a breaking change. Any objections/concerns?

i would say that it isn’t necessary because this isn’t really a change to this plugin directly and isn’t actually an officially supported use case. that said, i think there is value in drawing attention to the fact that it is known that this will impact some consumers and this is an opportunity to encourage them to fix the gap in their supply chain security. there is also value in having a major bump to allow consumers to continue using an old version that continues to use the old got version without risk of an in-range version causing that to change. in short, i’m supportive of the change being treated as breaking.

i think it would be valuable to link to this thread from the release notes (even if it is a modification after the release) for additional context. i would also recommend calling out that it is an option for folks to use an older version if they choose to ignore the security implications of using a self-signed cert without taking the steps to handle it in a trust verifying way.

In container same issue. Adding certs by

echo | openssl s_client -servername <servername> -connect <servername>:443 |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /usr/local/share/ca-certificates/<cert_name>.crt
update-ca-certificates   

or using NODE_TLS_REJECT_UNAUTHORIZED: 0 dose not work.

Verify GitLab authentication (https://....sys.local/api/v4)

(node:5186) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
[8:43:55 AM] [semantic-release] › ✘  Failed step "verifyConditions" of plugin "@semantic-release/gitlab"
[8:43:55 AM] [semantic-release] › ✘  An error occurred while running semantic-release: RequestError: unable to verify the first certificate
...
RequestError: unable to verify the first certificate
        at ClientRequest.<anonymous> (file:///fluent_bit/node_modules/got/dist/source/core/index.js:789:107)
        at Object.onceWrapper (node:events:627:26)
        at ClientRequest.emit (node:events:524:35)
        at TLSSocket.socketErrorListener (node:_http_client:496:9)
        at TLSSocket.emit (node:events:512:28)
        at emitErrorNT (node:internal/streams/destroy:151:8)
        at emitErrorCloseNT (node:internal/streams/destroy:116:3)
        at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
        at TLSSocket.onConnectSecure (node:_tls_wrap:1540:34)
        at TLSSocket.emit (node:events:512:28)
        at TLSSocket._finishInit (node:_tls_wrap:959:8)
        at ssl.onhandshakedone (node:_tls_wrap:743:12) {
      input: undefined,
      code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',

@semantic-release/gitlab@v10.0.1 works fine !!! Thanks @geigervlad