This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/docs by this push:
     new 6e36c7d6c1 READY-395/384: Document actuator off-by-default policy and 
MCP DCR secure-only registration
6e36c7d6c1 is described below

commit 6e36c7d6c1f44ac86b9476d4e561602675ae3583
Author: James Bognar <[email protected]>
AuthorDate: Sun Aug 16 15:33:58 2026 -0400

    READY-395/384: Document actuator off-by-default policy and MCP DCR 
secure-only registration
---
 pages/release-notes/10.0.0.md           | 13 ++++++++++++-
 pages/topics/16.11.ManagementSurface.md | 11 ++++++++++-
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index b830be7c8a..5de5b76fe7 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -364,6 +364,8 @@ New endpoints:
 
 Exposure is **on-by-default-with-gating**: non-sensitive reads are exposed; 
mutating/sensitive operations (`/loggers` set-level, the dumps) are 
deny-by-default behind explicit opt-in settings beans (`LoggersSettings`, 
`DumpsSettings`). No auth provider is auto-wired — the consumer supplies their 
own guard.
 
+**`BasicActuatorGroup` mounts only `/healthz`/`/readyz`/`/livez` and the dumps 
by default; `/info` and `/loggers` are off.** The convenience group composes 
`HealthMixin` + `DumpsMixin` only — `InfoMixin` and `LoggersMixin` are 
deliberately left out, since an unauthenticated manifest dump (`/info`) and 
logger-topology disclosure (`/loggers` read) are both meaningful information 
leaks with no guard auto-wired. Re-enable either (or both) with an a-la-carte 
subclass adding `@Rest(mixins={Inf [...]
+
 See the new [Management Surface](/docs/topics/ManagementSurface) topic page 
for the endpoint catalog, the `BasicActuatorGroup` one-liner, the exposure 
policy, and the manifest-stamping recipe.
 
 ### `/loggers` non-JUL backends (Logback, Log4j2)
@@ -1166,7 +1168,7 @@ See 
[juneau-rest-server-mcp](/docs/topics/JuneauRestServerMcp#replay-protection-
 
 **F3 — dynamic client registration + authorization hardening.** The third 
slice completes the client story with RFC 7591 / OIDC Dynamic Client 
Registration, issuer-keyed credential persistence (SEP-2352), and scoped 
step-up authorization (SEP-2350, both halves), all in 
`juneau-rest-client-mcp-auth` except the server step-up gate:
 
-- **Dynamic Client Registration (SEP-837 / RFC 7591 / OIDC).** 
`McpDynamicClientRegistrar` POSTs client metadata to an AS 
`registration_endpoint` and returns an immutable, secret-redacting 
`McpClientRegistration`. `McpApplicationType` is a Juneau-owned `NATIVE`/`WEB` 
enum (native is the SEP-837 SHOULD for CLI/desktop/`localhost` clients) so the 
public API does not leak the Nimbus `provided` type. Loopback redirects are 
built with `LoopbackRedirectUris`: `portAgnostic(path)` is the RFC 82 [...]
+- **Dynamic Client Registration (SEP-837 / RFC 7591 / OIDC).** 
`McpDynamicClientRegistrar` POSTs client metadata to an AS 
`registration_endpoint` and returns an immutable, secret-redacting 
`McpClientRegistration`. `McpApplicationType` is a Juneau-owned `NATIVE`/`WEB` 
enum (native is the SEP-837 SHOULD for CLI/desktop/`localhost` clients) so the 
public API does not leak the Nimbus `provided` type. Loopback redirects are 
built with `LoopbackRedirectUris`: `portAgnostic(path)` is the RFC 82 [...]
 - **Issuer-keyed credential binding (SEP-2352).** Persisted credentials 
**MUST** be keyed by the AS `issuer` and never reused across authorization 
servers. `McpClientRegistrationStore` is the persistence SPI; 
`InMemoryMcpClientRegistrationStore` is the thread-safe, secret-redacting 
default. `McpClientRegistrationManager` orchestrates mechanism selection, 
issuer-keying, and migration: on-demand (no store), store-hit reuse, or 
re-registration when discovery indicates a different issuer — s [...]
 - **Scoped step-up authorization (SEP-2350, both halves).** Server side, 
`McpResourceServerConfig.addOperationScope(operation, scopes…)` declares 
per-operation required scopes; the RS answers an under-scoped call with `403 
insufficient_scope` + a `WWW-Authenticate` `scope=` hint, and the baseline 
`401` now also carries the `scope` hint when a baseline required-scope set is 
configured. Both the baseline and per-operation gates are **hierarchy-aware** 
(a broader granted scope satisfies a n [...]
 
@@ -1239,6 +1241,15 @@ See [OIDC Relying Party 
Login](/docs/topics/OidcRelyingParty#login-state-store-c
 
   A related set of ReDoS-hardening fixes (bounded/escaped regex handling in 
`HttpPartSchema`, `LogEntryFormatter`, and the request-routing 
`UrlPathMatcher`) landed in the same sweep. **Migration:** none for normal 
usage; an application that displayed unauthorized-request detail to end users, 
or that parsed XML relying on DTD processing on the non-validating path, will 
see the new generic/hardened behavior.
 
+- **Security hardening — parser and transport boundary sweep.** A follow-on 
hardening pass tightened validation at several parser/transport boundaries:
+  - **`MultipartBody`** (`juneau-rest-common`) now rejects CR/LF and other 
control characters in a part's `name`/`filename`/`contentType` (enforced both 
at `MultipartPart` construction and defensively at write time), closing a 
header-injection vector into the multipart wire format; `Content-Disposition` 
quoted-string values are also now backslash-escaped.
+  - **`BsonInputStream`** (`juneau-marshall`) now enforces each declared 
document/array length as a hard upper bound on every nested read (cstrings 
included), rejecting a forged-short length that previously could be bypassed by 
traversal relying solely on a `0x00` terminator.
+  - **`ProtobufReader`** (`juneau-marshall`) caps varint/tag decoding at 10 
bytes (the maximum a 64-bit LEB128 varint can occupy) and validates a 
wire-declared `LEN` field's length against the configured maximum before 
skipping an unknown field, closing an unbounded-CPU decode loop and a 
length-cap bypass, respectively.
+  - **`SamlAssertionValidator`** / `SamlAuthFilter` 
(`juneau-rest-server-auth-saml`) now bind a bearer `SubjectConfirmationData`'s 
`Recipient` to the request's actual ACS URL, rejecting an assertion issued for 
a different endpoint.
+  - **`OidcDiscoveryClient.Builder`** (`juneau-rest-auth-oauth-flow`) now 
requires the configured issuer to be `https` (loopback exempt), rejecting a 
plaintext discovery endpoint at build time.
+
+  **Migration:** none for normal usage; each of these only rejects 
previously-out-of-spec or previously-exploitable input.
+
 - **Present-but-empty `RestContext.*` boolean settings no longer throw 
(leniency improvement).** Landed alongside the new `RestContextProperties` 
`@ConfigProperties` bean (see New Features above): previously, a 
present-but-empty value for a boolean `RestContext.*` setting (e.g. 
`RestContext.eagerInit=`) threw `BeanCreationException` at injection time, 
because the old `@Value boolean` field's strict conversion had no tolerance for 
an empty string. As of 10.0.0 this is resolved leniently t [...]
 
 - **SVL variables in a `RestContext.*` boolean setting now resolve through the 
resource's own var resolver (capability widening).** Landed alongside the same 
`RestContextProperties` change: a `$C{...}` / `$R{...}` / `$S{...}`-style 
variable embedded in a boolean `RestContext.*` value (e.g. 
`RestContext.virtualThreads=$C{MyConfig/virtualThreads}`) is now resolved 
through the owning resource's `VarResolver` rather than `VarResolver.DEFAULT`, 
so resource-scoped variables like `$C{...}` (con [...]
diff --git a/pages/topics/16.11.ManagementSurface.md 
b/pages/topics/16.11.ManagementSurface.md
index 58c8954267..d380a113e7 100644
--- a/pages/topics/16.11.ManagementSurface.md
+++ b/pages/topics/16.11.ManagementSurface.md
@@ -32,12 +32,21 @@ import org.apache.juneau.rest.server.*;
 public class RootResources extends BasicRestServletGroup { /* ... */ }
 ```
 
