Aitor Moya Lopez d84f69e91c Propagate readOnlyMode into all dropdownDescriptorSelector fragments in core (#27167)
* Propagate readOnlyMode into SCM Checkout Strategy descriptor config

f:dropdownDescriptorSelector renders its selected descriptor's config.jelly
lazily via AJAX (lib/form/dropdownDescriptorSelector.jelly), and only
variables listed in its `capture` attribute are visible to that lazily
rendered fragment. hudson/model/Job/configure.jelly sets readOnlyMode for
the whole config page, but lib/hudson/project/config-scm.jelly's call for
scmCheckoutStrategy didn't capture it, so a Job's SCM Checkout Strategy
config fragment was not disabled for read-only viewers (Item.READ +
Item.EXTENDED_READ, no Item.CONFIGURE), even though every other field on
the page correctly disables in that case.

This mirrors the same gap that was originally found and fixed in
cloudbees-folder-plugin (JENKINS-62218,
jenkinsci/cloudbees-folder-plugin#747) and reverted there since it's a
core issue affecting every Job configuration page, not just folders. Part
of the JENKINS-12548 read-only system configuration browsing epic
(JEP-224). No Jira ticket filed yet for this specific core gap.

* Propagate readOnlyMode to remaining dropdownDescriptorSelector fragments

f:dropdownDescriptorSelector defers rendering of every non-selected
descriptor's config.jelly/config.groovy via l:renderOnDemand, which only
forwards variables named in its `capture` attribute into that later
AJAX-rendered fragment. readOnlyMode (JEP-224, JENKINS-12548) is not
forwarded by default, so a viewer with Item.EXTENDED_READ but not
Item.CONFIGURE can get back a fully editable fragment for any option other
than the currently selected one, even though the rest of the page correctly
disables.

The gap was first found and fixed for the SCM Checkout Strategy dropdown on
Job/configure.jelly (previous commit, also reported against
cloudbees-folder-plugin#747 / JENKINS-62218 and reverted there as a core
issue). Review of that fix pointed out the bug is generic to
dropdownDescriptorSelector, not specific to SCM Checkout Strategy. This
commit closes the remaining Job/agent-configuration-scoped call sites found
by auditing all *.jelly and *.groovy usages of the tag in core:

- HudsonPrivateSecurityRealm/config.jelly (Password Complexity Rule)
- DelegatingComputerLauncher/config.jelly and DumbSlave/configure-entries.jelly
  (agent Launch method, Availability/retention strategy)
- Maven/config.jelly (Settings file, Global Settings file build-step config)
- GlobalFingerprintConfiguration/config.jelly (Fingerprint Storage Engine)
- BuildDiscarderProperty/config-details.jelly and
  SimpleGlobalBuildDiscarderStrategy/config.jelly (Discard old builds strategy,
  at both the per-job and global-default nesting levels)
- GlobalMavenConfig/config.groovy (default settings/global settings provider)
- ViewsTabBar/GlobalConfigurationImpl/config.groovy (Views Tab Bar)
- GlobalCrumbIssuerConfiguration/config.groovy (Crumb Issuer)

hudson/model/MyViewsProperty/config.jelly (Views Tab Bar on a user's own
account page) was deliberately left out: that page requires full
Jenkins.ADMINISTER and never sets readOnlyMode in its render chain, so it is
not an instance of this bug.

A further instance of this same gap exists on the "Manage Jenkins > Security"
page (Security Realm / Authorization Strategy / Markup Formatter selectors),
reachable with only Overall.SYSTEM_READ. That one is being reported through
the Jenkins Security Team's private disclosure process instead of here, since
it can expose an editable Security Realm/Authorization Strategy fragment to a
low-privilege viewer -- a permission-escalation-adjacent issue rather than a
plain read-only-UI gap.

Adds a regression test (SCMCheckoutStrategyReadOnlyModeTest) that registers a
throwaway SCMCheckoutStrategy with a real editable field, triggers the same
renderOnDemand() JS a browser fires when switching the dropdown, and asserts
the resulting fragment is rendered as the standard read-only N/A placeholder
rather than an editable input.

* Propagate readOnlyMode to GlobalSecurityConfiguration's dropdownDescriptorSelector calls

Applies the same fix as the previous commit to the last remaining
dropdownDescriptorSelector call sites in core: Security Realm, Authorization,
and Markup Formatter on hudson/security/GlobalSecurityConfiguration/index.groovy
("Manage Jenkins > Security", reachable with only Overall.SYSTEM_READ).

This was initially held back to verify it wasn't a privilege-escalation risk
before publishing: GlobalSecurityConfiguration#configure() unconditionally
calls j.checkPermission(Jenkins.ADMINISTER) as the first line, before any
submitted JSON is read, so a forged configSubmit POST from a SYSTEM_READ-only
user is rejected server-side (AccessDeniedException3) regardless of what the
UI rendered; the Save/Apply buttons are also only rendered inside
l.isAdmin(). The lazily-rendered fragment itself never carries live secrets
either, since dropdownDescriptorSelector renders non-selected options with
instance=null. Confirmed the same double gate (checkPermission(CONFIGURE) in
doConfigSubmit) exists for the other already-fixed call sites, so this is the
same severity class as the rest of the change: a read-only-mode UI/UX gap,
not a write-path vulnerability.

Adds a regression test (GlobalSecurityConfigurationReadOnlyModeTest) covering
this Groovy-view, SYSTEM_READ-scoped rendering path, following the same
pattern as SCMCheckoutStrategyReadOnlyModeTest: register a throwaway
AuthorizationStrategy with a real editable field, trigger the same
renderOnDemand() JS a browser fires when switching the dropdown, and assert
the fragment renders as the standard read-only N/A placeholder.

* Propagate readOnlyMode once in dropdownDescriptorSelector taglib, not per caller

Per jtnord's review on #27167: rather than requiring every caller of
f:dropdownDescriptorSelector to pass capture="readOnlyMode" (12 call
sites in core alone, plus any plugin using the same taglib), fix it
once in the taglib itself.

lib/form/dropdownDescriptorSelector.jelly already always captures
"descriptor" and "it" for the lazily rendered l:renderOnDemand
fragment regardless of what the caller's capture attribute lists.
readOnlyMode now joins that same always-captured set, so read-only
mode propagates into every lazily loaded descriptor fragment
ecosystem-wide without any caller changes.

This reverts the 12 per-callsite capture="readOnlyMode" additions
from the previous commits on this branch and updates the two
JenkinsRule/HtmlUnit regression tests' documentation to point at the
new, single fix location. Both tests still pass unchanged, since they
exercise the real page end-to-end rather than depending on any
caller's capture attribute.

* Add a taglib-level regression test for dropdownDescriptorSelector

The two existing regression tests on this branch (SCMCheckoutStrategy,
GlobalSecurityConfiguration) exercise real pages end-to-end through
JenkinsRule + MockAuthorizationStrategy, which only covers 2 of the
now-generic fix's many callers and requires standing up a full
permission model to prove a taglib-level behavior.

Following this project's existing convention for testing this exact
taglib family (lib/form/DropdownListTest, lib/layout/RenderOnDemandTest,
lib/form/RowVisibilityGroupTest, the latter of which already reuses a
single config.jelly across sibling Descriptor implementations), add a
lean unit test that exercises f:dropdownDescriptorSelector directly via
a synthetic RootAction, with no security realm involved. The fixture's
test1.jelly sets readOnlyMode directly and deliberately omits
capture="readOnlyMode", proving the taglib itself is responsible for
propagating it into the lazily-rendered fragment -- which by
construction covers every current and future caller, not just the two
pages exercised by the other tests.

* Empty commit to retrigger CI
2026-10-10 10:13:29 -06:00
2023-04-05 12:15:34 +02:00
2022-08-25 21:50:13 +01:00
2025-09-30 09:46:03 +02:00
2011-09-11 16:12:09 +02:00

Jenkins logo

Jenkins Regular Release Jenkins LTS Release Docker Pulls CII Best Practices Reproducible Builds Gitter


Table of Contents


About

In a nutshell, Jenkins is the leading open-source automation server. Built with Java, it provides over 2,000 plugins to support automating virtually anything, so that humans can spend their time doing things machines cannot.

What to Use Jenkins for and When to Use It

Use Jenkins to automate your development workflow, so you can focus on work that matters most. Jenkins is commonly used for:

  • Building projects
  • Running tests to detect bugs and other issues as soon as they are introduced
  • Static code analysis
  • Deployment

Execute repetitive tasks, save time, and optimize your development process with Jenkins.

Downloads

The Jenkins project provides official distributions as WAR files, Docker images, native packages and installers for platforms including several Linux distributions and Windows. See the Downloads page for references.

For all distributions Jenkins offers two release lines:

  • Weekly - Frequent releases which include all new features, improvements, and bug fixes.
  • Long-Term Support (LTS) - Older release line which gets periodically updated via bug fix backports.

Latest releases:

Jenkins Regular Release Jenkins LTS Release

Getting Started (Development)

For more information on setting up your development environment, contributing, and working with Jenkins internals, check the contributing guide and the Jenkins Developer Documentation.

Source

Our latest and greatest source of Jenkins can be found on GitHub. Fork us!

Contributing to Jenkins

New to open source or Jenkins? Here’s how to get started:

For more information about participating in the community and contributing to the Jenkins project, see this page.

Documentation for Jenkins core maintainers is in the maintainers guidelines.

News and Website

All information about Jenkins can be found on our official website, including documentation, blog posts, plugin listings, community updates, and more.

Stay up-to-date with the latest Jenkins news, tutorials, and release notes:

Follow Jenkins on social media to stay connected with the community:

Governance

The Jenkins project is governed by an open source community. To learn more about the governance structure, project leadership, and how decisions are made, visit the Governance Page.

Adopters

Jenkins is trusted by millions of users and adopted by thousands of companies around the world — from startups to enterprises — to automate their software delivery pipelines.

Explore the Adopters Page and https://stories.jenkins.io to see:

  • Companies and organizations using Jenkins
  • Success stories and case studies
  • How Jenkins is used in different industries

If your company uses Jenkins and you'd like to be featured, feel free to submit your story!

License

Jenkins is licensed under the MIT License.

Languages
Java 87.1%
HTML 6.5%
JavaScript 3.1%
SCSS 2.2%
Groovy 0.4%
Other 0.6%