CVE-2006-1546Apache Software Foundation (ASF) Struts before 1.2.9 allows remote attackers to bypass validation via a request with a 'org.apache.struts.taglib.html.Constants.CANCEL' parameter, which causes the action to be canceled but would not be detected from applications that do not use the isCancelled check.
CWE-20 · Improper input validation
No public exploit
Nothing published shows this CVE being exploited, which is not the same as ruling it out. nothing published in 20 years.
CVSS E:U
A Waratek agent blocks this today.
Applicable rule: CVE has an ARMR patch rule that provides mitigation
| Decided by | armr-patch-file : An ARMR patch file on disk for this CVE |
|---|---|
| Finding | CVE has an ARMR patch rule that provides mitigation |
Shipped files covering this CVE. A CVE genuinely takes more than one: separate Maven artifacts hooking different parser classes, the same patch built for two ARMR versions, or a fix at both the framework and the container.
rules/frameworks/apache/struts/CVE-2006-1546/patch/2.6/CVE-2006-1546.armr patch rule added 2020-06-25 updated 2026-03-04app("APACHE STRUTS"):
requires(version: "ARMR/2.6")
/***************************************************************************
CVE-2006-1546 (APACHE STRUTS)
CVSS 2.0 Summary:
Base Score | 7.5
Attack Vector | Network
Attack Complexity | Low
Authentication Required | None
Confidentiality | Partial
Integrity | Partial
Availability | Partial
Description:
Apache Software Foundation (ASF) Struts before 1.2.9 allows remote
attackers to bypass validation via a request with a
'org.apache.struts.taglib.html.Constants.CANCEL' parameter, which
causes the action to be canceled but would not be detected from
applications that do not use the isCancelled check.
Resources:
https://nvd.nist.gov/vuln/detail/CVE-2006-1546
https://github.com/apache/struts1/commit/f126bcf14
https://github.com/apache/struts1/commit/8318351d5
Affected Operating Systems:
Any
Affected Versions:
Apache Struts: 1.2.8
Tested Versions:
1.2.8
Protection Provided:
Functional (default), Alerting (set 'IS_CANCELLABLE = true')
Patch Version:
1.1
***************************************************************************/
patch("CVE-2006-1546 :01"):
function("org/apache/struts/action/RequestProcessor.process(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V",
checksums: ["3296f7f124", // MavenCentral: 1.2.8
"01534bd660"]) // github-branch: 1.2.8
call("org/apache/struts/action/RequestProcessor.processValidate(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Lorg/apache/struts/action/ActionForm;Lorg/apache/struts/action/ActionMapping;)Z")
code(language: java, import: ["java.io.IOException",
"javax.servlet.ServletException"]):
private static final String INVALID_CANCEL_EXCEPTION = "InvalidCancelException";
private static JavaMethod processValidateMethod;
private static JavaMethod processExceptionMethod;
private static JavaMethod processForwardConfigMethod;
public void load() {
processValidateMethod = JavaMethod.load(
"org/apache/struts/action/RequestProcessor.processValidate(" +
"Ljavax/servlet/http/HttpServletRequest;" +
"Ljavax/servlet/http/HttpServletResponse;"+
"Lorg/apache/struts/action/ActionForm;" +
"Lorg/apache/struts/action/ActionMapping;" +
")Z");
processExceptionMethod = JavaMethod.load(
"org/apache/struts/action/RequestProcessor.processException(" +
"Ljavax/servlet/http/HttpServletRequest;" +
"Ljavax/servlet/http/HttpServletResponse;" +
"Ljava/lang/Exception;" +
"Lorg/apache/struts/action/ActionForm;" +
"Lorg/apache/struts/action/ActionMapping;" +
")Lorg/apache/struts/action/ActionForward;");
processForwardConfigMethod = JavaMethod.load(
"org/apache/struts/action/RequestProcessor.processForwardConfig(" +
"Ljavax/servlet/http/HttpServletRequest;" +
"Ljavax/servlet/http/HttpServletResponse;" +
"Lorg/apache/struts/config/ForwardConfig;" +
")V");
}
public void patch(JavaFrame frame) throws Throwable {
Object self = frame.loadThisVariable();
Object request = frame.loadObjectVariable(1);
Object response = frame.loadObjectVariable(2);
Object form = frame.loadObjectVariable(5);
Object mapping = frame.loadObjectVariable(4);
try {
if (!processValidate(self, request, response, form, mapping)) {
frame.returnVoid();
return;
}
} catch (Throwable e) {
String exceptionClassName = e.getClass().getSimpleName();
if (INVALID_CANCEL_EXCEPTION.equals(exceptionClassName)) {
Object forward = processExceptionMethod.call(self, request, response, e, form, mapping);
processForwardConfigMethod.call(self, request, response, forward);
frame.returnVoid();
return;
}
frame.raiseException(e);
return;
}
frame.storeBooleanOperand(0, true);
}
private boolean processValidate(Object self, Object request,
Object response, Object form,
Object mapping) throws Throwable {
return (Boolean) processValidateMethod.call(self, request, response, form, mapping);
}
endcode
endpatch
// This patch is taken from: https://github.com/apache/struts1/commit/8318351d5
patch("CVE-2006-1546 :02"):
function("org/apache/struts/action/RequestProcessor.processValidate(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Lorg/apache/struts/action/ActionForm;Lorg/apache/struts/action/ActionMapping;)Z",
checksums: ["3296f7f124", // MavenCentral: 1.2.8
"01534bd660"]) // github-branch: 1.2.8
callsite("javax/servlet/ServletRequest.getAttribute(Ljava/lang/String;)Ljava/lang/Object;")
code(language: java):
private static JavaMethod getValidateMethod;
public void load() {
getValidateMethod =
JavaMethod.load("org/apache/struts/config/ActionConfig.getValidate()Z");
}
public void patch(JavaFrame frame) {
Object mapping = frame.loadObjectVariable(4);
boolean validate = (Boolean) getValidateMethod.call(mapping);
if (!validate) {
frame.returnBoolean(true);
}
}
endcode
endpatch
patch("CVE-2006-1546 :03"):
function("org/apache/struts/action/RequestProcessor.processValidate(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;Lorg/apache/struts/action/ActionForm;Lorg/apache/struts/action/ActionMapping;)Z",
checksums: ["3296f7f124", // MavenCentral: 1.2.8
"01534bd660"]) // github-branch: 1.2.8
callreturn("javax/servlet/ServletRequest.getAttribute(Ljava/lang/String;)Ljava/lang/Object;")
code(language: java, import: ["org.apache.struts.Globals"]):
// IMPORTANT: CUSTOMER CONFIGURATION REQUIRED
// Was this request cancelled? If it has been, application owner
// needs to state whether the cancellation is permissible, otherwise
// the cancellation is considered to be a symptom of a programmer
// error or a spoof. By default, when an Action is cancelled,
// validation is bypassed and the Action should not execute the
// business operation. If a request tries to cancel an Action when
// IS_CANCELLABLE is false, an "InvalidCancelException" is thrown.
private static final boolean IS_CANCELLABLE = false;
private static JavaMethod removeAttributeMethod;
private static JavaMethod getRequestUriMethod;
public void load() {
removeAttributeMethod =
JavaMethod.load("javax/servlet/ServletRequest.removeAttribute(Ljava/lang/String;)V");
getRequestUriMethod =
JavaMethod.load("javax/servlet/http/HttpServletRequest.getRequestUri()Ljava/lang/String;");
}
public void patch(JavaFrame frame) {
Object getAttributeReturnValue = frame.loadObjectOperand(0);
if (getAttributeReturnValue == null) {
return;
}
if (IS_CANCELLABLE) {
ArmrEvent event = ArmrEvent.load("Execute Rule", "high");
event.addExtension("msg", "Cancelled transaction, skipping validation");
event.addExtension("act", "allow");
event.commit();
frame.returnBoolean(true);
return;
} else {
Object request = frame.loadObjectVariable(1);
removeAttributeMethod.call(request, Globals.CANCEL_KEY);
frame.raiseException(new InvalidCancelException());
}
}
private static class InvalidCancelException extends Exception {
public InvalidCancelException() {
super();
}
public InvalidCancelException(String message) {
super(message);
}
}
endcode
endpatch
endapp
AV:N/AC:L/Au:N/C:P/I:P/A:P
1 metric
VRT selects the newest version's highest entry and
publishes it as cvssScore, newest rather than largest because scores are not comparable
across versions, and highest rather than first because the first entry is frequently a CNA placeholder
scoring 0.0 over NVD's own analysis.
| Version | Score | Band | Vector | Assigner | Type | |
|---|---|---|---|---|---|---|
| CVSS 2.0 | 7.5 | no band published | AV:N/AC:L/Au:N/C:P/I:P/A:P |
NVD | Primary | published |
| Package Coordinate | Introduced | Fixed | Last affected |
|---|---|---|---|
struts:struts |
0 | 1.2.9 |
unbounded |
| Published | 2006-03-30 | By the CVE Program. |
|---|---|---|
| ARMR remediation created | 2020-06-25 | Earliest commit adding this CVE's ARMR patch or security rule. |
| ARMR remediation last updated | 2026-03-04 | Most recent commit touching this CVE's ARMR patch or security rule. |
| Last VRT activity | 2026-03-04 | Most recent commit touching this CVE's classification, patch or rule file. |
| NVD record modified | 2026-06-16 | NVD's own last-modified date for this record. |