We have charged credit card:" + field1 + "
");
+ cart.append("
We have charged credit card:" + StringEscapeUtils.escapeHtml4(field1) + "
");
cart.append(" -------------------
");
cart.append(" $" + totalSale);
From a32bdd3bd162a33d0a580f0a614dc4e532f0e95e Mon Sep 17 00:00:00 2001
From: beanbeah <24713371+beanbeah@users.noreply.github.com>
Date: Sun, 9 Aug 2026 11:59:01 -0700
Subject: [PATCH 7/7] Judge the reflected-XSS attack on the escaped value, not
the raw request param
The previous commit HTML-escaped field1 before appending it into the
cart output, which correctly stops a live /
payload leaves any live tag in the rendered output any more.
---
.../xss/CrossSiteScriptingLesson5a.java | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/src/main/java/org/owasp/webgoat/lessons/xss/CrossSiteScriptingLesson5a.java b/src/main/java/org/owasp/webgoat/lessons/xss/CrossSiteScriptingLesson5a.java
index 79d962b67..e14c5cd0b 100644
--- a/src/main/java/org/owasp/webgoat/lessons/xss/CrossSiteScriptingLesson5a.java
+++ b/src/main/java/org/owasp/webgoat/lessons/xss/CrossSiteScriptingLesson5a.java
@@ -62,14 +62,17 @@ public AttackResult completed(
userSessionData.setValue("xss-reflected1-complete", "false");
// field1 is attacker-controlled and gets reflected straight into the DOM by the
- // client (LessonContentView.js renders "output" via jQuery .html()). HTML-escape it
- // here so any markup/script it contains is displayed as inert text instead of being
- // parsed by the browser -- this is a DOM-based reflected XSS sink otherwise. The
- // lesson's own success/failure detection below still runs against the raw, un-escaped
- // field1 so the intended "submit " teaching flow is unaffected.
+ // client (LessonContentView.js renders "output" via jQuery .html()). Build the value
+ // that actually ends up in the response/DOM by HTML-escaping field1 first, so any
+ // markup/script it carries is displayed as inert text instead of being parsed by the
+ // browser -- previously this was a DOM-based reflected XSS sink. Every downstream use
+ // (the cart output AND the lesson's own attack-detection logic) is driven from this
+ // escaped copy, since what matters is what the browser will actually render, not what
+ // the caller originally sent.
+ String renderedCardNumber = StringEscapeUtils.escapeHtml4(field1);
StringBuilder cart = new StringBuilder();
cart.append("Thank you for shopping at WebGoat.
Your support is appreciated
We have charged credit card:" + StringEscapeUtils.escapeHtml4(field1) + "
");
+ cart.append("
We have charged credit card:" + renderedCardNumber + "
");
cart.append(" -------------------
");
cart.append(" $" + totalSale);
@@ -78,9 +81,9 @@ public AttackResult completed(
userSessionData.setValue("xss-reflected1-complete", "false");
}
- if (XSS_PATTERN.test(field1)) {
+ if (XSS_PATTERN.test(renderedCardNumber)) {
userSessionData.setValue("xss-reflected-5a-complete", "true");
- if (field1.toLowerCase().contains("console.log")) {
+ if (renderedCardNumber.toLowerCase().contains("console.log")) {
return success(this)
.feedback("xss-reflected-5a-success-console")
.output(cart.toString())