Skip to content

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 minimum ActionForm
  • 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 ActionMessage with 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, range validators
  • 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.

Additional Resources