TL;DR: Legacy Java remains embedded in enterprise systems, with nearly 70% of organisations saying more than half of their applications run on Java or the JVM, according to Azul's 2025 survey cited by Oligo Security. Runtime protection shifts the focus from static vulnerability lists to live execution paths, which is where legacy library abuse actually becomes exploitable.
At a glance
What this is: This is an analysis of why legacy Java applications need runtime protection, because static scanning misses which vulnerable code paths are actually executing in production.
Why it matters: It matters because IAM and NHI teams increasingly inherit machine-run application estates where trust, execution, and blast radius must be controlled at runtime, not just at build time.
By the numbers:
- Nearly 70% of organizations report that more than half of their applications run on Java or the JVM.
- 19% of applications still run on Java 6 or 7, versions released nearly two decades ago.
- 13% of organizations still rely on vulnerable versions of Log4j in production, years after patches were released.
👉 Read Oligo Security's analysis of runtime defense for legacy Java applications
Context
Legacy Java security is hard because the risk sits inside long-lived applications, not just at the perimeter. When libraries are unmaintained, unpatched, or too tightly coupled to replace, a scan alone cannot tell security teams whether the vulnerable path is actually reachable in production. That makes Java runtime protection directly relevant to NHI governance, because service-driven applications and their credentials often carry business-critical access.
The source article argues for moving from build-time assumptions to runtime evidence. In practice, that means treating application execution as part of identity security, because machine identities, service accounts, and workload access can all be abused through the same live execution paths that traditional tooling misses. For practitioners, this is a familiar problem in a more visible form: the environment is stable, but the attack surface keeps shifting beneath it.
Key questions
Q: How should security teams prioritise legacy Java vulnerabilities?
A: Prioritise the vulnerabilities that are actually executing in production, exposed through reachable interfaces, and attached to high-value business functions. A long list of dormant CVEs creates noise, while active runtime paths define real risk. The best triage model combines execution evidence, exploitability, and workload privilege scope.
Q: Why do legacy Java applications create a bigger security problem than patching alone?
A: Because patching is often slow, risky, or impossible when code is tightly coupled to business processes. The result is exposure debt: known vulnerabilities remain live while teams defer change to avoid breaking critical systems. Runtime controls are needed when operational continuity outweighs the speed of code replacement.
Q: What is the difference between static scanning and runtime protection for Java?
A: Static scanning predicts what could be vulnerable, while runtime protection shows what is actively happening in production and can stop abuse in real time. Scanning is useful for inventory and planning, but it cannot confirm exploitability. Runtime protection closes that gap by observing execution and blocking unsafe behavior as it occurs.
Q: How can organisations reduce blast radius in legacy Java environments?
A: Limit the privileges of the workload, monitor live code execution, and block unsafe actions before they complete. That combination reduces how far an attacker can move if a library is abused. Blast radius is controlled less by the number of vulnerabilities than by the trust granted to the running application.
Technical breakdown
Why static analysis misses runtime Java risk
Static analysis can identify libraries, call graphs, and known CVEs, but it cannot prove which code paths are executed in a live application. That gap matters in Java because many vulnerable methods exist in dependencies that are present but never called, while others only become dangerous under a specific input chain. Runtime protection focuses on observed execution, which turns speculative exposure into measurable behavior. For legacy systems, that is the difference between theoretical risk and active risk, especially when the application cannot be safely rewritten or fully patched.
Practical implication: Security teams should use runtime evidence to prioritise remediation work, not just dependency inventories.
How runtime blocking contains exploit chains without breaking applications
Runtime defense works by watching for unsafe actions as they happen and stopping malicious behavior at the function or syscall boundary. In Java, that can mean intercepting dangerous deserialization, suspicious JNDI lookups, or attempts to load attacker-controlled classes before the exploit completes. The architectural point is not that every risky library is removed. It is that abusive execution is constrained in real time while legitimate workflows continue. That is especially important when legacy systems support revenue or operational continuity and cannot tolerate broad preventive controls that halt normal processing.
Practical implication: Practitioners should look for controls that can block exploit behavior while preserving application availability.
Why legacy dependency sprawl becomes an identity and access issue
Legacy Java stacks often embed third-party code, transitive dependencies, and service access patterns that are hard to inspect end to end. That creates security ambiguity: the application may look compliant at a policy level while still running code with excessive reach into data, services, or internal APIs. From an NHI perspective, the problem is not only vulnerable code. It is the trust granted to the workload that executes it. Runtime visibility helps teams see where that trust is being exercised, which is essential when service accounts and application tokens are part of the same blast radius.
Practical implication: Teams should map workload privileges to live execution paths and shrink access where code is unnecessarily trusted.
Threat narrative
Attacker objective: The attacker wants to convert a vulnerable Java execution path into code execution, then use the application's trust to reach internal systems or data.
- Entry occurs when an attacker reaches a public API or other interface that accepts unsafe input and passes it into legacy Java deserialization or lookup logic.
- Escalation follows when the crafted payload triggers a gadget chain, unsafe class loading, or a JNDI-style retrieval that executes attacker-controlled code.
- Impact is achieved when the payload runs operating-system commands, loads malicious configuration, or accesses internal resources through the vulnerable application context.
Breaches seen in the wild
- MongoBleed breach — MongoBleed exposed secrets across 87K MongoDB servers.
- IOS app secrets leakage report — iOS apps leaking hardcoded secrets and credentials endangering user privacy.
Read our 52 NHI Breaches Analysis report for a comprehensive view of breaches impacting Non-Human Identities including AI Agents.
NHI Mgmt Group analysis
Runtime truth is the missing control plane for legacy Java security. Static inventories and vulnerability scanners tell teams what exists, not what executes. In tightly coupled Java estates, that distinction decides whether a finding is theoretical or exploitable. The field should treat live execution telemetry as a core security control, not an optional observability layer. Practitioners should prioritise runtime truth over dependency theory.
Legacy Java risk is a governance problem, not just an AppSec problem. When teams cannot patch fast enough, they implicitly accept exposure debt. That debt accumulates across service accounts, application tokens, and internal privileges that the workload can reach. NHI governance has to account for the identity used by the application as well as the code it runs. Practitioners should review workload privileges as part of remediation planning.
Identity blast radius is the right concept for runtime defense in Java estates. The practical question is not only whether a library is vulnerable, but how far an exploited workload can move once it is abused. Limiting that blast radius requires visibility into execution, privilege scope, and dependency reachability. This is where legacy Java security and NHI governance converge. Practitioners should reduce trust in every workload that cannot be fully modernized.
Non-intrusive blocking is becoming the default expectation for legacy protection. Organisations are unlikely to replace critical Java systems just to remove risk, so security controls must work around operational constraints. That raises the bar for runtime defense tools: they must stop abuse without breaking core business flows. The market is moving toward containment-first controls because remediation cycles are too slow for the exposure profile. Practitioners should evaluate whether their controls can contain, not just detect.
Transitive dependency exposure is the hidden scale problem. Java estates rarely fail because teams knowingly deploy one bad library. They fail because old packages persist deep in dependency chains and survive far longer than remediation teams expect. This makes governance and visibility more important than reactive patch campaigns. Practitioners should inventory active execution paths and not assume a dependency is safe just because it is buried.
From our research:
- Enterprises that have experienced a compromised NHI averaged 2.7 separate incidents in the past 12 months, according to The 2024 ESG Report: Managing Non-Human Identities.
- From our research: Two-thirds of enterprises have endured a successful cyberattack resulting from compromised non-human identities, with a quarter encountering multiple attacks.
- From our research: The NHI Lifecycle Management Guide shows how provisioning, rotation, and offboarding reduce long-lived access exposure.
What this signals
Identity blast radius is now a practical control objective for runtime-heavy applications. Java estates that cannot be replaced quickly should be treated as live trust zones, where service accounts and application tokens inherit the same constraints as the code they execute. Teams that already use the NIST Cybersecurity Framework 2.0 can map this work to protect and detect functions, while workload visibility should be aligned to the NHI Lifecycle Management Guide.
With 2.7 separate incidents in the past 12 months for organisations that experienced a compromised NHI, the lesson for Java-heavy environments is that repeated exposure is the norm when identity and execution controls are weak. Runtime telemetry should therefore feed access review, privilege reduction, and containment decisions, not just security dashboards.
Runtime containment becomes the interim strategy when modernization is delayed. Teams should expect more appetite for blocking controls that stop unsafe execution without disrupting core services, especially in estates where patching cadence lags business need. The operational question is no longer whether runtime defense is elegant, but whether it lowers exposure fast enough to matter.
For practitioners
- Inventory runtime-executing Java paths Use runtime telemetry to identify which libraries, methods, and code paths actually execute in production, then prioritise only those paths for containment or remediation. Pair that list with owner mapping so application teams know which services depend on each exposed path.
- Constrain workload privileges before patching lags Reduce the permissions held by service accounts and application tokens associated with legacy Java workloads. Focus on internal APIs, data stores, and file-system access that the workload does not need for normal processing.
- Block unsafe execution patterns at runtime Add protections for deserialization abuse, suspicious lookup behavior, and malicious class loading so exploit attempts are stopped before code execution completes. The control should preserve normal application flows, not force a maintenance outage.
- Use remediation queues based on exploitability Sort Java vulnerabilities by observed execution, exposure of the entry point, and business criticality. Findings that never execute in production should not receive the same urgency as active paths with external reach.
Key takeaways
- Legacy Java creates a security gap because static tools cannot tell teams which vulnerable paths are actually live in production.
- Runtime protection matters because it can stop unsafe execution while preserving business continuity in systems that cannot be rapidly rewritten.
- For NHI and IAM teams, the core issue is blast radius: the workloads running legacy code often hold the trust needed to move laterally.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10 address the attack and risk surface, while NIST CSF 2.0 and NIST Zero Trust (SP 800-207) set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP Non-Human Identity Top 10 | NHI-03 | Legacy Java workloads often retain risky secrets and long-lived access. |
| NIST CSF 2.0 | PR.AC-4 | Runtime Java protection depends on limiting access to what workloads actually need. |
| NIST Zero Trust (SP 800-207) | PR.AC-4 | Zero Trust requires continuous validation of workload access in live application flows. |
Treat Java workloads as continuously verified identities and constrain internal access by execution context.
Key terms
- Runtime Protection: Runtime protection is a control model that observes application behavior while software is running and blocks unsafe actions as they occur. In Java estates, it helps distinguish active exploit paths from dormant vulnerable code, which is essential when patching is delayed or impossible.
- Identity Blast Radius: Identity blast radius is the amount of damage an attacker can cause after compromising a workload, service account, or token. In practice, it is shaped by privilege scope, reachable systems, and how much trust the application has been given at runtime.
- Exposure Debt: Exposure debt is the buildup of known but unresolved security risk when teams postpone remediation because systems are difficult to change safely. For legacy applications, it accumulates quickly when patching, refactoring, or replacement would disrupt core business operations.
- Transitive Dependency: A transitive dependency is a package that your software uses indirectly through another library rather than calling it directly. These dependencies often hide in Java estates, which makes visibility and runtime validation necessary to understand what code is actually present and active.
Deepen your knowledge
Java runtime protection and identity blast radius are core topics in our NHI Foundation Level course, the industry's only accredited NHI security programme. If you are governing long-lived workloads that still cannot be patched quickly, it is worth exploring.
This post draws on content published by Oligo Security: Runtime Security for Java: From Visibility to Active Defense. Read the original.
Published by the NHIMG editorial team on 2026-05-11.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org