.tmp project directory is joined to "build" directory without proper path parsing

Summary

The .tmp directory is built on top of BuildDir in TmpProjectDir build.go#L250 by simply concatenating a variable value to the string ".tmp". This can cause problems when BuildDir is overridden by the user when GIT_CLONE_PATH is set.

In the CI example below, git clean -ffdx that's run after git fetch can potentially remove .tmp (and everything under BuildDir, depending on how GIT_CLONE_PATH is defined.

Steps to reproduce

  • Set GIT_CLONE_PATH=/build" - TmpDir becomes /build.tmp

    • git fetch current_repo # this checks gitlab.com certs
    • git clean -ffdx (does nothing)
  • Set GIT_CLONE_PATH=/build/ - TmpDir becomes /build/.tmp

    • git fetch current_repo # this checks gitlab.com certs
    • git clean -ffdx (removes .tmp directory)
.gitlab-ci.yml
variables:
  FF_USE_FASTZIP: 1
  # output upload and download progress every 5 seconds
  TRANSFER_METER_FREQUENCY: "5s"
  # Use fastest compression for artifacts, resulting in larger archives
  ARTIFACT_COMPRESSION_LEVEL: "fastest"
  # Use no compression for caches
  CACHE_COMPRESSION_LEVEL: "fastest"
  # Submodule testing stuff
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_DEPTH: 3
  CI_DEBUG_TRACE: "true"
  GIT_TRACE: 2
  GIT_CURL_VERBOSE: 1

test_job:
  stage: build
  image: eu.gcr.io/pex-gcr/pexbuild-debian10:latest
  script:
    - ls -l
    - ls -l test/

Actual behavior

Folder structure hierarchy of TmpDir changes depending on how GIT_CLONE_PATH is defined.

Expected behavior

The path input passed via GIT_CLONE_PATH should always be safely parsed before being used to build TmpDir.

Relevant logs and/or screenshots

job log
13:09:33.404675 run-command.c:663       trace: run_command: GIT_DIR=.git git-remote-https origin https://gitlab-ci-token:[MASKED]@gitlab.com/pexip/sre/testrepo.git
*   Trying xxx.xxx.xxx.xxx:443...
* Connected to gitlab.com (xxx.xxx.xxx.xx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /build/.tmp/CI_SERVER_TLS_CA_FILE
*  CApath: none
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=gitlab.com
*  start date: Apr 12 00:00:00 2021 GMT
*  expire date: May 11 23:59:59 2022 GMT
*  subjectAltName: host "gitlab.com" matched cert's "gitlab.com"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.

# Here you can see the later attempt at cloning the submodule

Cloning into '/build/test'...
13:09:34.736029 run-command.c:663       trace: run_command: git-remote-https origin https://gitlab-ci-token:[MASKED]@gitlab.com/example/test.git
*   Trying xxx.xxx.xxx.xxx:443...
* Connected to gitlab.com (xxx.xxx.xxx.xxx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* error setting certificate verify locations:  CAfile: /build/.tmp/CI_SERVER_TLS_CA_FILE CApath: none
* Closing connection 0
fatal: unable to access 'https://gitlab.com/example/test.git/': error setting certificate verify locations:  CAfile: /build/.tmp/CI_SERVER_TLS_CA_FILE CApath: none
fatal: clone of 'https://gitlab-ci-token:[MASKED]@gitlab.com/gitlab.com/example/test.git' into submodule path '/build/test' failed
Failed to clone 'test' a second time, aborting

Environment description

N/A

Used GitLab Runner version

Possible fixes

TmpProjectDir build.go#L250

Should be probably rewritten as:

return path.join(helpers.ToSlash(b.BuildDir), ".tmp")