Cross-site scripting (XSS) continues to be one of the most prevalent and severe security flaws affecting web applications. Developers building Java web apps need to take proactive steps to prevent such attacks.
What is XSS, and why are Java applications at risk
XSS enables attackers to embed harmful scripts—most often JavaScript—into web pages that are then executed in the browsers of unsuspecting visitors. Consequences may include confidential data theft, session hijacking, or redirection of users to harmful websites.
Java applications are especially prone to XSS risks since they frequently process dynamic content, user-submitted input, and intricate templates, all of which can create opportunities for exploitation if not carefully managed.
Java’s web layer produces HTML that is delivered to the client. When user input is added to this HTML without sanitization or encoding, it is simple to launch an exploit.
Types of XSS attacks
- Reflected XSS: The attacker sends harmful input in an HTTP request (commonly through a RequestParam), which is instantly reflected back in the web page or response.
- Stored XSS: The malicious script is saved in the backend system and later presented on a web page, putting every subsequent visitor at risk of exposure.
- DOM-based XSS: The attack is carried out fully within the browser’s Document Object Model (DOM), where injected JavaScript runs client-side and remains invisible to server-side security checks.
How Java web applications can be exploited
Common exploitation scenarios include injecting <script> tags, overriding HTML attributes, or manipulating client-side JavaScript execution. Attackers frequently take advantage of input fields, URL parameters, and similar entry points to inject malicious code. If this input is not properly validated or encoded, a Java application can be exposed to XSS.
Common Entry Points for XSS in Java
User input in JSP/servlet pages
Inputs like comments, search terms, and form submissions can easily turn into attack vectors if they are not properly validated and sanitized.
Dynamic Content Rendering
Numerous Java applications generate dynamic HTML, JavaScript, or CSS that depends on user input. When output encoding is missing or inadequate, attackers can inject harmful code directly into this dynamically rendered content.
Incorrect HTML encoding
Incorrect encoding of special characters such as <, >, “, and ‘ can allow attackers to go beyond the intended HTML or JavaScript context. It can lead oto XSS if the output is not properly escaped.
Best practices for preventing XSS in Java
Validating and sanitizing user input
A good place to start is by strictly validating input using whitelists, especially in RequestParam, form fields, or API payloads.
For example, if only alphanumeric characters are expected, special characters should be rejected or removed.
Where rich text input is required and explicitly allowed, you should use a dedicated sanitization library such as OWASP Java HTML Sanitizer or JSoup to remove or neutralize dangerous HTML tags and attributes.
But validation alone is not enough to stop XSS and should always be combined with proper output encoding for reliable protection.
Context-aware output encoding
Output encoding is essential in protection against XSS. By converting special characters in user-supplied data into safe representations, it prevents them from being executed as code in the browser. Examples of encoding include:
- HTML encoding: Replacing < with <, > with >, and & with & to prevent HTML structure from being broken.
- Attribute encoding: Ensures that any data placed inside HTML attributes is properly enclosed in quotes and that special characters are encoded, preventing them from being misinterpreted as executable code.
- JavaScript encoding: If user data is put inside JavaScript, it should be encoded so it stays as plain text and cannot turn into harmful code.
It is recommended to use libraries such as OWASP Java Encoder for safe, automatic, and consistent handling of HTML, JavaScript, CSS, and URL encoding.
Escaping data in JSPs with JSTL
The JavaServer Pages Standard Tag Library (JSTL) offers tags like <c:out>, which automatically escape user input into safe HTML. This makes them safer than using raw expressions like ${}, as it lowers the chance of XSS from unescaped output.
Reliable security libraries
Instead of relying on manual escaping or regular expressions, teams can use proven security libraries such as those already mentioned: OWASP Java Encoder, OWASP Java HTML Sanitizer or JSoup.
In most cases, a specialized library will be more reliable and efficient than any custom solution, and will also make it easier to maintain and update the code.
Correct security headers
Setting a proper Content Security Policy (CSP) header helps block whole categories of attacks, including different forms of XSS.
It is worth noting that the special X-XSS-Protection header is now deprecated in modern browsers and should not be used as protection against cross-site scripting.
Framework-based XSS protection for Java
Built-in security measures for XSS might be available for some frameworks.
As with libraries, it is usually better to use built-in functions than to try to write your own.
XSS headers and filters in Spring Security
Spring Security is mainly focused on authentication and authorization, but it also provides several features under the umbrella of “exploit protection”. These include default security headers, configuration options, and request filtering.
Its XSS-specific feature is only the outdated X-XSS-Protection header. The framework makes it easier to configure CSP headers, but they are not turned on by default, since content security policies typically need to be tailored for each site.
Jakarta EE and built-in controls
Jakarta EE (Java EE) offers mechanisms such as servlet filters and tag libraries that help developers apply input validation and secure output encoding.
Once again, the recommended approach for mitigating XSS is to rely on built-in security features whenever available.
Testing and monitoring XSS in Java applications
Static analysis for secure coding
Static Application Security Testing (SAST, such as Mend.io) tools analyze Java source code, configuration files, and templates to detect potential security flaws, such as malformed output encoding or unsanitized input processing.
SAST helps enforce secure coding practices during development, but it does not account for how the application actually runs. It cannot confirm whether a vulnerability is exploitable or analyze how different components interact and whether user input truly reaches a risky spot.
Runtime protection with RASP
Runtime Application Self-Protection (RASP) solutions observe applications as they run and can identify or stop suspicious actions in real time.
RASP should not be seen as a replacement for secure coding or thorough testing. Since it works reactively and depends on known attack patterns, it may miss more advanced XSS techniques. And because it runs on the server, it cannot detect client-side issues like DOM-based XSS.
Used properly, RASP can reduce the damage from XSS attacks that evade other safeguards, but it should be treated as an additional layer of defense alongside other mentioned practices.
Detecting XSS vulnerabilities with DAST
Dynamic Application Security Testing (DAST, for example, Invicti) simulates real-world attacks on a running web application, making it the most effective way to determine whether XSS vulnerabilities are actually exploitable.
DAST does not require access to the source code and works from the outside, as a malicious hacker. It works by sending payloads through HTTP requests and analyzing the application’s responses.
This makes DAST especially useful in Java environments, where different layers of filtering, validation, and encoding may combine in unpredictable ways.
For instance, a Java web application may apply input validation in a Spring controller, output encoding in a JSP, and extra filtering through a servlet filter. While each layer might seem secure individually, only DAST can verify whether they collectively prevent real-world XSS attacks.
Advanced DAST solutions such as Invicti (based on Acunetix and Netsparker) also include evidence-based scanning to eliminate false positives and detect all types of XSS vulnerabilities.
To test the Invicti platform for free, please submit a request below.







