Development tools under /wheels/* are reachable by remote clients when the public component is enabled
What fixes it
- 4.2.0wheels, otherGitHub
A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.
Description
Impact
When enablePublicComponent is true (the default in the development environment, or any environment where an application sets it), Wheels serves password-less developer tools under /wheels/*: application info and settings, the route table, API docs, package views, and the core and application test runners.
Wheels 4.1.2 restricted these tools to local requests, but the check relies only on client-supplied request headers and does not verify the connecting peer address. A remote client can therefore still reach the tools. Before 4.1.2 there was no restriction at all.
Exposure includes environment, settings and datasource details, the full route table, and the ability to start test runs. In versions where application tests default to the primary datasource, a test run can write to the application's real database.
This matters most for servers that run in development mode while reachable from a network, including production images generated by wheels deploy init before 4.2.0 (see #3946), and development servers reachable on a LAN.
/wheels/migrator and the password-protected CLI endpoints already require a loopback peer and are not affected.
Patches
Fixed in 4.2.0. The developer tools now also require the connecting socket peer (REMOTE_ADDR) to be a loopback address, in addition to the existing local-Host and X-Forwarded-For checks. They are refused (404) in the production environment regardless of enablePublicComponent.
Behaviour change for Docker-hosted development: through a published Docker port, requests arrive from the Docker gateway address, not loopback, so the tools now return 403. The 403 message names the new setting. To allow specific peers in development or testing, set it in your config:
set(devToolsAllowedRemoteAddresses = "172.17.0.1"); // exact IPv4/IPv6, or IPv4 CIDR such as 172.16.0.0/12
The setting is empty by default (loopback only). It is ignored outside development and testing, and wildcard, /0 and malformed entries match nothing. With Docker Desktop, clients on your LAN can also arrive from the gateway address, so publish the port on 127.0.0.1 (for example 127.0.0.1:8080:8080) when you allow the gateway.
Workarounds
- Never run production servers in
developmentmode, and do not setenablePublicComponent=trueoutside development. - Do not expose a development-mode server on a network interface: bind it to
127.0.0.1(the Wheels CLI does so by default from 4.2.0), or publish Docker ports on127.0.0.1. - Block
/wheels/*and/wheels-docsat the reverse proxy or web server.
Text from GitHub Advisory Database
Affected versions 1
- wheels, other>= 4.0.0, <= 4.1.2GitHub