You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »

Status: DRAFT

Java 17

From this version of Struts, the framework requires Java 17 at least to run

Jakarta Servlet API 6

Struts 7.x.x requires a servlet container which supports Jakarta Servlet API 6 at least, it won't work with older versions.

Stronger security

A number of breaking changes have been made so that the default behaviour of the Struts framework is more predictable and/or more secure. Many of these measures were developed in direct response to real exploits and common critical developer errors.

Please read the following sections carefully so that you can make informed decisions about the security standing of your application when migrating to Struts 7.0.

Namespace resolution

The default values for the following namespace mapping options have changed to the more sensible behaviour of requiring exact matches. This prevents Actions being accessed from more namespaces than intended.

If your application contains links to Actions using non-exact namespaces, when migrating to Struts 7.0 you should update these links to use the exact namespace, or update the Action definition to the desired namespace.

However, if you prefer the previous behaviour, you may revert these options in your application configuration. If you choose to do this, consider whether you have any request path matching code in your application as it is important that these alternative access endpoints are accounted for to prevent unintended code bypasses.

struts.mapper.alwaysSelectFullNamespace=true
struts.actionConfig.fallbackToEmptyNamespace=false

Static field and custom map access

In a previous version of Struts, the ability to execute static methods was removed as it could be used to execute arbitrary methods in the case of an OGNL exploit. Static fields present similar risks as they could be of any type with arbitrary attached methods. As such, from Struts 7.0, static field access will be disabled by default.

If your product relies on static field access, when upgrading to Struts 7.0, the simplest migration path you take will depend on your specific needs. You may copy such field values directly into the classes that require them. Or you may copy these field values into a helper/utility class which you can then reference from your desired Actions, or add it to the OGNL context.

You may disable this restriction by reverting the following configuration option but we advise against it.

struts.ognl.allowStaticFieldAccess=false

It is possible to instantiate arbitrary map classes directly from OGNL expressions. This capability can also be used to craft exploit payloads. As such, in Struts 7.0, only the following map types can be instantiated from OGNL expressions:

  • java.util.HashMap
  • java.util.TreeMap
  • java.util.LinkedHashMap

You may disable this restriction by reverting the following configuration option but we highly advise against it.

struts.ognl.disallowCustomOgnlMap=true

OGNL expression max length

Enforcing an OGNL expression max length prevents attackers from crafting creative exploit payloads. This limit has been reduced from 200 to 150 in order to further hinder such exploit attempts.

After upgrading to Struts 7.0, if you notice log errors relating to the OGNL expression length, you should find the source of these expressions using a debugger or otherwise. One the source has been identified, you should attempt to move this logic to Java code instead, and potentially provide a variable from which the OGNL expression can retrieve the pre-computed value.

As an example, if your application is logging errors when executing XML validator files, you may have a particularly long OGNL based validation rule. If this expression cannot be simplified, we recommend moving this validation logic to Java code instead, by implementing the com.opensymphony.xwork2.Validateable interface on your Action.

You may use the following configuration option to increase the expression max length if you are unable to workaround your application issues.

struts.ognl.expressionMaxLength=150

Action parameter injection

Struts has traditionally allowed injecting user/request parameters via ANY public setter and/or getter on an Action class. However, this created situations where a developer may introduce a new setter/getter for an unrelated purpose but instead inadvertently introduce a new parameter injection point. There was even a long-standing issue in Struts ActionSupport itself where users could directly modify Action-internal error state (ref). These unintended parameter injection points have the potential to cause critical vulnerabilities.

As such, all parameter injection points must be explicitly marked with the new @StrutsParameter annotation. Please refer to the official documentation for further details on how this annotation works and should be used: Defining and annotating your Action parameters.

When upgrading to Struts 7.0, adding the necessary annotations to all setter methods can be scripted using a RegEx find and replace on all files matching *Action.java.

