Sitemap

Preventing XSS in Spring Boot — Especially for @RequestBody String

2 min readMay 4, 2025

⚠️ The Problem

Many developers assume XSS (Cross-Site Scripting) is purely a frontend concern.

But if you’re accepting raw String inputs in a Spring Boot controller — especially using @RequestBody — and rendering them back in a web page or API without sanitization, you're opening the door to XSS vulnerabilities.

🚨 Dangerous Code Example

@PostMapping("/submit")
public ResponseEntity<String> submit(@RequestBody String comment) {
// Later returned in UI or logs
return ResponseEntity.ok(comment);
}

A malicious user can send:

"<script>alert('XSS')</script>"

If you render that back in an HTML page or inject into logs, your users could be exposed.

🧼 The Solution: Sanitize Inputs

To protect against XSS in this case, you should sanitize any input that could later be rendered as HTML or interpreted by a browser.

✅ Use OWASP Java HTML Sanitizer

A robust and customizable library maintained by OWASP:

Gradle:

implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20211018.1'

Maven:

<dependency>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>owasp-java-html-sanitizer</artifactId>
<version>20211018.1</version>
</dependency>

✅ Example with Sanitization

import org.owasp.html.PolicyFactory;
import org.owasp.html.Sanitizers;
@RestController
public class CommentController {
private final PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.LINKS); @PostMapping("/submit")
public ResponseEntity<String> submit(@RequestBody String comment) {
String sanitized = policy.sanitize(comment);
return ResponseEntity.ok(sanitized);
}
}

This allows some formatting and links, but strips out dangerous tags like <script>, <img onerror>, etc.

🔧 Alternative: Custom XSS Filter for JSON Fields

If you’re using DTOs instead of raw strings, you can:

  1. Add a Jackson deserializer
  2. Or apply sanitization in your service/controller layer.

Example:

@PostMapping("/submit")
public ResponseEntity<Comment> submit(@RequestBody Comment comment) {
comment.setText(policy.sanitize(comment.getText()));
return ResponseEntity.ok(comment);
}

❗ Do Not Do This:

String sanitized = comment.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;");

This is not reliable, and attackers can bypass such naive filters easily.

🧠 Best Practices

  • Sanitize inputs as early as possible
  • Log only sanitized or encoded data
  • Avoid rendering raw user input into web pages
  • Consider frontend escaping ([[${comment}]] in Thymeleaf, etc.)
  • Use Content Security Policy (CSP) headers where applicable

🛡️ Summary

XSS vulnerabilities can creep in anywhere untrusted user input is handled.
Even server-side endpoints like @RequestBody String can become a threat vector if their outputs are not properly sanitized.

Sanitize on input, validate on process, and escape on output.

💬 Have you audited your Spring Boot endpoints lately?
Let’s make XSS a thing of the past.

#Java #SpringBoot #WebSecurity #OWASP #XSS #BackendSecurity #SecureCoding

--

--

Karan Bhandari
Karan Bhandari

No responses yet