Skip to content

fix(deps): update dependency org.mock-server:mockserver-client-java to v9.1.0 - #1282

Merged
LikeTheSalad merged 1 commit into
mainfrom
renovate/org.mock-server-mockserver-client-java-9.x
Oct 21, 2026
Merged

LikeTheSalad merged 1 commit into
mainfrom
renovate/org.mock-server-mockserver-client-java-9.x

Conversation

@elastic-renovate-prod

@elastic-renovate-prod elastic-renovate-prod Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
org.mock-server:mockserver-client-java (source) 9.0.0 → 9.1.0 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


Release Notes

mock-server/mockserver-monorepo (org.mock-server:mockserver-client-java)

v9.1.0

Security
  • Control-plane mTLS could be bypassed by sending the CA certificate after an untrusted client certificate. With controlPlaneTLSMutualAuthenticationRequired on, MockServer 5.13.0 to 9.0.0 accepted a control-plane request if any certificate the client sent could be validated against controlPlaneTLSMutualAuthenticationCAChain. A CA certificate is public, so anyone who could reach the control plane could send their own certificate followed by your CA certificate and create, read or delete expectations, change the configuration or reset the server, without the CA's private key. Also requiring data-plane mTLS (tlsMutualAuthenticationRequired) did not prevent this in the default set-up: the data-plane check also trusts MockServer's own CA, which by default is the CA bundled with MockServer, and its private key is published in the jar, so an attacker could sign their certificate with it. Data-plane mTLS prevented it only if MockServer had its own CA (certificateAuthorityCertificate and certificateAuthorityPrivateKey, or dynamicallyCreateCertificateAuthorityCertificate) and every CA in tlsMutualAuthenticationCertificateChain was private. MockServer now checks only the client's own certificate (the one whose private key it used for the connection): it must be signed by a CA in the chain, directly or through intermediate CA certificates the client sends after it, be in date, allow digital signatures if it lists key usages, allow client authentication if it lists extended key usages, and not be a CA certificate, a self-signed certificate or one of the certificates in the chain. A self-signed client certificate listed in controlPlaneTLSMutualAuthenticationCAChain is no longer accepted; sign client certificates with a CA instead. A controlPlaneTLSMutualAuthenticationCAChain that contains the bundled CA (or any certificate for its key) is now refused: MockServer does not start, PUT /mockserver/configuration answers 400, and any other change makes every control-plane request fail, where before only a warning was logged. If MockServerClient and MockServer share that property in one JVM (for example ClientAndServer or the JUnit rule) and you added the bundled CA so the client trusts MockServer's certificate, give MockServer its own CA with certificateAuthorityCertificate and certificateAuthorityPrivateKey and put that CA in the chain instead. The control-plane audit log now records the validated client certificate's subject as a verified principal (verified-mtls) unless OIDC supplied one; with mTLS and JWT both on, the audit principal is now the certificate subject instead of the unverified JWT sub. If a MockServer reachable by others had control-plane mTLS on, with or without data-plane mTLS, treat its expectations, recorded traffic and settings as possibly read or changed by someone else
  • mTLS (tlsMutualAuthenticationRequired) no longer accepts client certificates anyone can create (BREAKING for mTLS set-ups that use MockServer's default CA; see upgrading to 9). Up to 9.0.0, MockServer trusted client certificates signed by MockServer's own CA whenever mTLS was on, even with tlsMutualAuthenticationCertificateChain set. By default that CA is the one bundled with MockServer, and its private key is published in the MockServer jar, so anyone could create a client certificate, with any name, that MockServer accepted. That client also matched any client certificate condition in your expectations and, when control-plane authentication was off, could create, read or delete expectations. MockServer now never trusts the bundled CA for mTLS. If mTLS is on and nothing but the bundled CA would be trusted, or tlsMutualAuthenticationCertificateChain contains the bundled CA, MockServer does not start, PUT /mockserver/configuration answers 400, and the message names the fix: give MockServer its own CA with certificateAuthorityCertificate and certificateAuthorityPrivateKey, set dynamicallyCreateCertificateAuthorityCertificate=true, or set tlsMutualAuthenticationCertificateChain to the CA that signs your client certificates. With a chain set and the default CA, MockServer now trusts only the chain. For a throwaway local test, the new tlsMutualAuthenticationAllowBundledCa=true restores the old behaviour, and a warning is logged whenever the bundled CA becomes trusted (at startup, when a configuration change makes it trusted, and when the TLS context is rebuilt). This applies to HTTPS and HTTP/3. If a MockServer reachable by others relied on mTLS with the default CA, treat its expectations and recorded traffic as possibly read or changed by someone else
  • Dashboard: a crafted dashboard link can no longer make the dashboard reset, clear or stop the MockServer that serves it. The dashboard reads ?host=, ?port= and ?basePath= from its own address and used them unchecked to build every call it makes to MockServer, so a link such as …/mockserver/dashboard?basePath=/mockserver/reset%23 turned the dashboard's next routine call into /mockserver/reset as soon as someone opened it. These values now go through the same checks as a server typed into Set MockServer: a host must be a plain host name or IP address (no scheme, path, @ or #), a port a number from 1 to 65535, and a base path a plain path (no ?, #, %, \, // or ./.. segments). An invalid value is ignored, the dashboard uses the server that served it instead, and a warning at the top of the dashboard names what was ignored. A valid link that points the dashboard at a server on a different host now shows a warning naming that server, because what you create in the dashboard is sent there, with a button to switch back to the server that served the page; that server no longer decides whether dashboard analytics are on (the server that served the page still does). Valid links on the same host, such as ?port=1080 or ?basePath=/mock, work as before with no warning. A dashboard served behind a proxy under a path containing a percent-encoded character (for example a space) now falls back to the root path, with the same warning; pass ?basePath= to set it. The stricter base-path check also applies to Set MockServer, and a saved workspace target whose base path contains % or \ is dropped, so that workspace follows the dashboard's address again
  • Load scenarios: a STAIRS load shape with a huge steps value (for example 2147483647) could exhaust the server's memory when it was loaded with PUT /mockserver/loadScenario, before the stage limit was checked. A shape is now checked against the stage limit (loadGenerationMaxStages, 20 by default) before it is expanded, and rejected with 400 Bad Request if it is too big; no shape can expand to more than 10,000 stages. Stage durations so large that their total wrapped past the maximum run duration are now rejected too, and so is NaN or Infinity in any number in a load scenario (stage rates, shape parameters, step weights, the pacing value and thresholds); before, a NaN step weight made a weighted scenario fail once it ran. A VU shape value too big for a whole number of virtual users is now rejected by the virtual-user limit instead of silently wrapping to a small or negative count
  • Node, Python, Go, Rust and .NET clients: the callback and breakpoint WebSocket now carries the client's configured control-plane bearer token as Authorization: Bearer <token>, as control-plane HTTP calls already did, so callbacks and breakpoints keep working when MockServer requires JWT or OIDC control-plane authentication on that WebSocket. A token supplier is asked for a fresh token on each connection, including the Node and Python clients' reconnects. With no token configured nothing is sent, and a MockServer that does not require authentication ignores the header. In a browser the Node client cannot send it, because browsers do not let a page set headers on a WebSocket and MockServer accepts the token only in that header; use mutual TLS for browser callbacks and breakpoints when control-plane authentication is on. The Ruby client has no control-plane token option and the PHP client has no callback WebSocket, so neither changes
  • Log lines can no longer be forged through request data. The forward circuit breaker's log messages (which name the upstream, which can come from a request's Host header or HTTP/2 :authority) and the LLM conversation matcher's debug messages (which quote the request body) now write carriage returns, line feeds and other control characters as escapes such as \r and \n, so a crafted request cannot start a new log line
  • By default, web pages on other sites can no longer use MockServer's API or WebSockets from your browser (BREAKING; see upgrading to 9). Since 7.0.0, MockServer's own API (every /mockserver/... path, including MCP and metrics), the dashboard's live log and the callback WebSocket answered any web page, so a site you visited while MockServer was running could read recorded traffic, add or change expectations, and reset or stop the server. A new property, controlPlaneCorsAllowOrigin, now decides which browser origins may use them. Left blank (the default), it allows pages on localhost, 127.0.0.1 or [::1] (http or https, any port) and pages MockServer serves itself, such as the dashboard, when MockServer is reached by a name DNS rebinding cannot take over (see the next entry); set it to a comma-separated list of origins (or *) to allow others. It can only be set at startup: PUT /mockserver/configuration ignores it, with a warning, so a request to the control plane cannot widen it. Any request the control plane serves (any /mockserver/... path including MCP and metrics, a legacy path such as /reset or /expectation with a method the control plane serves there, the liveness path, and the /_mockserver_ui_websocket and /_mockserver_callback_websocket upgrades) that carries an Origin header from any other page, including Origin: null (a sandboxed iframe or a file:// page), is refused with 403 before it is handled and before any expectation can answer it, whatever method it uses and whether or not the browser sent a preflight first. Preflights for those requests are answered by MockServer without Access-Control-Allow-* headers. corsAllowOrigin no longer affects MockServer's own API: it, and enableCORSForAllResponses, still apply to mocked and proxied responses as before, with four exceptions. A preflight for a request the control plane serves is answered by MockServer under controlPlaneCorsAllowOrigin, not by an expectation (including a respondBeforeBody one) or corsAllowOrigin; a respondBeforeBody expectation no longer answers a request the control plane serves; a browser request from a page controlPlaneCorsAllowOrigin does not allow is refused with 403 even where a mock, not the control plane, would have answered it, for these requests: GET or DELETE on /loadScenario/start or /loadScenario/stop; PUT /pact; GET or DELETE on any deeper path under /loadScenario/<name>/ other than GET /loadScenario/<name>/report; GET, PUT or DELETE under /chaosExperiment/profiles/<name>/; POST under /chaosExperiment/apply/<name>/; and any method on a /mockserver or /_mockserver_ path that is not a route; and an unmatched preflight for another method on a legacy path (for example POST /graphql to a mocked GraphQL API) allows only the requested method. Clients that are not browsers are unaffected; the Java client no longer sends an Origin header on its WebSockets. Action needed only if a browser page on another host calls MockServer's API, the dashboard targets a MockServer on another host, a reverse proxy in front of the dashboard rewrites the Host header, or you set corsAllowOrigin so a page could call the API: set controlPlaneCorsAllowOrigin on that MockServer to the page's origin, for example -Dmockserver.controlPlaneCorsAllowOrigin=https://app.example.com. This does not stop a site visited by a browser that uses MockServer as its proxy, because the page is then same-origin with MockServer; turn on control-plane authentication if untrusted pages may run in a browser that can reach MockServer
  • A DNS-rebinding page can no longer use MockServer's API or WebSockets by default (BREAKING for a dashboard opened at a public-looking name; see upgrading to 9). A malicious site can point its own host name at MockServer, so its page becomes same-origin with MockServer and passed the "pages MockServer serves itself" rule. That rule now applies only when MockServer is reached by localhost, an IP address, a single-label name (such as a Docker or Compose service name like mockserver, or a Kubernetes short service name), a name ending in .svc, .svc.cluster.local or .internal (the top-level domain reserved for private use, which covers host.docker.internal and *.ec2.internal), or a name ending in a suffix listed in the new controlPlaneTrustedHostSuffixes property (for clusters with a custom domain, for example corp.example). This applies even when controlPlaneCorsAllowOrigin is set: listing some origins never restores same-host trust for other names. The trusted-name check ignores case and one trailing dot, and the page's origin must still match the Host exactly, port included; look-alikes such as localhost.evil.com, svc.evil.com or internal.evil.com, and non-ASCII names, do not count. A page on any other name, for example http://evil.example.com:1080 sent with Host: evil.example.com:1080, now gets 403 on MockServer's API and WebSockets. Action needed only if you open the dashboard, or a page MockServer serves, at a multi-label name such as https://mockserver.example.com: list that origin in controlPlaneCorsAllowOrigin, or add a private suffix to controlPlaneTrustedHostSuffixes. Either opts that name back in, including to a rebinding attack on it. Like controlPlaneCorsAllowOrigin, controlPlaneTrustedHostSuffixes can only be set at startup; corp.example, .corp.example and *.corp.example mean the same, a public suffix such as com, co.uk or github.io, under which anyone can register a name, is rejected with an error at startup and trusts nothing, and an entry it cannot use is logged as a warning. This stops rebinding by an ordinary web site; someone who controls how the victim's machine resolves names (a hostile Wi-Fi resolver, LLMNR or mDNS spoofing on the local network, a DNS search domain, or the cluster DNS) can still rebind any trusted name except an IP address or localhost, so turn on control-plane authentication if that is in your threat model. A request whose Host headers disagree (for example an HTTP/2 :authority and a different host header) is never treated as same-host
  • The callback WebSocket now requires control-plane authentication when it is turned on, as the dashboard's WebSocket already did. The Java client now sends its control-plane JWT (or its request override's Authorization header) on the callback and breakpoint WebSockets, and the other clients send their bearer token (see above). With mTLS control-plane authentication the WebSocket now needs the client certificate too: the Java and Rust clients present it, and the Node, Python, Go and .NET clients now do too (see below). Upgrade the clients with the server: older ones send no token or certificate on the WebSocket, so with control-plane authentication on their callbacks and breakpoints are refused. The dashboard, like the Node client in a browser, needs mTLS for breakpoints when control-plane authentication is on
  • Node, Python, Go and .NET clients: the callback and breakpoint WebSocket now presents the client's configured mTLS client certificate and trusts its configured CA certificate, as control-plane HTTP calls already did, so callbacks and breakpoints keep working when MockServer requires mTLS control-plane authentication on that WebSocket. Before, the WebSocket presented no client certificate, and the Go and .NET clients also ignored a configured CA certificate on it. The Go client uses the TLS settings of an http.Client passed with WithHTTPClient; the .NET client applies its TLS settings only when they were set through MockServerClient.Builder(...).WithTls(...), not when you pass your own HttpClient. The Rust client already presents its client_cert_pem certificate on its secure callback WebSocket; the Ruby client has no client certificate option and the PHP client has no callback WebSocket, so neither changes
  • A callback WebSocket that registers with a client id (X-CLIENT-REGISTRATION-ID) already in use no longer silently takes over that client's object callbacks and breakpoints. With control-plane authentication on, the same caller takes over at once: the same JWT issuer and subject, the same OIDC principal, or the same mTLS client certificate (compared by its SHA-256 fingerprint, so a renewed certificate counts as another caller). Otherwise, MockServer pings the registered connection and refuses the new one if it answers within 2 seconds, with 403 Forbidden when both are authenticated as different callers and 409 Conflict otherwise; if it does not answer, or has closed, the new connection takes over and the old one is closed, so a client still reconnects after its connection drops without MockServer noticing. A client answers only while it is reading its WebSocket, so a live client that spends more than 2 seconds in a callback or breakpoint handler does not answer, and can be taken over by another connection: by anyone with authentication off, or by any authenticated caller with it on. A client whose credential changed, such as a renewed certificate, can therefore still replace its own dropped connection. Only one connection at a time can take a client id over; another trying at the same moment gets 409. The Java client now flushes its pong at once, so a Java connection that is not inside a long callback answers the check