-`BasicActuatorGroup` composes `InfoMixin`, `LoggersMixin`, `HealthMixin`, and 
`DumpsMixin` under a single prefix. The prefix defaults to `/actuator` and is 
configurable via the `juneau.actuator.path` system property (resolved through 
the standard `$S{...}` SVL var):
+`BasicActuatorGroup` composes `HealthMixin` and `DumpsMixin` under a single 
prefix. The prefix defaults to `/actuator` and is configurable via the 
`juneau.actuator.path` system property (resolved through the standard `$S{...}` 
SVL var):
 
 ```bash
 java -Djuneau.actuator.path=/manage -jar myapp.jar
 ```
 
+> **`/info` and `/loggers` are off by default** — unlike health, they are not 
mounted on the bare group, since `InfoMixin` discloses the full manifest and 
`LoggersMixin`'s read side discloses logger topology, neither behind any auth. 
Re-enable either (or both) a-la-carte on a subclass:
+>
+> ```java
+> @Rest(mixins={InfoMixin.class, LoggersMixin.class})
+> public class MyActuatorGroup extends BasicActuatorGroup { /* ... */ }
+> ```
+>
+> Mixins declared on a subclass are additive to the ones inherited from 
`BasicActuatorGroup`, so `HealthMixin`/`DumpsMixin` stay mounted too. With no 
such subclass, `/info` and `/loggers` return `404` under the group's prefix.
+
 > **`/metrics` is not assembled into the group** — it lives in the 
 > `juneau-rest-server-metrics-micrometer` module (which `juneau-microservice` 
 > does not depend on). Add `MetricsMixin` a-la-carte to your host resource 
 > when that module is on the classpath.
 
 Composition is convenience, not the only way in — every endpoint remains 
independently mountable a-la-carte via its standalone `*Mixin`/`*Resource` 
flavor.

Reply via email to