CWE-103: Struts: Incomplete validate() Method Definition
Overview
This vulnerability occurs when a Struts ActionForm's validate() method is not properly implemented or returns null, bypassing validation and allowing unvalidated user input to reach the application logic. This can lead to injection attacks, data integrity issues, and business logic bypasses.
OWASP Classification
A05:2025 - Injection
Risk
High: Missing or incomplete validation allows attackers to submit malicious or malformed data that can lead to SQL injection, XSS, or business logic exploitation. This undermines the security assumptions of the entire application.
Remediation Steps
Core principle: Ensure security requirements and mitigations are fully documented and enforced; undocumented security becomes insecure security.
Locate the Incomplete validate() Method
Review the security findings to identify which ActionForm class has an incomplete or missing validate() method:
- Check if the method returns null (bypasses all validation)
- Look for empty implementations or stub code
- Identify which form fields are not being validated
- Trace the data_path to understand how untrusted data flows through the application
Implement Complete validate() Method
Ensure the ActionForm properly extends a validation class and implements the validate() method:
- Extend the proper validation class: Use
ValidatorForm,DynaValidatorForm, or at minimumActionForm - Always return ActionErrors object: Never return null, even if there are no errors
- Validate all form fields: Check data type, length, format, and range for every field
- Return field-specific errors: Use
ActionMessagewith descriptive error keys
Add Declarative Validation Rules
Leverage the Struts Validator framework for common validation patterns:
- Create validation.xml configuration: Define validation rules for form fields
- Use built-in validators: Apply
required,email,minlength,maxlength,rangevalidators - Implement custom validators: Create validators for complex business rules
- Combine with programmatic validation: Override
validate()to add additional checks beyond declarative rules
Validate Against Allowlists
For fields with restricted value sets, use strict allowlist validation:
- Reject unexpected values: Only accept known-good values from a predefined list
- Validate enumerated types: Check dropdown selections, radio buttons against allowed options
- Use regular expressions: Validate format for usernames, emails, phone numbers
- Check business logic constraints: Enforce valid state transitions, numeric ranges
Apply Defense in Depth
Even with proper Struts validation, add additional security layers:
- Validate on both client and server: Client-side for UX, server-side for security
- Use parameterized queries: Prevent SQL injection in data access layer
- Apply output encoding: Encode data when rendering to prevent XSS
- Implement authorization checks: Verify user permissions before processing form data
Test the Validation
Verify the fix with both valid and malicious inputs:
- Test with normal data: Ensure legitimate users can submit forms
- Test with invalid data: Verify validation rejects malformed input (empty strings, wrong types, excessive length)
- Test with injection payloads: Try SQL injection (
' OR '1'='1), XSS (<script>alert(1)</script>) - Test edge cases: Boundary values, special characters, null values
Common Vulnerable Patterns
Returning null from validate() method
public class UserForm extends ActionForm {
private String username;
private String email;
// Dangerous: returns null, bypasses all validation
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
return null;
}
}
Why this is vulnerable:
- Empty or stub validate() implementations
- Missing validate() method entirely
- Validating only some fields while ignoring others
Secure Patterns
Implement complete validate() method
public class UserForm extends ActionForm {
private String username;
private String email;
// Proper validation implementation
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
// Validate username
if (username == null || username.trim().isEmpty()) {
errors.add("username", new ActionMessage("error.username.required"));
} else if (username.length() < 3 || username.length() > 20) {
errors.add("username", new ActionMessage("error.username.length"));
}
// Validate email
if (email == null || !email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
errors.add("email", new ActionMessage("error.email.invalid"));
}
return errors; // Always return ActionErrors object
}
}
Why this works: The validate() method returns an ActionErrors object (never null), performs explicit validation on all form fields (username and email), checks for common issues (null, empty, format), and returns field-specific errors that the Struts framework can display to users. This ensures no unvalidated data reaches the application logic.