This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 824234c427 Harden HTML widget rendering and tidy security test comments
824234c427 is described below

commit 824234c427fa354b66df79c10388f5783566aea7
Author: James Bognar <[email protected]>
AuthorDate: Mon Aug 10 15:47:50 2026 -0400

    Harden HTML widget rendering and tidy security test comments
    
    - HtmlWidgetVar: degrade an individual widget's render failure to an empty
      fragment instead of propagating, so one failing $W{...} widget no longer
      blanks the rest of the surrounding page. Adds HtmlWidgetVar_Test.
    - PetstoreSpringboot_Test: fail fast with a clear message when a rendered
      page contains an inline server error, instead of an opaque assertion.
    - Remove stale weakness-class annotations from a set of path-traversal
      security test comments (comment-only cleanup).
---
 .../org/apache/juneau/commons/io/LocalDir.java     |  2 +-
 .../commons/io/LocalDir_PathTraversal_Test.java    |  2 +-
 .../apache/juneau/marshall/html/HtmlWidgetVar.java | 10 ++-
 .../juneau/marshall/html/HtmlWidgetVar_Test.java   | 81 ++++++++++++++++++++++
 .../rest/server/Rest_AllowedMethodParams_Test.java |  2 +-
 .../FreemarkerMixin_PathTraversal_Test.java        |  2 +-
 .../view/jsp/JspMixin_PathTraversal_Test.java      |  2 +-
 .../mustache/MustacheMixin_PathTraversal_Test.java |  2 +-
 .../ThymeleafMixin_PathTraversal_Test.java         |  2 +-
 .../DirectoryResource_PathTraversal_Test.java      |  2 +-
 .../examples/LogsResource_PathTraversal_Test.java  |  2 +-
 .../springboot/PetstoreSpringboot_Test.java        |  4 ++
 .../FreemarkerMixin_PathTraversal_Test.java        |  2 +-
 .../view/jsp/JspMixin_PathTraversal_Test.java      |  2 +-
 .../mustache/MustacheMixin_PathTraversal_Test.java |  2 +-
 .../ThymeleafMixin_PathTraversal_Test.java         |  2 +-
 16 files changed, 107 insertions(+), 14 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/io/LocalDir.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/io/LocalDir.java