Find: \n(\h*public void set[A-Z]\w*\((long|Long|int|Integer|String|double|Double|Object|Number|Char|char|Float|float|List|Collection|Set|Date|LocalDateTime|Calendar))

Replace: \n    @StrutsParameter\n$1

Example using IntelliJ:

We then recommend quickly reviewing all newly annotated methods to check that your application wasn't previously exposing a method that was not intended for parameter injection.

To identify all getter methods eligible for parameter injection, you may search for the following RegEx on files matching *Action.java.

Find: public (?!(long|Long|int|Integer|String|double|Double|Number|Char|char|Float|float|Date|LocalDateTime|Calendar)\b)[\w<>\.]+ get[A-Z]\w*\(\)

These matches should be reviewed on a case by case basis. If the return type is intended for parameter injection, add the annotation to the method with an appropriate depth limit. Please refer to the aforementioned official documentation for details on selecting the depth limit.

You may disable this annotation requirement entirely by reverting the following configuration option but we highly advise against it.

struts.parameters.requireAnnotations=true

OGNL proxied object access

Access to proxied objects, specifically Spring beans and Hibernate entities, from OGNL expressions has been restricted. In the case of an exploit (usually a server-side template injection), access to such objects can be used to escalate the severity by modifying application state or database records.

If your application relies on invoking Spring bean methods directly via OGNL, you should create new methods on your Action class that calls the desired methods instead. You may then call these new Actions methods from your expressions rather than invoking the Spring bean directly.

If your application relies on accessing Hibernate entities via OGNL, we recommend introducing an intermediary layer which provides proper separation between your persistence layer and view layer.

If you are unable to implement appropriate remediations, you may disable this restriction by reverting the following configuration option but we advise against it.

struts.disallowProxyObjectAccess=true

The OGNL allowlist capability will currently not work when proxy object access is restored. Please see the later section on also disabling the allowlist if necessary. There is some work in progress (WW-5428) to allow the allowlist capability to continue functioning with an exemption for Hibernate entities so that such applications can still obtain some security benefit from the allowlist.

Access to objects defined in the default (or empty) package has also been disallowed. This prevents the usage of classes not intended for production use as well as miscellaneous other proxied objects.

You may disable this restriction by reverting the following configuration option but we advise against it.

struts.disallowDefaultPackageAccess=true

OGNL allowlist capability

The OGNL allowlist offers the strongest protection against critical exploits, such as those caused by double evaluations in the past. It succeeds the exclusion list as it does not require developers to maintain a list of potentially dangerous classes. Instead, we only allow OGNL expressions to access the minimal classes required for your Struts application to function.

Most applications will not need any additional configuration when the allowlist is enabled, especially if you have completed the aforementioned migration steps for Action parameter injection. However, some applications will need to manually allowlist the classes or packages for the POJO/DTOs used for user/request parameter injection and template rendering.

If you are unsure of what these classes/packages may be, the simplest way to determine them are to start your application with the allowlist capability enabled, then view some actions and submit some forms. If the log output contains errors stating that certain classes have not been allowlisted, you should add them to the allowlist. If the log error refers to a class which is indeed a POJO/DTO and belongs to a package of more POJO/DTOs, simply allowlist the whole package; otherwise, allowlist just that specific class.

struts.allowlist.packageNames=
struts.allowlist.classes=

You may disable the allowlist capability entirely by reverting the following configuration option but we highly advise against it.

struts.allowlist.enable=true

New constants

Constant nameDescription




Deprecated interfaces

A set of action related interfaces have been marked as deprecated. These interfaces have a new proper versions in another package, please start using the new versions as the depretacted interfaces will be removed with the next major release.

DeprecatedNew version




















File upload support


Temp/Work directory of ApplicationServer/ServletContainer

Users reported it was necessary for them to remove temp/work directory of their ApplicationServer/ServletContainer. Likely to force server to recompile JSPs.


  • No labels