<p>This is not answering only the question but also a bit more (I put this here for reference):<br>
I found out a decent way to tackle this and some complications coming afterwards... (after hours and hours of fiddling) - e.g. to execute the script in an SSH session:</p>

<pre class="lang-yaml prettyprint-override"><code>deploy job:
  variables:
    # the variables could come from anywhere (e.g. GitLab Settings - environment variables)
    SSH_DIR: '/srv/app/'
    SCRIPT_CMD: |
      echo "Double quotes are safe"
      echo 'Single quotes are safe'
      echo "Code executions are safe -" `whoami`@`hostname` $$(date)
      # the '$$' is needed as otherwise GitLab itself tries variable substitution

  # Here's the magic to get the code from the GitLab variable into a bash variable and then even executed on an SSH session
  script:
    # Put gitlab variable into shell variable to improve quote handling
    - CMD=$SCRIPT_CMD
    # Print for debugging
    - echo -e "Executing:\n$CMD"
    - CMD="set -e; cd $SSH_DIR; $CMD" # 'set -e' = stop on error
    # redirect variable to stdin of ssh bash (the -x causes bash to print each command)
    - ssh -p $SSH_PORT $USERNAME@$SSH_HOST "bash -x" &lt;&lt;&lt; "$CMD"

</code></pre>

<p>More detailed example <a href="https://gist.github.com/TeNNoX/cd8d4b901775f379d74287fa85f924c3" rel="nofollow noreferrer">here</a>.</p>

CC BY-SA 4.0
2019-10-03T23:29:41.693Z
2019-10-03T23:44:18.603Z
2019-10-03T23:44:18.603Z
TeNNoX
<p>One should use protected variables in my opinion. One could configure them in the pipeline settings and subsequently call them inside the pipeline. Using base64 formats should be avoided as these could be easily decrypted.</p>

<p><a href="https://docs.gitlab.com/ee/ci/variables/" rel="nofollow noreferrer">https://docs.gitlab.com/ee/ci/variables/</a></p>

CC BY-SA 4.0
2019-07-18T09:12:22.763Z
It's a common misconception. Protected env vars in GitLab are not what you think, the main purpose of them is that they are passed only to pipelines of the Protected branches. They are not otherwise protected. There is also a Masked option for env vars which is probably more what you mean, but still it doesn't work all the time - there's a limitation on value, again because it's internally processed by GitLab which it should really do.
Ivan
CC BY-SA 4.0
2019-07-17T20:22:19.993Z
2019-07-17T20:22:19.993Z
030
<p>Surprisingly indeed GitLab works weirdly with the env vars.<br>
It evaluates them internally, though it shouldn't in my view.</p>

<p>Value set as (in project Settings > CI/CD > Variables): <code>'aaa$bbb*%'</code><br>
becomes <code>'aaa*%'</code>
(with single quotes left!)</p>

<p>Couple of of proof links:</p>

<ul>
<li><a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/45173#note_101659865" rel="nofollow noreferrer">https://gitlab.com/gitlab-org/gitlab-ce/issues/45173#note_101659865</a></li>
<li><a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/27436" rel="nofollow noreferrer">https://gitlab.com/gitlab-org/gitlab-ce/issues/27436</a></li>
</ul>

<h2>Workarounds:</h2>

<p>1)
You can duplicate dollar ($) sign, i.e.: <code>aaa$$bbb*%</code><br>
(as mentioned on the first link above).</p>

<p>2)
Use base64 to encode and decode the value.</p>

<p>Do this first:</p>

<pre><code>$ echo 'aaa$bbb*%' | base64
YWFhJGJiYiolCg==
</code></pre>

<p>Then store this value in project Variables.</p>

<p>And then in your script decode it:</p>

<pre><code>PASS=$(echo ${sensitive_var} | base64 -D)
</code></pre>

