Secrets live encrypted in the controller's credentials store (Credentials Store), and pipelines refer to them by ID. Two harmless demo credentials were added under Manage Jenkins 8,793 > Credentials: a Secret text booknest-demo-token and a Username with password booknest-demo-db. credentials() in environment binds one to a variable, adding _USR and _PSW for a username and password; withCredentials binds for a block:
pipeline {
agent { label 'linux' }
environment {
API_TOKEN = credentials('booknest-demo-token')
DB = credentials('booknest-demo-db')
}
stages {
stage('Use secrets') {
steps {
sh 'echo "token=$API_TOKEN (${#API_TOKEN} chars) user=$DB_USR password=$DB_PSW"'
sh "echo unsafe: ${API_TOKEN}"
withCredentials([string(credentialsId: 'booknest-demo-token', variable: 'T')]) {
sh 'printf %s "$T" | sha256sum | cut -c1-16'
}
}
}
}
}The lines the steps printed, and Jenkins' warning:
token=**** (26 chars) user=**** password=**** Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure. unsafe: **** 9ba9cd92d898527a
The shell got the real 26-character value; the log shows ****. The double-quoted sh pasted the secret into the command text, where process listings and stored step arguments can reveal it. Masking is only a string match: the hash, or a base64 copy, passes straight through. Use single-quoted sh strings, and scope credentials to folders (Credentials Store).