Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions documentation/src/main/asciidoc/ch06.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -173,18 +173,34 @@ It is important to add each configured constraint violation by calling `addConst
Only after that the new constraint violation will be created.
====

[WARNING]
[[el-injection-caution]]
[CAUTION]
====
Note that the custom message template is passed directly to the Expression Language engine.
**Be aware that the custom message template is passed directly to the Expression Language engine.**
Thus, you should be very careful when integrating user input in a custom message template as it will be interpreted
by the Expression Language engine, which is usually not the behavior you expect and could allow malicious users to leak
sensitive data.
by the Expression Language engine, which is usually not the behavior you want and **could allow malicious users to leak
sensitive data or even execute arbitrary code**.
If you need to integrate user input in your message, you must <<section-hibernateconstraintvalidatorcontext,pass it as an expression variable>>
by unwrapping the context to `HibernateConstraintValidatorContext`.
The following validator is very unsafe as it includes user input in the violation message.
If the validated `value` contains EL expressions, they will be executed by the EL engine.
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java[tags=include]
----
The following pattern must be used instead:
If you need to integrate user input, you should:
[source]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java[tags=include]
----
* either escape it by using the http://beanvalidation.org/2.0/spec/#validationapi-message-defaultmessageinterpolation[Jakarta Bean Validation message interpolation escaping rules];
* or, even better, <<section-hibernateconstraintvalidatorcontext,pass it as message parameters or expression variables>> by unwrapping the context to `HibernateConstraintValidatorContext`.
By using expression variables, Hibernate Validator properly handles escaping and EL expressions won't be executed.
====

Refer to <<section-custom-property-paths>> to learn how to use the `ConstraintValidatorContext` API to
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.hibernate.validator.referenceguide.chapter06.elinjection;

import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext;
import org.hibernate.validator.referenceguide.chapter06.constraintvalidatorpayload.ZipCode;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

//tag::include[]
public class SafeValidator implements ConstraintValidator<ZipCode, String> {

@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if ( value == null ) {
return true;
}

HibernateConstraintValidatorContext hibernateContext = context.unwrap(
HibernateConstraintValidatorContext.class );
hibernateContext.disableDefaultConstraintViolation();

if ( isInvalid( value ) ) {
hibernateContext
.addExpressionVariable( "validatedValue", value )
.buildConstraintViolationWithTemplate( "${validatedValue} is not a valid ZIP code" )
.addConstraintViolation();

return false;
}

return true;
}

private boolean isInvalid(String value) {
// ...
return false;
}
}
// end::include[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.hibernate.validator.referenceguide.chapter06.elinjection;

import org.hibernate.validator.referenceguide.chapter06.constraintvalidatorpayload.ZipCode;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

//tag::include[]
public class UnsafeValidator implements ConstraintValidator<ZipCode, String> {

@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if ( value == null ) {
return true;
}

context.disableDefaultConstraintViolation();

if ( isInvalid( value ) ) {
context
.buildConstraintViolationWithTemplate( value + " is not a valid ZIP code" )
.addConstraintViolation();

return false;
}

return true;
}

private boolean isInvalid(String value) {
// ...
return false;
}
}
// end::include[]