Skip to content

Commit 5903f44

Browse files
committed
HV-1773 Be more explicit about issues with EL injection and how to avoid them
1 parent 6702a5e commit 5903f44

File tree

3 files changed

+97
-7
lines changed

3 files changed

+97
-7
lines changed

Diff for: documentation/src/main/asciidoc/ch06.asciidoc

+23-7
Original file line numberDiff line numberDiff line change
@@ -173,18 +173,34 @@ It is important to add each configured constraint violation by calling `addConst
173173
Only after that the new constraint violation will be created.
174174
====
175175

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

190206
Refer to <<section-custom-property-paths>> to learn how to use the `ConstraintValidatorContext` API to
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.hibernate.validator.referenceguide.chapter06.elinjection;
2+
3+
import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext;
4+
import org.hibernate.validator.referenceguide.chapter06.constraintvalidatorpayload.ZipCode;
5+
6+
import javax.validation.ConstraintValidator;
7+
import javax.validation.ConstraintValidatorContext;
8+
9+
//tag::include[]
10+
public class SafeValidator implements ConstraintValidator<ZipCode, String> {
11+
12+
@Override
13+
public boolean isValid(String value, ConstraintValidatorContext context) {
14+
if ( value == null ) {
15+
return true;
16+
}
17+
18+
HibernateConstraintValidatorContext hibernateContext = context.unwrap(
19+
HibernateConstraintValidatorContext.class );
20+
hibernateContext.disableDefaultConstraintViolation();
21+
22+
if ( isInvalid( value ) ) {
23+
hibernateContext
24+
.addExpressionVariable( "validatedValue", value )
25+
.buildConstraintViolationWithTemplate( "${validatedValue} is not a valid ZIP code" )
26+
.addConstraintViolation();
27+
28+
return false;
29+
}
30+
31+
return true;
32+
}
33+
34+
private boolean isInvalid(String value) {
35+
// ...
36+
return false;
37+
}
38+
}
39+
// end::include[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.hibernate.validator.referenceguide.chapter06.elinjection;
2+
3+
import org.hibernate.validator.referenceguide.chapter06.constraintvalidatorpayload.ZipCode;
4+
5+
import javax.validation.ConstraintValidator;
6+
import javax.validation.ConstraintValidatorContext;
7+
8+
//tag::include[]
9+
public class UnsafeValidator implements ConstraintValidator<ZipCode, String> {
10+
11+
@Override
12+
public boolean isValid(String value, ConstraintValidatorContext context) {
13+
if ( value == null ) {
14+
return true;
15+
}
16+
17+
context.disableDefaultConstraintViolation();
18+
19+
if ( isInvalid( value ) ) {
20+
context
21+
.buildConstraintViolationWithTemplate( value + " is not a valid ZIP code" )
22+
.addConstraintViolation();
23+
24+
return false;
25+
}
26+
27+
return true;
28+
}
29+
30+
private boolean isInvalid(String value) {
31+
// ...
32+
return false;
33+
}
34+
}
35+
// end::include[]

0 commit comments

Comments
 (0)