This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts.git
The following commit(s) were added to refs/heads/main by this push:
new 572f3aaf6 chore: harden showcase apps and convert READMEs to Markdown
(#1624)
572f3aaf6 is described below
commit 572f3aaf693132d3c5665b47b0d3236bef1d3ef4
Author: Lukasz Lenart <[email protected]>
AuthorDate: Tue Mar 17 10:25:04 2026 +0100
chore: harden showcase apps and convert READMEs to Markdown (#1624)
- Add production deployment warnings to showcase and rest-showcase READMEs
- Convert README.txt to README.md with proper Markdown formatting
- Restrict ViewSourceAction config parameter to XML files within webapp path
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
apps/rest-showcase/README.md | 18 ++++++++++++
apps/rest-showcase/README.txt | 15 ----------
apps/showcase/README.md | 19 +++++++++++++
apps/showcase/README.txt | 16 -----------
.../struts2/showcase/source/ViewSourceAction.java | 33 ++++++++++++++++++++--
5 files changed, 68 insertions(+), 33 deletions(-)
diff --git a/apps/rest-showcase/README.md b/apps/rest-showcase/README.md
new file mode 100644
index 000000000..1437ea14f
--- /dev/null
+++ b/apps/rest-showcase/README.md
@@ -0,0 +1,18 @@
+# Rest Showcase
+
+> **WARNING:** This application is a demonstration/development tool only. It
is **NOT** intended for production
+> deployment. Deploying this application on a publicly accessible server may
pose security risks.
+
+Rest Showcase is a simple example of a REST app built with the REST plugin.
+
+For more on getting started with Struts, see:
+
+- https://struts.apache.org/getting-started/
+
+## I18N
+
+Please note that this project was created with the assumption that it will be
run in an environment where the default
+locale is set to English. This means that the default messages defined in
`package.properties` are in English.
+
+If the default locale for your server is different, then rename
`package.properties` to `package_en.properties` and
+create a new `package.properties` with proper values for your default locale.
diff --git a/apps/rest-showcase/README.txt b/apps/rest-showcase/README.txt
deleted file mode 100644
index 13f133be8..000000000
--- a/apps/rest-showcase/README.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-README.txt - Rest Showcase Webapp
-
-Rest Showcase is a simple example of REST app build with the REST plugin.
-
-For more on getting started with Struts, see
-
-* http://cwiki.apache.org/WW/home.html
-
-I18N:
-=====
-Please note that this project was created with the assumption that it will be
run
-in an environment where the default locale is set to English. This means that
-the default messages defined in package.properties are in English. If the
default
-locale for your server is different, then rename package.properties to
package_en.properties
-and create a new package.properties with proper values for your default locale.
diff --git a/apps/showcase/README.md b/apps/showcase/README.md
new file mode 100644
index 000000000..4d7bc6e84
--- /dev/null
+++ b/apps/showcase/README.md
@@ -0,0 +1,19 @@
+# Showcase
+
+> **WARNING:** This application is a demonstration/development tool only. It
is **NOT** intended for production
+> deployment. It contains features such as source code viewing that
intentionally expose internal application details.
+> Deploying this application on a publicly accessible server may pose security
risks.
+
+Showcase is a collection of examples with code that you might adopt and adapt
in your own applications.
+
+For more on getting started with Struts, see:
+
+- https://struts.apache.org/getting-started/
+
+## I18N
+
+Please note that this project was created with the assumption that it will be
run in an environment where the default
+locale is set to English. This means that the default messages defined in
`package.properties` are in English.
+
+If the default locale for your server is different, then rename
`package.properties` to `package_en.properties` and
+create a new `package.properties` with proper values for your default locale.
diff --git a/apps/showcase/README.txt b/apps/showcase/README.txt
deleted file mode 100644
index 8e6cbb03c..000000000
--- a/apps/showcase/README.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-README.txt - showcase
-
-Showcase is a collection of examples with code that you might be adopt and
-adapt in your own applications.
-
-For more on getting started with Struts, see
-
-* http://cwiki.apache.org/WW/home.html
-
-I18N:
-=====
-Please note that this project was created with the assumption that it will be
run
-in an environment where the default locale is set to English. This means that
-the default messages defined in package.properties are in English. If the
default
-locale for your server is different, then rename package.properties to
package_en.properties
-and create a new package.properties with proper values for your default locale.
diff --git
a/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java
b/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java
index 2cd4b5a1b..9881d355a 100644
---
a/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java
+++
b/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java
@@ -30,7 +30,9 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.net.URL;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@@ -90,7 +92,11 @@ public class ViewSourceAction extends ActionSupport
implements ServletContextAwa
if (config != null && config.startsWith("file:/")) {
int pos = config.lastIndexOf(':');
configLine = Integer.parseInt(config.substring(pos + 1));
- configLines = read(new URL(config.substring(0, pos)).openStream(),
configLine);
+ String fileUrl = config.substring(0, pos);
+ Path configPath = resolveAllowedConfigPath(fileUrl);
+ if (configPath != null) {
+ configLines = read(Files.newInputStream(configPath),
configLine);
+ }
}
return SUCCESS;
}
@@ -227,6 +233,29 @@ public class ViewSourceAction extends ActionSupport
implements ServletContextAwa
return snippet;
}
+ /**
+ * Resolves the given file URL to a real path if it points to an XML file
within the webapp's
+ * deployment directory, preventing arbitrary file reads via crafted
config parameters.
+ *
+ * @return the resolved path if allowed, or null if the path is outside
the webapp or not an XML file
+ */
+ private Path resolveAllowedConfigPath(String fileUrl) {
+ try {
+ Path filePath = Path.of(new URI(fileUrl)).toRealPath();
+ String realBasePath = servletContext.getRealPath("/");
+ if (realBasePath == null) {
+ return null;
+ }
+ Path basePath = Path.of(realBasePath).toRealPath();
+ if (filePath.startsWith(basePath) &&
filePath.toString().endsWith(".xml")) {
+ return filePath;
+ }
+ return null;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
@Override
public void withServletContext(ServletContext arg0) {
this.servletContext = arg0;