Validation for entity's additionalInfo
This commit is contained in:
parent
6a75cd076f
commit
e7995fb02c
@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.thingsboard.server.common.data.id.UUIDBased;
|
import org.thingsboard.server.common.data.id.UUIDBased;
|
||||||
|
import org.thingsboard.server.common.data.validation.NoXss;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -36,6 +37,7 @@ import java.util.function.Consumer;
|
|||||||
public abstract class SearchTextBasedWithAdditionalInfo<I extends UUIDBased> extends SearchTextBased<I> implements HasAdditionalInfo {
|
public abstract class SearchTextBasedWithAdditionalInfo<I extends UUIDBased> extends SearchTextBased<I> implements HasAdditionalInfo {
|
||||||
|
|
||||||
public static final ObjectMapper mapper = new ObjectMapper();
|
public static final ObjectMapper mapper = new ObjectMapper();
|
||||||
|
@NoXss
|
||||||
private transient JsonNode additionalInfo;
|
private transient JsonNode additionalInfo;
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private byte[] additionalInfoBytes;
|
private byte[] additionalInfoBytes;
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.dao.service;
|
package org.thingsboard.server.dao.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.owasp.validator.html.AntiSamy;
|
import org.owasp.validator.html.AntiSamy;
|
||||||
import org.owasp.validator.html.Policy;
|
import org.owasp.validator.html.Policy;
|
||||||
@ -48,12 +49,18 @@ public class NoXssValidator implements ConstraintValidator<NoXss, Object> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
|
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
|
||||||
if (!(value instanceof String) || ((String) value).isEmpty()) {
|
String stringValue;
|
||||||
|
if (value instanceof CharSequence || value instanceof JsonNode) {
|
||||||
|
stringValue = value.toString();
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (stringValue.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return xssChecker.scan((String) value, xssPolicy).getNumberOfErrors() == 0;
|
return xssChecker.scan(stringValue, xssPolicy).getNumberOfErrors() == 0;
|
||||||
} catch (ScanException | PolicyException e) {
|
} catch (ScanException | PolicyException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,23 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.dao.service;
|
package org.thingsboard.server.dao.service;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import com.fasterxml.jackson.databind.node.TextNode;
|
||||||
|
import org.junit.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
|
import org.thingsboard.server.common.data.asset.Asset;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
public class NoXssValidatorTest {
|
public class NoXssValidatorTest {
|
||||||
private static NoXssValidator validator;
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void beforeAll() {
|
|
||||||
validator = new NoXssValidator();
|
|
||||||
validator.initialize(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(strings = {
|
@ValueSource(strings = {
|
||||||
@ -44,9 +37,25 @@ public class NoXssValidatorTest {
|
|||||||
" <img src= \"http://site.com/\" > ",
|
" <img src= \"http://site.com/\" > ",
|
||||||
"123 <input type=text value=a onfocus=alert(1337) AUTOFOCUS>bebe"
|
"123 <input type=text value=a onfocus=alert(1337) AUTOFOCUS>bebe"
|
||||||
})
|
})
|
||||||
public void testIsNotValid(String stringWithXss) {
|
public void givenEntityWithMaliciousPropertyValue_thenReturnValidationError(String maliciousString) {
|
||||||
boolean isValid = validator.isValid(stringWithXss, mock(ConstraintValidatorContext.class));
|
Asset invalidAsset = new Asset();
|
||||||
assertFalse(isValid);
|
invalidAsset.setName(maliciousString);
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
ConstraintValidator.validateFields(invalidAsset);
|
||||||
|
}).hasMessageContaining("field value is malformed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEntityWithMaliciousValueInAdditionalInfo_thenReturnValidationError() {
|
||||||
|
Asset invalidAsset = new Asset();
|
||||||
|
String maliciousValue = "qwerty<script>alert(document.cookie)</script>qwerty";
|
||||||
|
invalidAsset.setAdditionalInfo(JacksonUtil.newObjectNode()
|
||||||
|
.set("description", new TextNode(maliciousValue)));
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
ConstraintValidator.validateFields(invalidAsset);
|
||||||
|
}).hasMessageContaining("field value is malformed");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user