index a9fd3b3e7d..fb3e33960c 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/io/LocalDir.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/io/LocalDir.java
@@ -223,7 +223,7 @@ public class LocalDir {
         *      LocalFile <jv>file2</jv> = 
<jv>dir</jv>.resolve(<js>"pages/about.html"</js>);
         * </p>
         *
-        * <h5 class='section'>Security (CWE-22 / path-traversal):</h5>
+        * <h5 class='section'>Security (path-traversal):</h5>
         * <p>
         * For filesystem-root {@code LocalDir} instances, path resolution is 
delegated to
         * {@link FileUtils#resolveSafely(java.io.File, String)} which enforces 
a strict boundary check:
diff --git 
a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/io/LocalDir_PathTraversal_Test.java
 
b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/io/LocalDir_PathTraversal_Test.java
index 8e1f768460..b0b8e30563 100644
--- 
a/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/io/LocalDir_PathTraversal_Test.java
+++ 
b/juneau-core/juneau-commons/src/test/java/org/apache/juneau/commons/io/LocalDir_PathTraversal_Test.java
@@ -26,7 +26,7 @@ import org.apache.juneau.commons.*;
 import org.junit.jupiter.api.*;
 
 /**
- * Path-traversal (CWE-22) boundary tests for {@link LocalDir#resolve(String)}.
+ * Path-traversal boundary tests for {@link LocalDir#resolve(String)}.
  *
  * <p>
  * Covers both the filesystem-root branch (delegates to {@code 
FileUtils.resolveSafely}) and
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/html/HtmlWidgetVar.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/html/HtmlWidgetVar.java
index cc08663404..1827c99299 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/html/HtmlWidgetVar.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/html/HtmlWidgetVar.java
@@ -65,6 +65,14 @@ public class HtmlWidgetVar extends SimpleVar {
                if (w == null)
                        return "unknown-widget-" + key;
 
-               return w.getHtml(session);
+               try {
+                       return w.getHtml(session);
+               } catch (@SuppressWarnings("unused") Exception e) {
+                       // Defensive per-widget degradation: an individual 
widget's render failure must not propagate out of
+                       // var resolution, since that would abort the whole 
enclosing string and blank the surrounding page.
+                       // Degrade to an empty fragment so the navlink renders 
empty and the rest of the page is unaffected.
+                       // Only Exception is caught so JVM Errors (OOM, etc.) 
still propagate.
+                       return "";
+               }
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/html/HtmlWidgetVar_Test.java
 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/html/HtmlWidgetVar_Test.java
new file mode 100644
index 0000000000..88e493f376
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/marshall/html/HtmlWidgetVar_Test.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.marshall.html;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.commons.svl.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * Tests {@link HtmlWidgetVar} resolution of <js>"$W{...}"</js> variables.
+ *
+ * <p>
+ * Covers the defensive per-widget degradation contract: a widget whose {@link 
HtmlWidget#getHtml(VarResolverSession)}
+ * throws must not propagate out of var resolution (which would abort the 
whole enclosing string and blank the page).
+ * Instead it degrades to an empty fragment while surrounding text and 
unregistered-widget placeholders are unaffected.
+ */
+class HtmlWidgetVar_Test extends TestBase {
+
+       private static VarResolverSession session(HtmlWidget...widgets) {
+               var vr = VarResolver.create().vars(HtmlWidgetVar.class).build();
+               var s = vr.createSession();
+               s.bean(HtmlWidgetMap.class, new 
HtmlWidgetMap().append(widgets));
+               return s;
+       }
+
+       private static HtmlWidget widget(String name, String html) {
+               return new HtmlWidget() {
+                       @Override public String getName() { return name; }
+                       @Override public String getHtml(VarResolverSession 
session) { return html; }
+                       @Override public String getScript(VarResolverSession 
session) { return null; }
+                       @Override public String getStyle(VarResolverSession 
session) { return null; }
+               };
+       }
+
+       private static HtmlWidget throwingWidget(String name) {
+               return new HtmlWidget() {
+                       @Override public String getName() { return name; }
+                       @Override public String getHtml(VarResolverSession 
session) { throw new RuntimeException("boom"); }
+                       @Override public String getScript(VarResolverSession 
session) { return null; }
+                       @Override public String getStyle(VarResolverSession 
session) { return null; }
+               };
+       }
+
+       @Test void a01_resolvesRegisteredWidget() {
+               var s = session(widget("greeting", "hello"));
+               assertEquals("before hello after", s.resolve("before 
$W{greeting} after"));
+       }
+
+       @Test void a02_unregisteredWidgetReturnsPlaceholder() {
+               var s = session(widget("greeting", "hello"));
+               assertEquals("before unknown-widget-missing after", 
s.resolve("before $W{missing} after"));
+       }
+
+       @Test void a03_throwingWidgetDegradesToEmptyAndDoesNotPropagate() {
+               var s = session(throwingWidget("boom"));
+               // The failing widget must degrade to empty rather than throw, 
and surrounding text must still render.
+               assertDoesNotThrow(() -> s.resolve("before $W{boom} after"));
+               assertEquals("before  after", s.resolve("before $W{boom} 
after"));
+       }
+
+       @Test void a04_throwingWidgetDoesNotAffectSiblingWidgets() {
+               var s = session(throwingWidget("boom"), widget("ok", "OK"));
+               assertEquals("[] [OK]", s.resolve("[$W{boom}] [$W{ok}]"));
+       }
+}
diff --git 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/Rest_AllowedMethodParams_Test.java
 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/Rest_AllowedMethodParams_Test.java
index 1800cc630f..dbe3e6f60a 100644
--- 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/Rest_AllowedMethodParams_Test.java
+++ 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/Rest_AllowedMethodParams_Test.java
@@ -170,7 +170,7 @@ class Rest_AllowedMethodParams_Test extends TestBase {
        }
 
        
//------------------------------------------------------------------------------------------------------------------
-       // Security: Malformed method parameters should return 405, not 500 
(CWE-74)
+       // Security: Malformed method parameters should return 405, not 500
        
//------------------------------------------------------------------------------------------------------------------
 
        @Test void b01_malformedMethodParameter_returns405() throws Exception {
diff --git 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
index 5bb00725e5..3d669d205e 100644
--- 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
+++ 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
@@ -73,7 +73,7 @@ class FreemarkerMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {
diff --git 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
index de05f9bc06..f4a75997df 100644
--- 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
+++ 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
@@ -80,7 +80,7 @@ class JspMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {
diff --git 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
index 463bc6b417..c489c81a60 100644
--- 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
+++ 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
@@ -67,7 +67,7 @@ class MustacheMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {
diff --git 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
index b0803e367a..d87c807dd1 100644
--- 
a/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
+++ 
b/juneau-integration-tests/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
@@ -63,7 +63,7 @@ class ThymeleafMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {
diff --git 
a/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/DirectoryResource_PathTraversal_Test.java
 
b/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/DirectoryResource_PathTraversal_Test.java
index 8e3d07df54..28ba5d5094 100644
--- 
a/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/DirectoryResource_PathTraversal_Test.java
+++ 
b/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/DirectoryResource_PathTraversal_Test.java
@@ -140,7 +140,7 @@ class DirectoryResource_PathTraversal_Test extends TestBase 
{
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct ../ traversal across each operation surface (view, 
download, delete)
+       // direct ../ traversal across each operation surface (view, download, 
delete)
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_GET_returns403() throws Exception {
diff --git 
a/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/LogsResource_PathTraversal_Test.java
 
b/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/LogsResource_PathTraversal_Test.java
index 6d70a2d496..6d4cb4478f 100644
--- 
a/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/LogsResource_PathTraversal_Test.java
+++ 
b/juneau-microservice/juneau-microservice-examples/src/test/java/org/apache/juneau/microservice/examples/LogsResource_PathTraversal_Test.java
@@ -139,7 +139,7 @@ class LogsResource_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct ../ traversal across each operation surface (view, 
download, delete)
+       // direct ../ traversal across each operation surface (view, download, 
delete)
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_GET_returns403() throws Exception {
diff --git 
a/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/petstore/springboot/PetstoreSpringboot_Test.java
 
b/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/petstore/springboot/PetstoreSpringboot_Test.java
index 6ae5e2c35d..a513c4a903 100644
--- 
a/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/petstore/springboot/PetstoreSpringboot_Test.java
+++ 
b/juneau-petstore/juneau-petstore-springboot/src/test/java/org/apache/juneau/petstore/springboot/PetstoreSpringboot_Test.java
@@ -157,6 +157,10 @@ class PetstoreSpringboot_Test {
        @Test void a01_rootRendersHtml() throws Exception {
                var resp = get("/", "text/html");
                assertEquals(200, resp.statusCode(), "body: " + resp.body());
+               // Fail fast if any rendered menu item / navlink returned a 
server error (e.g. a $W widget var that
+               // failed to resolve renders an inline "HTTP 500: Internal 
Server Error ..." fragment inside the 200
+               // page). Surface that fragment directly instead of the opaque 
"expected petstore link" failure below.
+               assertFalse(resp.body().contains("HTTP 500"), "root page 
rendered an inline server error: " + resp.body());
                assertTrue(resp.body().contains("petstore"), "expected petstore 
link on root: " + resp.body());
        }
 
diff --git 
a/juneau-rest/juneau-rest-server-view-freemarker/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
 
b/juneau-rest/juneau-rest-server-view-freemarker/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
index 1132481709..f78ab2babb 100644
--- 
a/juneau-rest/juneau-rest-server-view-freemarker/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
+++ 
b/juneau-rest/juneau-rest-server-view-freemarker/src/test/java/org/apache/juneau/rest/server/view/freemarker/FreemarkerMixin_PathTraversal_Test.java
@@ -76,7 +76,7 @@ class FreemarkerMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {
diff --git 
a/juneau-rest/juneau-rest-server-view-jsp/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
 
b/juneau-rest/juneau-rest-server-view-jsp/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
index 66a0a5d736..8ff78e6500 100644
--- 
a/juneau-rest/juneau-rest-server-view-jsp/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
+++ 
b/juneau-rest/juneau-rest-server-view-jsp/src/test/java/org/apache/juneau/rest/server/view/jsp/JspMixin_PathTraversal_Test.java
@@ -83,7 +83,7 @@ class JspMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {
diff --git 
a/juneau-rest/juneau-rest-server-view-mustache/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
 
b/juneau-rest/juneau-rest-server-view-mustache/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
index e03dab4d15..57daf92e4d 100644
--- 
a/juneau-rest/juneau-rest-server-view-mustache/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
+++ 
b/juneau-rest/juneau-rest-server-view-mustache/src/test/java/org/apache/juneau/rest/server/view/mustache/MustacheMixin_PathTraversal_Test.java
@@ -70,7 +70,7 @@ class MustacheMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {
diff --git 
a/juneau-rest/juneau-rest-server-view-thymeleaf/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
 
b/juneau-rest/juneau-rest-server-view-thymeleaf/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
index 2ca110ee40..d4a8399f68 100644
--- 
a/juneau-rest/juneau-rest-server-view-thymeleaf/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
+++ 
b/juneau-rest/juneau-rest-server-view-thymeleaf/src/test/java/org/apache/juneau/rest/server/view/thymeleaf/ThymeleafMixin_PathTraversal_Test.java
@@ -66,7 +66,7 @@ class ThymeleafMixin_PathTraversal_Test extends TestBase {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // CWE-22: direct .. traversal of basePath returns 403
+       // direct .. traversal of basePath returns 403
        
//-----------------------------------------------------------------------------------------------------------------
 
        @Test void t02_directTraversal_returns403() throws Exception {

Reply via email to