Rules / GL035
GL035 git URL with embedded credentials (user:token@host) in script
Severity: warn
OWASP: CICD-SEC-6 – Insufficient Credential Hygiene
What glsec checks
glsec flags script lines where a git clone, git push, git fetch, git pull, or git remote command uses a URL containing embedded userinfo credentials in the form https://user:token@host. This exposes the token through:
- The runner's process table — the credential is an argument of the running command (
psshows it) regardless of logging. .git/configinside the container, which may be archived byartifacts: untracked: true.- The job log, conditionally — only when
CI_DEBUG_TRACE/set -xis active (the shell trace then expands the variable), or when the tool does not redact credentials in its own output.
Note that, by default, the token does not appear in the job log: GitLab echoes the raw script text with the variable unexpanded (e.g. git push https://ci:${TOKEN}@…), and Git itself strips the userinfo from its remote output (To https://gitlab.com/org/repo.git). The risk is real but defence-in-depth — it materialises under debug tracing, with non-redacting tools (curl -v, wget), or via the process table. Even a CI-variable token (not hardcoded) is affected.
Trigger example
deploy:
script:
- git push https://ci:${TRANSLATION_TOKEN}@gitlab.com/org/repo.git HEAD:main
Safe alternative
Keep the token out of the URL — and ideally off the command line entirely.
Prefer an SSH remote with a deploy key stored in a protected CI variable (see GL030, GL032); the credential never appears in a URL, in .git/config, or as a command argument:
deploy:
script:
- git push git@${CI_SERVER_HOST}:${CI_PROJECT_PATH}.git HEAD:main
Or feed the token to Git through a credential helper / GIT_ASKPASS that reads it from the environment, so it is never written into the URL or persisted:
deploy:
script:
- git config credential.helper '!f() { echo "username=gitlab-ci-token"; echo "password=$CI_JOB_TOKEN"; }; f'
- git push "https://${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:main
Note:
git remote set-url origin "https://user:${TOKEN}@host/…"is not a fix — it still embeds the credential in the URL and is flagged by this rule.
References
- GitLab docs: Using CI_JOB_TOKEN for authentication
- GL004:
CI_JOB_TOKENforwarded to a non-GitLab host - GL032: SSH private key written to file via
echo - GL036: connection string with embedded credentials in
variables:block
See also
Enable the ShellCheck integration to surface additional shell issues in these script blocks.
Documentation for glsec 1.23.0. Source of this page · Rule implementation