Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-47101

Pipeline withCredentials step does not mask step descriptions for variables with the same name as existing system variables

    • 2.85

      There seems to be an issue with the Pipeline step withCredentials and how it masks variables.

      It seems that when a variable name already exists in the current environment, the step description masking is skipped and the variables are rendered as clear text.

      In the console log, the steps are masked correctly (the step description is not included anyway).

      I first observed this happening in the Blue Ocean UI as part of a script pipeline job.

      As a workaround, using a script seems to hide the step description (for shell cmds at least).

      Pipeline code to reproduce:

      pipeline {
          agent any
          
          stages {
              stage('test withCredentials bug'){
                  steps {
                      withCredentials([usernameColonPassword(credentialsId: 'withCredentialsBug', variable: 'USER')]) {
                          sh "echo '$USER'"
                          sh './user.sh'
                      }
                      
                      withCredentials([usernameColonPassword(credentialsId: 'withCredentialsBug', variable: 'USRPWD')]) {
                          sh "echo '$USRPWD'"
                          sh './user.sh'
                      }
                  }
              }
          }
      }
      

      user.sh helper script exists in the workspace:

      echo "\$USERPWD = $USRPWD"
      echo "\$USER = $USER"
      

      I've attached some screenshots below.

          [JENKINS-47101] Pipeline withCredentials step does not mask step descriptions for variables with the same name as existing system variables

          Catalin Cretu added a comment - - edited

          I've had a look around existing issues, but I couldn't really find this sort of bug. I'm not entirely sure about the priority either.

          Catalin Cretu added a comment - - edited I've had a look around existing issues, but I couldn't really find this sort of bug. I'm not entirely sure about the priority either.

          Jesse Glick added a comment -

          Due to the hack in ArgumentsActionImpl.SAFE_ENVIRONMENT_VARIABLES which tries to guess which things are secrets but does not really know.

          What I recommended to svanoort when he initially wrote this code was that we should rather get some coöperation from plugins which define secret environment variables. For freestyle projects we have getSensitiveBuildVariables but there is no Pipeline equivalent; and EnvVars has no way of marking secret values.

          One option would be to introduce a new API into core and have credentials-binding, mask-passwords, and workflow-cps all depend on it. This would be probably be some more structure in EnvVars, with the various merging/appending methods updated accordingly.

          Or, an explicit contextual object representing a Set<String> of secret variable names could be introduced into workflow-step-api, a lightweight dependency that credentials-binding already has. This would be trickier to use from mask-passwords, however, since MaskPasswordsBuildWrapper could no longer be a SimpleBuildWrapper—it would need to be split into a distinct Step.

          The least intrusive approach, at the expense of compile-time safety, would be to adopt a simple convention along the same lines as PATH+STUFF=/opt/stuff/bin. For example, if CredentialsBindingStep is defining USRPWD=s3cr3t, it should also define something like SECRET+USRPWD=true. Both variables would propagate through to nested scopes in the usual way, and then ArgumentsActionImpl could tell for sure that it should mask s3cr3t because it sees the environment variable SECRET+USRPWD.

          Jesse Glick added a comment - Due to the hack in ArgumentsActionImpl.SAFE_ENVIRONMENT_VARIABLES which tries to guess which things are secrets but does not really know. What I recommended to svanoort when he initially wrote this code was that we should rather get some coöperation from plugins which define secret environment variables. For freestyle projects we have getSensitiveBuildVariables but there is no Pipeline equivalent; and EnvVars has no way of marking secret values. One option would be to introduce a new API into core and have credentials-binding , mask-passwords , and workflow-cps all depend on it. This would be probably be some more structure in EnvVars , with the various merging/appending methods updated accordingly. Or, an explicit contextual object representing a Set<String> of secret variable names could be introduced into workflow-step-api , a lightweight dependency that credentials-binding already has. This would be trickier to use from mask-passwords , however, since MaskPasswordsBuildWrapper could no longer be a SimpleBuildWrapper —it would need to be split into a distinct Step . The least intrusive approach, at the expense of compile-time safety, would be to adopt a simple convention along the same lines as PATH+STUFF=/opt/stuff/bin . For example, if CredentialsBindingStep is defining USRPWD=s3cr3t , it should also define something like SECRET+USRPWD=true . Both variables would propagate through to nested scopes in the usual way, and then ArgumentsActionImpl could tell for sure that it should mask s3cr3t because it sees the environment variable SECRET+USRPWD .

          Prum And added a comment -

          This ticket is rather old, but I still have this issue. I would love to assemble my shell script in groovy, but I guess there is no way to do that, without leaking my passwords.?

          Prum And added a comment - This ticket is rather old, but I still have this issue. I would love to assemble my shell script in groovy, but I guess there is no way to do that, without leaking my passwords.?

          Prum And added a comment - - edited

          I found a solution for my problem. The following way I can assemble my scripts without leaking the passwords:

          withCredentials([
                  usernamePassword(
                      credentialsId: 'my-secret',
                      usernameVariable: 'USER',
                      passwordVariable: 'PASSWORD'
                  )
              ]) {
                  withEnv([
                     "USER=${USER}",
                     "PASSWORD=${PASSWORD}",
                  ]) {
                     sh 'some-command $USER $PASSWORD' // single quotes for bash variables
                   .....
          

          Prum And added a comment - - edited I found a solution for my problem. The following way I can assemble my scripts without leaking the passwords: withCredentials([ usernamePassword( credentialsId: 'my-secret' , usernameVariable: 'USER' , passwordVariable: 'PASSWORD' ) ]) { withEnv([ "USER=${USER}" , "PASSWORD=${PASSWORD}" , ]) { sh 'some-command $USER $PASSWORD' // single quotes for bash variables .....

          Jesse Glick added a comment -

          single quotes for bash variables

          Yes this is what the documentation tells you to do. The secret detection in ArgumentsAction (used, e.g., by Blue Ocean step summaries) is intended as a fallback defense for people who did not read that documentation.

          Jesse Glick added a comment - single quotes for bash variables Yes this is what the documentation tells you to do . The secret detection in ArgumentsAction (used, e.g., by Blue Ocean step summaries) is intended as a fallback defense for people who did not read that documentation.

          Carroll Chiou added a comment -

          Fix in workflow-cps 2.85

          Carroll Chiou added a comment - Fix in workflow-cps 2.85

            Unassigned Unassigned
            catalin_cretu Catalin Cretu
            Votes:
            5 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: