From 0fe6d3c23146d6c89ca5df82062f45bebee510b1 Mon Sep 17 00:00:00 2001 From: Jakub Karczewski Date: Wed, 7 Dec 2022 22:01:57 +0100 Subject: [PATCH 1/2] gradle update --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf..070cb70 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2d7b5d20b3f5c69211649cf8692139a91934e6c3 Mon Sep 17 00:00:00 2001 From: Jakub Karczewski Date: Wed, 7 Dec 2022 22:03:03 +0100 Subject: [PATCH 2/2] support for custom svg elements & attributes --- README.md | 5 ++++ .../security/svg/SvgSecurityValidator.java | 25 +++++++++++++++--- .../svg/SvgSecurityValidatorTest.java | 26 ++++++++++++++++--- src/test/resources/custom/custom1.svg | 4 +++ src/test/resources/custom/custom2.svg | 5 ++++ 5 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 src/test/resources/custom/custom1.svg create mode 100644 src/test/resources/custom/custom2.svg diff --git a/README.md b/README.md index 677880f..589e75f 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,8 @@ String svg = "\n" + throw new RuntimeException("this file is suspicious" + validation.getOffendingElements()); } ``` + +If you want to allow other (possibly non-safe) elements/attributes use +```java +ValidationResult detect = new SvgSecurityValidator(CUSTOM_ELEMENTS, CUSTOM_ATTRIBUTES).validate(testFile) +``` diff --git a/src/main/java/com/github/bgalek/security/svg/SvgSecurityValidator.java b/src/main/java/com/github/bgalek/security/svg/SvgSecurityValidator.java index bb1cb5c..a7d6f48 100644 --- a/src/main/java/com/github/bgalek/security/svg/SvgSecurityValidator.java +++ b/src/main/java/com/github/bgalek/security/svg/SvgSecurityValidator.java @@ -11,9 +11,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Stream; /** * SVG Safe is a very simple and lightweight library that helps @@ -27,6 +29,23 @@ public class SvgSecurityValidator implements XssDetector { private static final Pattern JAVASCRIPT_PROTOCOL_IN_CSS_URL = Pattern.compile("url\\(.?javascript"); + private final String[] svgElements; + private final String[] svgAttributes; + + private SvgSecurityValidator(String[] elements, String[] attributes) { + this.svgElements = elements; + this.svgAttributes = attributes; + } + + public SvgSecurityValidator() { + this(SVG_ELEMENTS, SVG_ATTRIBUTES); + } + + public SvgSecurityValidator(List additionalElements, List additionalAttributes) { + this.svgElements = Stream.concat(Arrays.stream(SVG_ELEMENTS), additionalElements.stream()).distinct().toArray(String[]::new); + this.svgAttributes = Stream.concat(Arrays.stream(SVG_ATTRIBUTES), additionalAttributes.stream()).distinct().toArray(String[]::new); + } + /** * This is the main method that handles svg file validation * @@ -46,12 +65,12 @@ public ValidationResult validate(byte[] input) { return validate(new String(input, StandardCharsets.UTF_8)); } - private static Set getOffendingElements(String xml) { + private Set getOffendingElements(String xml) { if (JAVASCRIPT_PROTOCOL_IN_CSS_URL.matcher(xml).find()) return Collections.singleton("style"); PolicyFactory policy = new HtmlPolicyBuilder() - .allowElements(SVG_ELEMENTS) + .allowElements(this.svgElements) .allowStyling(CssSchema.union(CssSchema.DEFAULT, CssSchema.withProperties(SVG_SPECIFIC_STYLES))) - .allowAttributes(SVG_ATTRIBUTES).globally() + .allowAttributes(this.svgAttributes).globally() .allowUrlProtocols("https") .toFactory(); Set violations = new HashSet<>(); diff --git a/src/test/java/com/github/bgalek/security/svg/SvgSecurityValidatorTest.java b/src/test/java/com/github/bgalek/security/svg/SvgSecurityValidatorTest.java index a68a56d..143767d 100644 --- a/src/test/java/com/github/bgalek/security/svg/SvgSecurityValidatorTest.java +++ b/src/test/java/com/github/bgalek/security/svg/SvgSecurityValidatorTest.java @@ -1,15 +1,14 @@ package com.github.bgalek.security.svg; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.Collections; -import java.util.Objects; +import java.util.*; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -50,6 +49,25 @@ void shouldThrowExceptionWhenInputIsNotValidXml(String file) { assertFalse(detect.hasViolations()); } + @Test + void shouldNotFailWhenUserDefinedAttributesFound() { + String testFile = loadFile("custom/custom1.svg"); + List strings = Collections.singletonList("horiz-adv-x"); + ValidationResult detect = new SvgSecurityValidator(Collections.emptyList(), strings).validate(testFile); + assertEquals(Collections.emptySet(), detect.getOffendingElements()); + assertFalse(detect.hasViolations()); + } + + @Test + void shouldNotFailWhenUserDefinedElementsFound() { + String testFile = loadFile("custom/custom2.svg"); + List strings = Collections.singletonList("cursor"); + ValidationResult detect = new SvgSecurityValidator(strings, Collections.emptyList()).validate(testFile); + assertEquals(Collections.emptySet(), detect.getOffendingElements()); + assertFalse(detect.hasViolations()); + } + + private static Stream safeUseCases() { return Stream.of( Arguments.of("safe/valid1.svg"), @@ -84,4 +102,4 @@ private String loadFile(String fileName) { throw new RuntimeException(e); } } -} \ No newline at end of file +} diff --git a/src/test/resources/custom/custom1.svg b/src/test/resources/custom/custom1.svg new file mode 100644 index 0000000..b722a11 --- /dev/null +++ b/src/test/resources/custom/custom1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/test/resources/custom/custom2.svg b/src/test/resources/custom/custom2.svg new file mode 100644 index 0000000..2a3353d --- /dev/null +++ b/src/test/resources/custom/custom2.svg @@ -0,0 +1,5 @@ + + + + +