java.lang.Object
java.lang.Record
de.cuioss.http.security.validation.NormalizationStage
- Record Components:
config- Security configuration controlling validation behavior.validationType- Type of validation being performed (URL_PATH, PARAMETER_NAME, etc.).
- All Implemented Interfaces:
HttpSecurityValidator
public record NormalizationStage(SecurityConfiguration config, ValidationType validationType)
extends Record
implements HttpSecurityValidator
Path normalization validation stage with security checks.
This stage performs RFC 3986 Section 5.2.4 path normalization to resolve relative path segments (. and ..) while detecting and preventing path traversal attacks. The stage processes paths through multiple security layers:
- Segment Parsing - Splits path into segments for processing
- Normalization - Resolves . and .. segments according to RFC 3986
- Security Validation - Detects remaining traversal attempts
- Root Escape Detection - Prevents escaping application root
Design Principles
- RFC Compliance - Follows RFC 3986 path normalization rules
- Security First - Detects attacks through normalization analysis
- DoS Protection - Prevents excessive nesting and recursion attacks
- Thread Safety - Safe for concurrent use across multiple threads
Security Validations
- Path Traversal - Detects ../ patterns that remain after normalization
- Root Escape - Prevents paths from escaping the application root
- Excessive Nesting - Limits path depth to prevent resource exhaustion
- Malicious Patterns - Identifies suspicious path construction
Usage Examples
// Create normalization stage
SecurityConfiguration config = SecurityConfiguration.defaults();
NormalizationStage normalizer = new NormalizationStage(config, ValidationType.URL_PATH);
// Normalize legitimate path
String normalized = normalizer.validate("/api/users/./123/../456");
// Returns: "/api/users/456"
// Detect path traversal attack
try {
normalizer.validate("/api/../../etc/passwd");
// Throws UrlSecurityException with DIRECTORY_ESCAPE_ATTEMPT
} catch (UrlSecurityException e) {
logger.warn("Path traversal blocked: {}", e.getFailureType());
}
// Detect excessive nesting attack
try {
normalizer.validate("/a/../b/../c/../d/../e/../f/../g/../h/../i/../j/../k/../l/../m/../n/../o/../p/../q/../r/../s/../t");
// Throws UrlSecurityException with EXCESSIVE_NESTING
} catch (UrlSecurityException e) {
logger.warn("DoS attack blocked: {}", e.getFailureType());
}
Performance Characteristics
- O(n) time complexity where n is the number of path segments
- Single pass through path segments with early termination
- Minimal memory allocation - reuses StringBuilder
- DoS protection through segment counting
RFC 3986 Compliance
This implementation follows RFC 3986 Section 5.2.4 "Remove Dot Segments":
- Single dot segments (.) are removed
- Double dot segments (..) remove the previous segment
- Trailing slashes are preserved
- Leading slashes are preserved
Implements: Task V2 from HTTP verification specification
- Since:
- 1.0
- See Also:
-
Constructor Summary
ConstructorsConstructorDescriptionNormalizationStage(SecurityConfiguration config, ValidationType validationType) Creates an instance of aNormalizationStagerecord class. -
Method Summary
Modifier and TypeMethodDescriptionconfig()Returns the value of theconfigrecord component.final booleanIndicates whether some other object is "equal to" this one.final inthashCode()Returns a hash code value for this object.final StringtoString()Returns a string representation of this record class.Validates and normalizes a path with comprehensive security checks.Returns the value of thevalidationTyperecord component.Creates a conditional validator that only processes inputs matching the condition.Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, waitMethods inherited from interface de.cuioss.http.security.core.HttpSecurityValidator
andThen, compose
-
Constructor Details
-
NormalizationStage
Creates an instance of aNormalizationStagerecord class.- Parameters:
config- the value for theconfigrecord componentvalidationType- the value for thevalidationTyperecord component
-
-
Method Details
-
validate
Validates and normalizes a path with comprehensive security checks.Processing stages:
- Input validation - handles null/empty inputs
- Path segment parsing - splits on directory separators
- RFC 3986 normalization - resolves . and .. segments
- Security validation - detects remaining attack patterns
- Specified by:
validatein interfaceHttpSecurityValidator- Parameters:
value- The input path to validate and normalize- Returns:
- The validated and normalized path wrapped in Optional, or Optional.empty() if input was null
- Throws:
UrlSecurityException- if any security violations are detected:- EXCESSIVE_NESTING - if path contains too many segments or depth
- PATH_TRAVERSAL_DETECTED - if ../ patterns remain after normalization
- DIRECTORY_ESCAPE_ATTEMPT - if normalized path tries to escape root
-
when
Creates a conditional validator that only processes inputs matching the condition.- Specified by:
whenin interfaceHttpSecurityValidator- Parameters:
condition- The condition to test before validation- Returns:
- A conditional HttpSecurityValidator that applies normalization conditionally
-
toString
Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components. -
hashCode
Returns a hash code value for this object. The value is derived from the hash code of each of the record components. -
equals
Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. All components in this record class are compared withObjects::equals(Object,Object). -
config
Returns the value of theconfigrecord component.- Returns:
- the value of the
configrecord component
-
validationType
Returns the value of thevalidationTyperecord component.- Returns:
- the value of the
validationTyperecord component
-