CC BY-SA 4.0
2019-07-16T18:58:22.483Z
Hi Ivan, thanks for the fast reply.
As explained in the problem I already tried enclosing the value in single quotes.
It may not be related to Gitlab, but the original value is saved as env var in Gitlab, and then is passed in a job to the deployment script. 
Also, the script is on a docker image, so it might be possible that I can't access Gitlab's environment from there.
JJ Yong
CC BY-SA 4.0
2019-07-17T07:40:04.983Z
Where did you enclose the value in single quotes? In CI/CD Settings?
Ivan
CC BY-SA 4.0
2019-07-17T08:08:11.627Z
Yes, in the env vars of CI/CD settings
JJ Yong
CC BY-SA 4.0
2019-07-17T13:47:23.243Z
You are right, I've just tested it... funnily it didn't get rid of single-quotes, how you would expect it in bash case... lemme think...
Ivan
CC BY-SA 4.0
2019-07-17T13:50:10.743Z
See this: https://gitlab.com/gitlab-org/gitlab-ce/issues/45173#note_101659865
Ivan
CC BY-SA 4.0
2019-07-17T13:52:11.833Z
And this: https://gitlab.com/gitlab-org/gitlab-ce/issues/27436
Ivan
CC BY-SA 4.0
2019-07-17T13:52:43.237Z
It's really frustrating... GitLab being awesome has many such weird bugs or missing basic features... it makes me cry sometimes. By the way double-dollar workaround seems to help.
Ivan
CC BY-SA 4.0
2019-07-17T13:53:45.783Z
Another idea to try - is to use `base64` to encode value before storing it, and decode in your script.
Ivan
CC BY-SA 4.0
2019-07-17T16:13:25.047Z
Wow thanks, I thought about the base64 encoding but was thinking in the code, not in the script. I will have to see which option is more maintainable in the long run. Thank you very much
JJ Yong
CC BY-SA 4.0
2019-07-17T16:50:42.197Z
No problem. Good luck with your project.
Ivan
CC BY-SA 4.0
2019-07-16T17:00:49.880Z
2019-07-17T17:06:55.167Z
2019-07-17T17:06:55.167Z
Ivan
<p>I have the following situation:
I'm storing sensitive data in Gitlab's environment and then passing these variables to a deployment script in bash.</p>

<p>Gitlab's env var:</p>

<pre><code>Key: sensitive_var
Value: aaa$bbb*%
</code></pre>

<p>Then in the <code>.gitlab-ci.yml</code> file the env vars are passed to the deployment script as follows:</p>

<pre><code>.deploy:
  script:
    - deploy.sh PASS=${sensitive_var} 
</code></pre>

<p>The deployment script parses the arguments as follows:</p>

<pre><code>for arg; do
  TEMP_VAR=$(echo ${arg} | sed -e 's?=? ?')
done
</code></pre>

<p>The problem is that when we check the output of the <code>deploy.sh</code> script the variable's value gets expanded resulting in <code>aaa*%</code>.</p>

<p>Solutions tried so far:  </p>

<ul>
<li>Storing the value in Gitlab's environment with single quotes <code>'</code> but then the value was <code>'aaa*%'</code>.</li>
<li>Passing the environment variable with double quotes:</li>
</ul>

<pre><code>.deploy:
  script:
    - deploy.sh PASS="${sensitive_var}" 
</code></pre>

<pre><code>.deploy:
  script:
    - deploy.sh PASS="$sensitive_var" 
</code></pre>

<p>But the result was the same: <code>aaa*%</code>.  </p>

<ul>
<li>Combination of the above solutions didn't work either.</li>
</ul>

<p>Why is this happening, and how I can fix it?</p>

<gitlab-ci-runner><bash><yaml><environment-variables>
How to pass Gitlab env var with sensitive characters to bash script?
JJ Yong
# How to pass Gitlab env var with sensitive characters to bash script?

(Asked by: username_0 on 2019-07-16)

I have the following situation:
I'm storing sensitive data in Gitlab's environment and then passing these variables to a deployment script in bash.
Gitlab's env var:
Key: sensitive_var
Value: aaa$bbb*%

Then in the .gitlab-ci.yml file the env vars are passed to the deployment script as follows:
.deploy:
  script:
    - deploy.sh PASS=${sensitive_var} 

The deployment script parses the arguments as follows:
for arg; do
  TEMP_VAR=$(echo ${arg} | sed -e 's?=? ?')
done

The problem is that when we check the output of the deploy.sh script the variable's value gets expanded resulting in aaa*%.
Solutions tried so far:  

Storing the value in Gitlab's environment with single quotes ' but then the value was 'aaa*%'.
Passing the environment variable with double quotes:

.deploy:
  script:
    - deploy.sh PASS="${sensitive_var}" 

.deploy:
  script:
    - deploy.sh PASS="$sensitive_var" 

But the result was the same: aaa*%.  

