Skip to content

Commit 6e87474

Browse files
committed
Validates action, namespace and method in the same way
1 parent 9fcbd91 commit 6e87474

File tree

4 files changed

+150
-89
lines changed

4 files changed

+150
-89
lines changed

core/src/main/java/org/apache/struts2/StrutsConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,11 @@ public final class StrutsConstants {
282282

283283
public static final String STRUTS_EXPRESSION_PARSER = "struts.expression.parser";
284284

285+
/** namespaces names' whitelist **/
286+
public static final String STRUTS_ALLOWED_NAMESPACE_NAMES = "struts.allowed.namespace.names";
287+
/** default namespace name to use when namespace didn't match the whitelist **/
288+
public static final String STRUTS_DEFAULT_NAMESPACE_NAME = "struts.default.namespace.name";
289+
285290
/** actions names' whitelist **/
286291
public static final String STRUTS_ALLOWED_ACTION_NAMES = "struts.allowed.action.names";
287292
/** default action name to use when action didn't match the whitelist **/

core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.apache.struts2.RequestUtils;
3232
import org.apache.struts2.ServletActionContext;
3333
import org.apache.struts2.StrutsConstants;
34-
import org.apache.struts2.StrutsException;
3534
import org.apache.struts2.util.PrefixTrie;
3635

3736
import javax.servlet.http.HttpServletRequest;
@@ -117,6 +116,10 @@ public class DefaultActionMapper implements ActionMapper {
117116
protected boolean allowSlashesInActionNames = false;
118117
protected boolean alwaysSelectFullNamespace = false;
119118
protected PrefixTrie prefixTrie = null;
119+
120+
protected Pattern allowedNamespaceNames = Pattern.compile("[a-zA-Z0-9._/\\-]*");
121+
protected String defaultNamespaceName = "/";
122+
120123
protected Pattern allowedActionNames = Pattern.compile("[a-zA-Z0-9._!/\\-]*");
121124
protected String defaultActionName = "index";
122125

@@ -202,6 +205,16 @@ public void setAlwaysSelectFullNamespace(String alwaysSelectFullNamespace) {
202205
this.alwaysSelectFullNamespace = BooleanUtils.toBoolean(alwaysSelectFullNamespace);
203206
}
204207

208+
@Inject(value = StrutsConstants.STRUTS_ALLOWED_NAMESPACE_NAMES, required = false)
209+
public void setAllowedNamespaceNames(String allowedNamespaceNames) {
210+
this.allowedNamespaceNames = Pattern.compile(allowedNamespaceNames);
211+
}
212+
213+
@Inject(value = StrutsConstants.STRUTS_DEFAULT_NAMESPACE_NAME, required = false)
214+
public void setDefaultNamespaceName(String defaultNamespaceName) {
215+
this.defaultNamespaceName = defaultNamespaceName;
216+
}
217+
205218
@Inject(value = StrutsConstants.STRUTS_ALLOWED_ACTION_NAMES, required = false)
206219
public void setAllowedActionNames(String allowedActionNames) {
207220
this.allowedActionNames = Pattern.compile(allowedActionNames);
@@ -389,10 +402,28 @@ protected void parseNameAndNamespace(String uri, ActionMapping mapping, Configur
389402
}
390403
}
391404

392-
mapping.setNamespace(namespace);
405+
mapping.setNamespace(cleanupNamespaceName(namespace));
393406
mapping.setName(cleanupActionName(name));
394407
}
395408

409+
/**
410+
* Checks namespace name against allowed pattern if not matched returns default namespace
411+
*
412+
* @param rawNamespace name extracted from URI
413+
* @return safe namespace name
414+
*/
415+
protected String cleanupNamespaceName(final String rawNamespace) {
416+
if (allowedNamespaceNames.matcher(rawNamespace).matches()) {
417+
return rawNamespace;
418+
} else {
419+
LOG.warn(
420+
"{} did not match allowed namespace names {} - default namespace {} will be used!",
421+
rawNamespace, allowedActionNames, defaultActionName
422+
);
423+
return defaultNamespaceName;
424+
}
425+
}
426+
396427
/**
397428
* Checks action name against allowed pattern if not matched returns default action name
398429
*

0 commit comments

Comments
 (0)