Skip to content

GROOVY-12348: JmxBuilder: listen where the connector was asked to listen - #2870

Merged
paulk-asert merged 2 commits into
apache:masterfrom
paulk-asert:groovy12348
Sep 4, 2026
Merged

GROOVY-12348: JmxBuilder: listen where the connector was asked to listen#2870
paulk-asert merged 2 commits into
apache:masterfrom
paulk-asert:groovy12348

Conversation

@paulk-asert

Copy link
Copy Markdown
Contributor

connectorServer takes a host, defaulting to localhost, but it reached only the service URL. The authority before /jndi/ was left empty, which exports the RMI object on every interface, so host named the registry the stub was bound into and never restricted the listener. A connector asked for localhost was reachable from any host that could route to the port, and since the default MBean server is the platform one, that offered HotSpotDiagnostic.dumpHeap and the DiagnosticCommand operations to whoever arrived.

The connector now binds the host it was given. Both halves are needed: the server socket factory decides where the exported object listens, and the stub carries the client factory, which decides where a client dials. Binding without the second leaves clients dialling the host RMI advertises, where nothing is listening. A caller who supplied either factory keeps their own, so the SSL path is untouched, and a wildcard host still listens everywhere.

Starting a connector that both reaches other hosts and authenticates nobody now warns. A connector confined to loopback stays quiet, so the warning marks the case where a peer other than the operator can arrive.

The documentation recorded that its own example failed on Mac and CentOS 5 under Groovy 1.6 and wondered about /etc/hosts. The example fails because it does not create the RMI registry, which the corrected example below it already showed, so it now says that and describes what the connector exposes and to whom.

The model said Groovy is not deployed as a network service and listed such
a tool as a future condition, while `groovy -l` and JmxBuilder connector
servers already shipped. Both are development tools rather than services:
they run only where an operator started one, they bind loopback unless
given a wider address, and neither evaluates what a peer sends as code.
They belong with the shell and console tools in §9, so §2 carries them in
the interactive tools row rather than as an exception to the framing.

§7 gains the peer as an adversary and the closed capability list gains
connecting to such a listener. The two differ in what they offer: a line
reaches `groovy -l` as the `line` binding and a script that evaluates it
has opted into §3, whereas a connector server offers whatever its MBean
server holds, which for the platform server includes dumping the heap and
running diagnostic commands.

§9 records that neither authenticates or encrypts by default, and gives
connector servers their own false-friends row: every connector security
property was assembled and discarded between 2008 and 2026, so no
configuration produced a secured connector in that window and none can
have been relied upon.

§10 tells whoever widens a listener what they take on, and §12 says why a
loopback-bound development tool does not meet its condition and what would.
@codecov-commenter

codecov-commenter commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.05263% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.9642%. Comparing base (2ca5668) to head (7b40c25).
⚠️ Report is 21 commits behind head on master.

Files with missing lines Patch % Lines
...roovy/jmx/builder/JmxServerConnectorFactory.groovy 71.0526% 3 Missing and 8 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##               master      #2870        +/-   ##
==================================================
+ Coverage     70.9418%   70.9642%   +0.0224%     
- Complexity      37054      37190       +136     
==================================================
  Files            1576       1578         +2     
  Lines          134857     135226       +369     
  Branches        24973      25049        +76     
==================================================
+ Hits            95670      95962       +292     
- Misses          30530      30570        +40     
- Partials         8657       8694        +37     
Files with missing lines Coverage Δ
...roovy/jmx/builder/JmxServerConnectorFactory.groovy 64.1304% <71.0526%> (+4.8712%) ⬆️

... and 54 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

connectorServer takes a host, defaulting to localhost, but it reached only
the service URL. The authority before /jndi/ was left empty, which exports
the RMI object on every interface, so host named the registry the stub was
bound into and never restricted the listener. A connector asked for
localhost was reachable from any host that could route to the port, and
since the default MBean server is the platform one, that offered
HotSpotDiagnostic.dumpHeap and the DiagnosticCommand operations to
whoever arrived.

The connector now binds the host it was given. Both halves are needed:
the server socket factory decides where the exported object listens, and
the stub carries the client factory, which decides where a client dials.
Binding without the second leaves clients dialling the host RMI
advertises, where nothing is listening. A caller who supplied either
factory keeps their own, so the SSL path is untouched, and a wildcard
host still listens everywhere.

Starting a connector that both reaches other hosts and authenticates
nobody now warns. A connector confined to loopback stays quiet, so the
warning marks the case where a peer other than the operator can arrive.

