Skip to content

Commit

Permalink
HV-1773 Be more explicit about issues with EL injection and how to av…
Browse files Browse the repository at this point in the history
…oid them
  • Loading branch information
gsmet committed Apr 30, 2020
1 parent 6702a5e commit 5903f44
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 7 deletions.
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[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 javax.validation.ConstraintValidator;
import javax.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 javax.validation.ConstraintValidator;
import javax.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[]

0 comments on commit 5903f44

Please sign in to comment.