Combination of the above solutions didn't work either.

Why is this happening, and how I can fix it?

**Tags:** gitlab-ci-runner, bash, yaml, environment-variables


---

## 3 answers

### Answer by username_3 on 2019-07-16. Score: 4 | Accepted answer

Surprisingly indeed GitLab works weirdly with the env vars.
It evaluates them internally, though it shouldn't in my view.
Value set as (in project Settings > CI/CD > Variables): 'aaa$bbb*%'
becomes 'aaa*%'
(with single quotes left!)
Couple of of proof links:

https://gitlab.com/gitlab-org/gitlab-ce/issues/45173#note_101659865
https://gitlab.com/gitlab-org/gitlab-ce/issues/27436

Workarounds:
1)
You can duplicate dollar ($) sign, i.e.: aaa$$bbb*%
(as mentioned on the first link above).
2)
Use base64 to encode and decode the value.
Do this first:
$ echo 'aaa$bbb*%' | base64
YWFhJGJiYiolCg==

Then store this value in project Variables.
And then in your script decode it:
PASS=$(echo ${sensitive_var} | base64 -D)

> **Comments:**
> **username_0**: Hi username_3, thanks for the fast reply. As explained in the problem I already tried enclosing the value in single quotes. It may not be related to Gitlab, but the original value is saved as env var in Gitlab, and then is passed in a job to the deployment script.  Also, the script is on a docker image, so it might be possible that I can't access Gitlab's environment from there.  
> **username_3**: Where did you enclose the value in single quotes? In CI/CD Settings?  
> **username_0**: Yes, in the env vars of CI/CD settings  
> **username_3**: You are right, I've just tested it... funnily it didn't get rid of single-quotes, how you would expect it in bash case... lemme think...  
> **username_3**: See this: https://gitlab.com/gitlab-org/gitlab-ce/issues/45173#note_101659865  
> **username_3**: And this: https://gitlab.com/gitlab-org/gitlab-ce/issues/27436  
> **username_3**: It's really frustrating... GitLab being awesome has many such weird bugs or missing basic features... it makes me cry sometimes. By the way double-dollar workaround seems to help.  
> **username_3**: Another idea to try - is to use `base64` to encode value before storing it, and decode in your script.  
> **username_0**: Wow thanks, I thought about the base64 encoding but was thinking in the code, not in the script. I will have to see which option is more maintainable in the long run. Thank you very much  
> **username_3**: No problem. Good luck with your project.  

---

### Answer by username_1 on 2019-10-03. Score: 2

This is not answering only the question but also a bit more (I put this here for reference):
I found out a decent way to tackle this and some complications coming afterwards... (after hours and hours of fiddling) - e.g. to execute the script in an SSH session:
deploy job:
  variables:
    # the variables could come from anywhere (e.g. GitLab Settings - environment variables)
    SSH_DIR: '/srv/app/'
    SCRIPT_CMD: |
      echo "Double quotes are safe"
      echo 'Single quotes are safe'
      echo "Code executions are safe -" `whoami`@`hostname` $$(date)
      # the '$$' is needed as otherwise GitLab itself tries variable substitution

  # Here's the magic to get the code from the GitLab variable into a bash variable and then even executed on an SSH session
  script:
    # Put gitlab variable into shell variable to improve quote handling
    - CMD=$SCRIPT_CMD
    # Print for debugging
    - echo -e "Executing:\n$CMD"
    - CMD="set -e; cd $SSH_DIR; $CMD" # 'set -e' = stop on error
    # redirect variable to stdin of ssh bash (the -x causes bash to print each command)
    - ssh -p $SSH_PORT $USERNAME@$SSH_HOST "bash -x" <<< "$CMD"


More detailed example here.


---

### Answer by username_2 on 2019-07-17. Score: 0

One should use protected variables in my opinion. One could configure them in the pipeline settings and subsequently call them inside the pipeline. Using base64 formats should be avoided as these could be easily decrypted.

<https://docs.gitlab.com/ee/ci/variables/>

> **Comments:**
> **username_3**: It's a common misconception. Protected env vars in GitLab are not what you think, the main purpose of them is that they are passed only to pipelines of the Protected branches. They are not otherwise protected. There is also a Masked option for env vars which is probably more what you mean, but still it doesn't work all the time - there's a limitation on value, again because it's internally processed by GitLab which it should really do.  

---