The documentation recorded that its own example failed on Mac and CentOS 5
under Groovy 1.6 and wondered about /etc/hosts. The example fails because
it does not create the RMI registry, which the corrected example below it
already showed, so it now says that and describes what the connector
exposes and to whom.
@testlens-app

testlens-app Bot commented Sep 3, 2026

Copy link
Copy Markdown

🚨 TestLens detected 3 failed tests 🚨

Here is what you can do:

  1. Inspect the test failures carefully.
  2. If you are convinced that some of the tests are flaky, you can mute them below.
  3. Finally, trigger a rerun by checking the rerun checkbox.

Test Summary

Build and test / lts (17, windows-latest, 1) > :groovy-groovysh:test

Test Runs Flakiness
GroovyPosixCommandsTest > headAndGrepAndWcStripControlCharactersFromNames() 20% 🔴
GroovyPosixCommandsTest > lsStripsControlCharactersFromFileNames() 20% 🔴
GroovyPosixCommandsTest > lsStripsControlCharactersFromSymlinkTargets() 20% 🔴

🏷️ Commit: 7b40c25
▶️ Tests: 112748 executed
⚪️ Checks: 31/31 completed

Test Failures

GroovyPosixCommandsTest > headAndGrepAndWcStripControlCharactersFromNames() (:groovy-groovysh:test in Build and test / lts (17, windows-latest, 1))
java.nio.file.InvalidPathException: Illegal char <�> at index 2: ok�[2Ktrap.txt
	at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
	at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
	at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
	at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
	at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232)
	at java.base/java.nio.file.Path.resolve(Path.java:515)
	at java.base/jdk.internal.reflect.GeneratedMethodAccessor33.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at org.codehaus.groovy.reflection.CachedMethod.invokeReflective(CachedMethod.java:505)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:455)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:298)
	at org.codehaus.groovy.vmplugin.v8.IndyInterface.invokeColdReflective(IndyInterface.java:650)
	at org.apache.groovy.groovysh.jline.GroovyPosixCommandsTest.headAndGrepAndWcStripControlCharactersFromNames(GroovyPosixCommandsTest.groovy:123)
GroovyPosixCommandsTest > lsStripsControlCharactersFromFileNames() (:groovy-groovysh:test in Build and test / lts (17, windows-latest, 1))
java.nio.file.InvalidPathException: Illegal char <�> at index 2: ok�[2Ktrap.txt
	at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
	at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
	at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
	at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
	at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232)
	at java.base/java.nio.file.Path.resolve(Path.java:515)
	at java.base/jdk.internal.reflect.GeneratedMethodAccessor33.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at org.codehaus.groovy.reflection.CachedMethod.invokeReflective(CachedMethod.java:505)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:455)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:298)
	at org.codehaus.groovy.vmplugin.v8.IndyInterface.invokeColdReflective(IndyInterface.java:650)
	at org.apache.groovy.groovysh.jline.GroovyPosixCommandsTest.lsStripsControlCharactersFromFileNames(GroovyPosixCommandsTest.groovy:97)
GroovyPosixCommandsTest > lsStripsControlCharactersFromSymlinkTargets() (:groovy-groovysh:test in Build and test / lts (17, windows-latest, 1))
java.nio.file.InvalidPathException: Illegal char <�> at index 2: ok�[2Ktrap.txt
	at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
	at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
	at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
	at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
	at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232)
	at java.base/java.nio.file.Path.resolve(Path.java:515)
	at java.base/jdk.internal.reflect.GeneratedMethodAccessor33.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at org.codehaus.groovy.reflection.CachedMethod.invokeReflective(CachedMethod.java:505)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:455)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:298)
	at org.codehaus.groovy.vmplugin.v8.IndyInterface.invokeColdReflective(IndyInterface.java:650)
	at org.apache.groovy.groovysh.jline.GroovyPosixCommandsTest.lsStripsControlCharactersFromSymlinkTargets(GroovyPosixCommandsTest.groovy:108)

Rerun Controls

Select tests to mute in this pull request:

  • GroovyPosixCommandsTest > headAndGrepAndWcStripControlCharactersFromNames()
  • GroovyPosixCommandsTest > lsStripsControlCharactersFromFileNames()
  • GroovyPosixCommandsTest > lsStripsControlCharactersFromSymlinkTargets()

Reuse successful test results:

  • ♻️ Only rerun the tests that failed or were muted before

Click the checkbox to trigger a rerun:

  • Rerun jobs

Learn more about TestLens at testlens.app/docs.

@paulk-asert
paulk-asert merged commit 9bd1773 into apache:master Sep 4, 2026
31 of 32 checks passed
@paulk-asert
paulk-asert deleted the groovy12348 branch September 4, 2026 01:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants