In May 2025, a single GET /actuator/heapdump returned a 150MB file. With grep, plaintext passwords appeared in seconds. That was the TeleMessage incident, added to CISA's Known Exploited Vulnerabilities catalog in July 2025 with confirmed active exploitation.
/actuator/heapdump is not a forgotten monitoring feature. It is a full memory exfiltration primitive. Actuator endpoints were designed for operations teams with internal access, not the public internet. When they reach the internet, they deliver decrypted credentials, database passwords, and active session tokens to anyone who reaches the URL.
The config line that ships this attack surface to production
management.endpoints.web.exposure.include=* appears in quickstart guides and Stack Overflow templates. It enables every Actuator endpoint without authentication, reversing Spring Boot 2.0's secure-by-default redesign. It gets copied directly into production configurations.
Spring Boot 2.0, released in 2018, exposes only /health and /info by default. The decision was deliberate: versions before 2.0 opened all endpoints without restriction. One line reverses that: management.endpoints.web.exposure.include=*. This line appears as the "fix" in dozens of Stack Overflow answers to "why isn't my actuator working?". No warning accompanies it in the typical tutorial.
The result at scale: 92,000 Spring Boot endpoints indexed on Shodan with Actuator fingerprints. GreyNoise records over 1,000 malicious IPs scanning for these paths in any 30-day window. Wiz found that 11% of cloud environments with Actuator expose it to the internet; 24% of those have active misconfigurations. The cycle is predictable: developer copies the line from Stack Overflow, app reaches production, Shodan indexes within hours.
Six endpoints, six distinct attack primitives in production
Each Actuator endpoint represents a different attack class. They are not just data leaks. The distinction matters because different endpoints enable different follow-on attacks: silent reconnaissance, credential extraction, log poisoning, route mapping, and direct JVM termination.
/actuator/env returns all application properties. Spring Boot 2.3+ masks keys containing password, secret, or key in the name. Custom names like database.connection-string, api.token, or db.pass return as plaintext, unmasked.
/actuator/heapdump delivers the full JVM heap as a compressed .hprof file. Eclipse MAT extracts decrypted values from every variable in memory at dump time: database passwords, API tokens, AWS keys. /actuator/loggers is a write attack: a POST changes any package's log level to TRACE; request and response bodies, including Authorization headers, appear in logs immediately.
/actuator/mappings reveals the complete route inventory, including /internal/*, /admin/*, and undocumented endpoints invisible to regular API consumers. /actuator/beans exposes the full Spring application context: bean definitions, dependencies, and loaded configuration classes. /actuator/shutdown, when enabled with management.endpoint.shutdown.enabled=true, terminates the JVM with a single unauthenticated POST, with no rate limiting or confirmation required.
Confirmed breaches: Volkswagen and TeleMessage
The Volkswagen case in 2024 showed the real impact of an exposed /heapdump without authentication. A researcher accessed the public endpoint on VW's telematics service. The heap dump contained AWS access keys in plaintext. The researcher downloaded 9.5TB of GPS data from approximately 800,000 vehicles directly from S3.
The same dump contained OAuth client IDs and secrets used for JWT generation. This opened access to internal APIs and data on 800,000 EV owners across VW, Audi, Seat, and Skoda brands. Location data precision reached 10cm. Without authentication on the endpoint, the entire attack was a single curl.
CVE-2025-48927 hit TeleMessage, a Signal clone used by US government officials. The Actuator was exposed without authentication. A single GET /actuator/heapdump returned 150MB containing plaintext credentials. CISA added the CVE to the KEV catalog on July 1, 2025, confirming active exploitation before a patch was available. KEV listing means confirmed in-the-wild attacks, not theoretical risk.
In a bug bounty case published around the same time, a researcher found /actuator/heapdump exposed on a major food and drug retailer. The heap contained database credentials and internal API keys. The workflow was identical to Volkswagen: curl, decompress, Eclipse MAT, credentials extracted within minutes.
The extraction workflow requires no specialized tools. curl -O http://target/actuator/heapdump downloads the file. In Eclipse MAT, the OQL query SELECT toString(s) FROM java.lang.String s WHERE toString(s).contains('password') returns credential strings from heap objects. For quick extraction: strings heapdump.hprof | grep -i "password\|secret\|token".
CVE-2022-22947: remote code execution, not just data leakage
CVE-2022-22947 demonstrates that data leakage is not the worst case when Actuator is exposed. CVSS 3.1: 10.0 Critical; vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H (scope-changed, S:C, is why the score reaches 10.0). No authentication, no user interaction, exploitable over the network.
The vulnerability affects Spring Cloud Gateway before versions 3.0.7 and 3.1.1, when the Gateway Actuator endpoint is enabled and exposed. The /actuator/gateway/routes endpoint accepts route definitions via POST. Those definitions accept SpEL (Spring Expression Language) expressions in filter parameters; the server evaluates them in StandardEvaluationContext, which has full access to the Java runtime.
The payload: a POST with a filter containing #{T(java.lang.Runtime).getRuntime().exec('id')}. The server executes the command inside the JVM process, running as the application's OS user. Public exploits appeared within days of disclosure in March 2022. Remediation requires upgrading to 3.0.7+ or 3.1.1+; disabling the Gateway Actuator removes the vector regardless of version.
Detection: attackers find exposed endpoints before defenders do
The Actuator fingerprint is unambiguous: /actuator/health returns {"status":"UP"} as JSON, with no false positives. Automated scanners find exposed deployments within hours of them reaching the internet. Not days, hours.
Fuzzing wordlists include /actuator, /actuator/health, /actuator/env, /manage, and /management, standard in every API reconnaissance tool. Common exposure ports: 8080 (development default), 8443, 9000, and 9090 (separate management port). The Nuclei template spring-actuator in the projectdiscovery/nuclei-templates repository returns all discovered endpoints and maps which are active.
GreyNoise records around 1,000 unique malicious IPs targeting Actuator health check paths in any 30-day window. 95% are classified as malicious, not researchers. The attack timeline is predictable: endpoint reaches the internet, Shodan indexes within hours, scanning begins within days.
Three independent controls
Actuator security requires three independent controls. Each eliminates a different attack vector. None alone is sufficient. Together, they make Actuator endpoints unreachable from the public internet regardless of any individual failure.
Control 1, port isolation: management.server.port=8081 binds the Actuator to an internal interface. A firewall rule blocks the port at the network level. Public traffic never reaches the endpoints, regardless of the Spring exposure configuration property.
Control 2, Spring Security authentication: add to SecurityFilterChain:
http.authorizeHttpRequests(auth -> auth
.requestMatchers(EndpointRequest.toAnyEndpoint()).authenticated()
);
For /heapdump and /env, restricting to specific roles is recommended. Authentication fails when misconfigured; port isolation is the first control for exactly that reason.
Control 3, explicit disable: management.endpoint.heapdump.enabled=false and management.endpoint.shutdown.enabled=false remove the endpoints regardless of exposure or authentication configuration. The last line of defense: even if both previous controls fail, the endpoint does not exist.
Automated API surface scanners flag Actuator endpoints by checking for /actuator path responses with HTTP 200 and JSON content-type before any authentication.
Kubernetes health probes require /actuator/health to be reachable from the cluster control plane. This is a legitimate operational need. The correct scope is a network policy that allows only the kubelet IP range to reach that single endpoint on the management port. Public internet access to all endpoints on the application port is never justified.
/actuator/heapdump is not a monitoring feature accidentally left on. It is a full memory exfiltration primitive. Every production Spring Boot deployment should treat it with the same access controls as the database console. Never accessible from the public internet. Never without authentication. Never without explicit audit.
Top comments (0)