Added
  • A capture-and-replay example for a remote MCP server, in every client language (Java, Node, Python, Ruby, Go, .NET, Rust, PHP, curl, with shared JSON under examples/json/parallel_search_mcp): MockServer records an MCP client's calls to the live Parallel Search MCP server, then replays them offline from expectations that match on the JSON-RPC method and echo the request id
  • Rust client: an HttpResponse can now carry any response body the server accepts, not only a string. New builders binary_body(bytes, content_type) (a BINARY body, base64-encoded on the wire and served back byte for byte), json_body(..), file_body(..) and body_value(Body) sit beside body(..), and typed_body() reads any body back as a Body (for a retrieved expectation, in the shape the server returned). HttpRequest::binary_data(bytes) builds a binary (non-HTTP) request matcher for use with respond_with_binary, and binary_data_bytes() reads it back. Body::with_content_type(..) now sets the content type on JSON, BINARY, STRING and XML bodies as well as FILE bodies, and wraps an inline JSON object (one with no type, or a type that is not a MockServer body type, such as GeoJSON's FeatureCollection) as a typed JSON body so the content type is not added to the JSON payload; other body types are left unchanged. HttpResponse.body keeps its Option<String> type and a string body is unchanged on the wire; other body shapes are kept in HttpResponse.extra["body"]
  • Dashboard: each workspace can target its own MockServer. The Set MockServer button on a workspace tab takes a host, port, https and base path, checks the server answers the dashboard (and explains why not: unreachable, CORS refused, control-plane authentication, a wrong base path, or an http server from an https dashboard), and every tab then shows the server it targets. Every view, action and live update in a workspace goes to its server; switching to a workspace on another server clears what was shown from the previous one. Breakpoints set on a server stay active while any workspace targets it, and are removed when the last workspace targeting it is closed or pointed elsewhere
  • Dashboard: the Verify view's response matcher has a Status range (a class such as 4XX, or one comparison such as >= 400), and its quick scope now accepts status:, for example status:>=500 or status:>=400 status:<500 (filled in as 4XX). A range that needs two comparisons, such as status:>=400 status:<450, is refused rather than widened
  • Rule 8 in the always-on check-false-green-guards.sh CI gate fails the build when a test asserts an HTTP status loosely, for example not(is(401)), anyOf(is(200), is(404)), status < 300, .not.toBe(404) or status in (200, 404), because such an assertion also passes on a 500. It covers Java, Kotlin, JavaScript/TypeScript, Python and Go test sources; a genuinely tolerant assertion carries a status-tolerance-ok: <reason> comment. The existing tolerant assertions were pinned to their exact status. See docs/operations/false-green-guards.md
  • Security scanning: a new zizmor GitHub Actions workflow audits .github/ (workflows, composite action and dependabot.yml) and reports its findings as code scanning alerts under the category zizmor, and CodeQL now also scans C#, Go, Rust and the GitHub Actions workflows, with the security-extended query suite for every language. See docs/operations/security.md
  • Security scanning: a new agent-config-scan GitHub Actions workflow checks the AI agent configuration (.opencode/, .claude/, AGENTS.md, CLAUDE.md, opencode.json(c), .mcp.json, SKILL.md and similar files, at any depth) with deterministic rules for hidden or bidirectional Unicode, permission drift against a committed baseline (including settings env), hooks, plugins and marketplaces not on an allowlist, unpinned or unlisted MCP servers, credential patterns, symbolic links, imported files and CODEOWNERS coverage. It is closed-world and fails closed: files under an AI-tool configuration root that no check claims, configuration keys no check handles, case variants of known names, YAML frontmatter outside a small subset, JSON that fails strict parsing, imports it cannot follow and launchers it does not recognise are all findings. Findings are code scanning alerts under the category agent-config and fail the job. The scanner is a standard-library Python script with a committed policy file, both CODEOWNED. See docs/operations/security.md
  • Security scanning: the agent-config scan now also checks VS Code workspace files (*.code-workspace) and dev container configuration (.devcontainer/devcontainer.json, .devcontainer/**/devcontainer.json and .devcontainer.json, at any depth). A workspace's settings, and a dev container's customizations.vscode.settings, get the same closed-world checks as .vscode/settings.json, including MCP servers and auto-approve settings. A workspace folder must be a directory of files in the repository. Dev container lifecycle commands such as postCreateCommand and initializeCommand must be on their own allowlist and use a recognised launcher. The container image must be pinned by @sha256: digest or allowlisted. Any other key that is not listed as inert, such as features, runArgs, mounts, containerEnv, tasks or launch, is a finding. See docs/operations/security.md
Changed
  • MockServer is not published to Chocolatey, SDKMAN!, winget, Scoop, asdf/mise or a mock-server Homebrew tap; install the CLI with brew install mockserver (from homebrew-core) on macOS or Linux, or from the windows-x86_64.zip on the GitHub Release on Windows; Docker and the executable JAR work everywhere
  • Java client: chaining withBeforeAction(...) or withAfterAction(...) now adds each action to the expectation, so .withAfterAction(a).withAfterAction(b) runs both a and b. Before, each call replaced the list and only the last action ran. withBeforeActions(...) and withAfterActions(...) still replace the whole list. The same singular methods are now on Expectation too
  • ClassGraph upgraded from 4.8.198 to 5.0.0. If you use the regular (not -no-dependencies) artifacts, three new transitive jars arrive with it (classgraph-base, classgraph-vfs, classgraph-classpath), and a project that pins classgraph to 4.x must stop doing so, because 5.x is not binary-compatible; for the same reason, another library in your build that uses the 4.x API can break if Maven resolves it to 5.0.0, so use the -no-dependencies artifacts there
  • Dashboard: the generated Rust code for a response with a FILE, BINARY, typed JSON or other object body now sets it with .body_value(Body::object(..)), and a JSON array or scalar body with .json_body(..), instead of inserting it into response.extra
  • At the INFO log level (the default) MockServer now keeps more log entries waiting to be recorded before it starts dropping them. The cap on entries still waiting to be logged at INFO is now a seventh of the heap ceiling, as it already was at WARN, instead of a twelfth; DEBUG and TRACE keep a twelfth. Under heavy load with large bodies fewer log events are dropped, so fewer upper-bound verifications fail because evidence was dropped. On the JSON and proxy traffic we measured, the whole event log should still stay under about a fifth of the heap
  • At the INFO log level (the default) MockServer now keeps about 40% fewer past log entries by default: the event-log size budget (maxEventLogSizeInBytes) is a twentieth of the heap ceiling, as it already was at WARN, instead of a twelfth. When a server is close to the most traffic it can log, this means the garbage collector does less work and the slowest responses are faster; with G1 the 99th-percentile response time was up to about a third lower in our tests. verify(), retrieve and the dashboard see fewer of the oldest requests, and an upper-bound verification fails sooner once they are evicted. To keep the previous amount of history, set maxEventLogSizeInBytes to a twelfth of your heap. DEBUG and TRACE are unchanged
  • Logging a message that quotes a request, response or expectation uses less CPU, at every log level: the quoted text is now indented line by line with a simple loop instead of a regular expression. In a micro-benchmark this renders a typical message 25–37% faster and allocates 35–46% less; the logged text is unchanged, byte for byte. Whether it raises the request rate at which a busy server logging at INFO starts dropping log events has not been measured yet
  • Logging at INFO (or more verbose) uses less CPU when nothing prints the log, for example with disableSystemOut set and no other log handler configured, or when no SLF4J logging provider is on the classpath. MockServer no longer builds the text of each log message just to throw it away; retrieving the logs, the dashboard and verification failure messages still show exactly the same text, built when they ask for it. When the log is printed, a message that quotes a request, response or expectation is now built in one pass instead of first building each quoted part separately: in a micro-benchmark that is 5–11% faster and allocates 21–40% less, and the printed text is unchanged, byte for byte. Whether this raises the request rate at which a busy server logging at INFO starts dropping log events has not been measured yet
Fixed
  • The /mockserver/metrics handler no longer answers 500 to a request that carries no keep-alive flag, such as one built in code and passed to the handler directly; it now treats a missing flag as "close" and sets the 200 status explicitly. Requests decoded from the wire always carry the flag, so a server scraped over HTTP was not affected
  • Dashboard: with the dashboard open in two browser tabs, a reload no longer gives one workspace another workspace's view and search terms; each tab now keeps the others' workspace changes instead of overwriting them
  • MCP and A2A mocks built with the Java, Node, Python, Ruby, Go, PHP, .NET or Rust client builders now return text containing a backslash before $ or # exactly as written; previously a\$b was returned as a$b and a\#b as a#b
  • Java, Node and Python clients: importing a WireMock, Mountebank or Mockoon document (importDocument / import_document), including one whose format is auto-detected, now returns the imported expectations. The server had already added them, but its reply also carries warnings, which the clients could not read: Java threw IllegalArgumentException, Node resolved the whole reply object instead of an array, and Python returned an empty list. Each client now returns the expectations and logs the warnings (Java at WARN, Node with console.warn, Python with logging at WARNING). A reply object without an expectations list (for example an error from a gateway) is now an error rather than an empty result. These methods also now refuse format=recording before sending anything. Before, the server would load the recorded request/response pairs into its request log and the client returned them as if they were added expectations; to re-import recorded traffic, send PUT /mockserver/import?format=recording directly. The Ruby, Go, .NET, Rust and PHP clients only import HAR and Postman documents, whose reply is a plain list, so they were not affected
  • Java, Python, Ruby and Go clients: starting a chaos experiment no longer reports a 403 as "chaos is disabled". No server setting disables chaos experiments; a 403 means control-plane authorization rejected the request, and the error now says so. In Go, StartChaosExperiment and SetServiceChaos no longer return FeatureDisabledError for a 403. An invalid experiment is still rejected with 400
  • Drift alert webhook, LLM semantic drift analysis and the p95 performance drift threshold no longer carry over from a stopped MockServer to the next one started in the same JVM (for example one ClientAndServer or JUnit rule per test). Before, a server started with driftAlertWebhookEnabled or driftSemanticAnalysisEnabled left them switched on after it stopped, so later servers kept posting its webhook and calling its LLM even with both flags off. These three settings are shared by the whole JVM: the most recently started server that turns any of them on decides all three, a server that turns none on leaves them unchanged, and when the deciding server stops they revert to the previous such server still running, or are switched off
  • Rust client: retrieving expectations whose httpResponse (or template responseOverride) body is not a plain string, such as a BINARY, typed JSON, FILE or XML body or an inline JSON object, no longer fails with "invalid type: map, expected a string"; the body is read back and sent again unchanged
  • Rust client: a JSON array or scalar body read back from the server (request or response) is now a typed JSON body rather than a plain string, so sending it back no longer turns a JSON body into a string body
  • Go client: a DNS MX record with priority 0 (for example MXRecord(name, 0, exchange)) is now served with preference 0. Before, the client left a zero priority out of the expectation and the server answered with its default preference of 10. A DnsRecord with Type: "MX" now always sends its Priority, so an MX record built as a struct literal without Priority is now served with preference 0 rather than 10
  • Rust client: close_breakpoint_websocket() no longer hangs. While the callback WebSocket was idle, its background reader held the socket lock while waiting for the next message, so the close call waited on that lock forever. This WebSocket is opened by mock_with_callback and by breakpoints. The call now returns at once and closes the connection
  • HTTP/3: large downloads with curl --http3 built on OpenSSL's QUIC support (as shipped by Debian and Ubuntu) stall far less often on a Linux host left at the usual net.core.rmem_max. MockServer now reads more of the client's packets at a time, so fewer of the client's acknowledgements and flow-control updates are dropped. This cut stalls from 14 to 2 in 90 downloads of 20 MiB at a stock buffer. Raising net.core.rmem_max to 4194304 on the host prevented every stall in our tests (none in 180 downloads)
  • HTTP/3 on Linux: the HTTP/3 port now uses the native epoll transport, like the TCP ports, when useNativeTransport is on (the default). It reads the client's packets in batches and sends its own in batches (GSO), so large downloads with curl --http3 built on OpenSSL no longer stalled at the usual net.core.rmem_max: none of 122 downloads of 20 MiB stalled, against 11 with the previous transport, and downloads ran about 55% faster on about 25% less CPU. Where the network path refuses batched sends (some VPN or rootless-container network devices), MockServer logs one warning and sends packets one at a time from then on. macOS and Windows, and Linux with useNativeTransport=false, keep the previous transport
  • Java, Go, Node, Python, Ruby, PHP, .NET and Rust clients: an MCP mock whose tool name, resource URI or prompt name contains a backslash now matches tools/call, resources/read and prompts/get requests for it. Before, the backslash was not escaped in the request matcher, so a name such as a\b never matched, and one ending in a backslash or containing \' made the matcher invalid
  • Rust client: the callback WebSocket used by mock_with_callback and breakpoints now works against a MockServer reached over HTTPS (secure(true)). Before, it could not open a wss connection at all. It now uses the same TLS settings as the client's HTTP calls: the platform trust roots, a CA added with ca_cert_pem or ca_cert_pem_path, tls_verify(false), and the client_cert_pem client certificate
  • .NET client: disposing the client no longer hangs when MockServer stops answering on the callback WebSocket. If the server did not reply to the close handshake while a callback handler was running, or just after the WebSocket connected, Dispose waited forever. It now waits at most 5 seconds and then drops the connection

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

@elastic-renovate-prod elastic-renovate-prod Bot added changelog:skip dependencies Pull requests that update a dependency file labels Oct 21, 2026
@elastic-renovate-prod
elastic-renovate-prod Bot requested a review from a team as a code owner October 21, 2026 08:27
@LikeTheSalad
LikeTheSalad merged commit c96ac9c into main Oct 21, 2026
36 checks passed
@LikeTheSalad
LikeTheSalad deleted the renovate/org.mock-server-mockserver-client-java-9.x branch October 21, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-java changelog:skip dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant