> How can they be avoided without stopping the use of CI/CD?
Use separate systems for CI and CD, and don't put sensitive "keys to the kingdom" credentials in CI. For example:
Put CI in GitHub Actions or GitLab CI without any credentials to write artifacts or knowledge of stage/prod deployments. Let the "interns" in the threat model use this.
Put production CD/release in Jenkins or a similar self hosted, not publicly accessible system. Limit the folks who can trigger jobs in this system to a small group of trusted employees, and don't trigger runs on actions that don't require U2F auth (e.g. require a manual click through the webui protected by SSO, or only deploy from specific branches protected to only allow approved PRs -- no git client pushes).
> I assume it is the same with GitLab?
Yes. While GitLab does offer some secret and variable masking controls, the Travis disclosure earlier this week where all secrets were exposed to Pull Request CI shows you probably don't want to bet your business on those controls. (Acknowledging GitLab != Travis)
Use protected branches (only inject prod secrets on master, which can't be pushed to) and have test secrets for other branches. Now your weak spot is only anyone who can hit merge on a PR to master, which is easy to control.
On gitlab, there has been another way for some time: There is a JWT token CI_JOB_JWT available in an env var which contains the branch name and other info as one of the claims [1]. One can then use this token to obtain production secrets based on whether the branch is trusted.
Github has the same feature upcoming [2], which allows to get also directly AWS or GCP credentials restricted by branch name [3, 4].