Exposed Spring actuator /env: lock the endpoint and rotate what it showed
Securing the Spring Boot actuator and rotating any secrets it printed stops your live app config from being read by anyone
The threat
The scanner requested /actuator/env (or /env on older Spring Boot) and got back a JSON dump of the applicationβs live environment: every property Spring resolved at startup. Actuator is a built-in diagnostics feature, and /env is meant for operators, not the public. Reachable without authentication, it reads out your whole configuration on request.
That configuration routinely includes the sensitive parts: spring.datasource.password, cloud and mail credentials, third-party API keys, internal hostnames. Even where Spring masks some values, neighbouring endpoints (/actuator/configprops, /actuator/heapdump) can fill the gaps, and older versions masked less. Treat anything the endpoint printed as known to whoever fetched it.
The exact fix
Step 1, contain: rotate any secret the endpoint exposed. Read what /env actually returned, and rotate each sensitive value at its source: database password, API keys, mail and message-broker credentials. Anything printed there should be considered public.
Step 2, stop exposing the endpoint. Actuator should never be open to the internet. In modern Spring Boot (application.properties or .yml):
- Expose only what you need over the web. Health is usually enough:
management.endpoints.web.exposure.include=health
management.endpoints.web.exposure.exclude=env,beans,configprops,heapdump,threaddump
management.endpoint.env.show-values=never
- Put actuator behind auth (Spring Security), and ideally on a separate management port bound to the internal network:
management.server.port=8081
management.server.address=127.0.0.1
- If you do not use actuator at all, drop the
spring-boot-starter-actuatordependency.
And as a backstop, block the path at your reverse proxy so it can never reach the app from outside.
nginx:
location /actuator {
deny all;
return 404;
}
The management port is the strongest single move. Setting
management.server.portwith an internaladdressmeans that even if some endpoint is enabled by accident later, the public listener never serves it.
Verify it
curl -s https://yourdomain.com/actuator/env
You want a 404 or 401, not a JSON body full of property names. If "activeProfiles" or "propertySources" appears in the response, the endpoint is still open.
Proof
The ApeCyber scanner flags this with a single unauthenticated GET of the actuator path, from the outside, reading only what the endpoint volunteers and probing no further. At β40 this is the maximum single-finding weight, and it clears the moment the endpoint stops answering anonymous requests and the exposed secrets are rotated.