# Masking local strings in Groovy

**URL:** <https://community.jenkins.io/t/masking-local-strings-in-groovy/14790>\
**Category:** Using Jenkins\
**Created:** [May 3, 2024, 1:03pm UTC](https://community.jenkins.io/t/masking-local-strings-in-groovy/14790 "2024-05-03T13:03:07Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![j-koehler](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/j-koehler/32/7383_2.png) [@j-koehler](https://community.jenkins.io/u/j-koehler)\
**Post date:** [May 3, 2024, 1:03pm UTC](https://community.jenkins.io/t/masking-local-strings-in-groovy/14790/1 "2024-05-03T13:03:07Z")

</div>

Using Jenkins 2.440.2.

I am using credentials but for some reason I have to urlencode one of the credentials (since it’s used together with `sh 'curl ...'`) but it is also used in a “plain” version.

Unfortunately, Jenkins is leaking the encoded password when it differs from the credential.

```auto
withCredentials([usernamePassword(credentialsId: 'xyz', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
    script {
        String duplicate_password = env.PASSWORD
        String encoded_password = java.net.URLEncoder.encode(env.PASSWORD, "UTF-8")

        echo "credential password is ${env.PASSWORD}"
        echo "duplicate_password is ${duplicate_password}"
        echo "encoded_password is ${encoded_password}"
    }
}

```

The output of this is:

```auto
14:45:20 Warning: A secret was passed to "echo" using Groovy String interpolation, which is insecure.
14:45:20 Affected argument(s) used the following variable(s): [PASSWORD]
14:45:20 See https:// ****.io/redirect/groovy-string-interpolation for details.
14:45:20 credential password is ****
14:45:20 [Pipeline] echo
14:45:20 Warning: A secret was passed to "echo" using Groovy String interpolation, which is insecure.
14:45:20 Affected argument(s) used the following variable(s): [PASSWORD]
14:45:20 See https:// ****.io/redirect/groovy-string-interpolation for details.
14:45:20 duplicate_password is ****
14:45:20 [Pipeline] echo
14:45:20 encoded_password is REDACTED

```

Is there a way or plugin to be able to create a local variable which is masked in `echo` and `sh` (here: output and blue ocean label, not the actual command executed)?

At the moment I can only see two options, both of which have their disadvantages:

1. Have two credentials: one urlencoded, the other one as plaintext
2. Ensure the credential requires no urlencoding

Both options have the disadvantage that they can easily be forgotten when changing passwords and the like. It would therefore be best if there were a way to do this programmatically.

Does anybody know of such an option?

Thank you!

---

<div class="post-metadata">

**Author:** ![mawinter69](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/mawinter69/32/1625_2.png) [@mawinter69](https://community.jenkins.io/u/mawinter69)\
**Post date:** [May 3, 2024, 1:39pm UTC](https://community.jenkins.io/t/masking-local-strings-in-groovy/14790/2 "2024-05-03T13:39:34Z")

</div>

The plugin [Mask Passwords](https://plugins.jenkins.io/mask-passwords/) allows to do this

```auto
maskPasswords(varPasswordPairs: [[password: encoded_password , var: 'USERNAME']]) {
  echo "encoded_password is ${encoded_password}"
}

```

---

<div class="post-metadata">

**Author:** ![j-koehler](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/j-koehler/32/7383_2.png) [@j-koehler](https://community.jenkins.io/u/j-koehler)\
**Post date:** [May 3, 2024, 1:54pm UTC](https://community.jenkins.io/t/masking-local-strings-in-groovy/14790/3 "2024-05-03T13:54:35Z")

</div>

Oh thank you! 🙂 I stumbled across this plugin before, but hadn’t given it any further consideration because in the README it sounded like I needed to know my variables to mask (and their values) beforehand and define them in per job in the job configuration. So very cumbersome and parallel to the credentials.

But from your snippet it sounds much more useful and exactly what I’m looking for. Am I right to assume, I would have to create a nested withCredentials/maskPasswords setup? Something like this (pseudo code):

```auto
...
withCredentials(...) {
    ...
    maskPasswords(...) {
      ...
    } 
   ...
}
...

```

---

<div class="post-metadata">

**Author:** ![mawinter69](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/mawinter69/32/1625_2.png) [@mawinter69](https://community.jenkins.io/u/mawinter69)\
**Post date:** [May 3, 2024, 2:11pm UTC](https://community.jenkins.io/t/masking-local-strings-in-groovy/14790/4 "2024-05-03T14:11:25Z")

</div>

In freestyle jobs you would need to know them in advance but in pipeline you can do it dynamically.

And yes you’re right need to nest the things.

---

<div class="post-metadata">

**Author:** ![j-koehler](https://dub1.discourse-cdn.com/flex013/user_avatar/community.jenkins.io/j-koehler/32/7383_2.png) [@j-koehler](https://community.jenkins.io/u/j-koehler)\
**Post date:** [May 4, 2024, 12:02pm UTC](https://community.jenkins.io/t/masking-local-strings-in-groovy/14790/5 "2024-05-04T12:02:24Z")

</div>

Thank you so much, it now works.

Was some more work to do to avoid leaking through Blue Ocean output of the `sh` command as well but it now works.

My solution now (no pseudo code but only the bare minimum):

```auto
withCredentials([usernamePassword(credentialsId: 'xyz', passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
script {
    String encoded_password = java.net.URLEncoder.encode(env.GIT_PASSWORD, "UTF-8")
    maskPasswords(varPasswordPairs: [[password: encoded_password]]) {
        String git_url = env.GIT_URL.replace("https://", "https://${GIT_USERNAME}:${encoded_password}@")
         // we have to add the local variable to the environment, otherwise the secure `sh '...'` will not interpolate the variable
        env.CREDENTIAL_GIT_URL = git_url
        // use single quotes to avoid leaking trough blue ocean output of the command
        sh 'git push -f --tags ${CREDENTIAL_GIT_URL}'
   }
}

```

There might be an easier way but this works.
