Skip to content

Commit

Permalink
Merge pull request #126 from spassarop/1.6.5
Browse files Browse the repository at this point in the history
Support for leading dash on CSS property names
  • Loading branch information
davewichers authored Feb 1, 2022
2 parents 7ff740d + e1abb46 commit 46b3253
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 15 deletions.
97 changes: 97 additions & 0 deletions src/main/java/org/owasp/validator/css/CssParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2007-2022, Arshan Dabirsiaghi, Sebastián Passaro
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of OWASP nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.owasp.validator.css;

import org.apache.batik.css.parser.LexicalUnits;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.CSSParseException;
import org.w3c.css.sac.LexicalUnit;

public class CssParser extends org.apache.batik.css.parser.Parser {

/**
* This implementation is a workaround to solve leading dash errors on property names.
* @see <code>https://issues.apache.org/jira/browse/BATIK-1112</code>
* @param inSheet Specifies if the style to parse is inside a sheet or the sheet itself.
* @throws CSSException Thrown if there are parsing errors in CSS
*/
protected void parseStyleDeclaration(final boolean inSheet) throws CSSException {
boolean leadingDash = false;
for (;;) {
switch (current) {
case LexicalUnits.EOF:
if (inSheet) {
throw createCSSParseException("eof");
}
return;
case LexicalUnits.RIGHT_CURLY_BRACE:
if (!inSheet) {
throw createCSSParseException("eof.expected");
}
nextIgnoreSpaces();
return;
case LexicalUnits.SEMI_COLON:
nextIgnoreSpaces();
continue;
case LexicalUnits.MINUS:
leadingDash = true;
next();
break;
default:
throw createCSSParseException("identifier");
case LexicalUnits.IDENTIFIER:
}

final String name = (leadingDash ? "-" : "") + scanner.getStringValue();
leadingDash = false;

if (nextIgnoreSpaces() != LexicalUnits.COLON) {
throw createCSSParseException("colon");
}
nextIgnoreSpaces();

LexicalUnit exp = null;

try {
exp = parseExpression(false);
} catch (final CSSParseException e) {
reportError(e);
}

if (exp != null) {
boolean important = false;
if (current == LexicalUnits.IMPORTANT_SYMBOL) {
important = true;
nextIgnoreSpaces();
}
documentHandler.property(name, exp, important);
}
}
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/owasp/validator/css/CssScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public class CssScanner {
/**
* The parser to be used in any scanning
*/
private final Parser parser = new Parser();
private final Parser parser = new CssParser();

/**
* The policy file to be used in any scanning
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/owasp/validator/html/InternalPolicy.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.owasp.validator.html;

import org.owasp.validator.html.model.Property;
import org.owasp.validator.html.model.Tag;

import java.util.Map;
Expand Down Expand Up @@ -57,8 +58,8 @@ protected InternalPolicy(ParseContext parseContext) {
}
}

protected InternalPolicy(Policy old, Map<String, String> directives, Map<String, Tag> tagRules) {
super(old, directives, tagRules);
protected InternalPolicy(Policy old, Map<String, String> directives, Map<String, Tag> tagRules, Map<String, Property> cssRules) {
super(old, directives, tagRules, cssRules);
this.maxInputSize = determineMaxInputSize();
this.isNofollowAnchors = isTrue(Policy.ANCHORS_NOFOLLOW);
this.isNoopenerAndNoreferrerAnchors = isTrue(Policy.ANCHORS_NOOPENER_NOREFERRER);
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/owasp/validator/html/Policy.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public class Policy {

private final Map<String, AntiSamyPattern> commonRegularExpressions;
protected final Map<String, Tag> tagRules;
private final Map<String, Property> cssRules;
protected final Map<String, Property> cssRules;
protected final Map<String, String> directives;
private final Map<String, Attribute> globalAttributes;
private final Map<String, Attribute> dynamicAttributes;
Expand Down Expand Up @@ -341,12 +341,12 @@ protected Policy(ParseContext parseContext) {
this.dynamicAttributes = Collections.unmodifiableMap(parseContext.dynamicAttributes);
}

protected Policy(Policy old, Map<String, String> directives, Map<String, Tag> tagRules) {
protected Policy(Policy old, Map<String, String> directives, Map<String, Tag> tagRules, Map<String, Property> cssRules) {
this.allowedEmptyTagsMatcher = old.allowedEmptyTagsMatcher;
this.requiresClosingTagsMatcher = old.requiresClosingTagsMatcher;
this.commonRegularExpressions = old.commonRegularExpressions;
this.tagRules = tagRules;
this.cssRules = old.cssRules;
this.cssRules = cssRules;
this.directives = directives;
this.globalAttributes = old.globalAttributes;
this.dynamicAttributes = old.dynamicAttributes;
Expand Down Expand Up @@ -634,7 +634,7 @@ private static Element getDocumentElementByUrl(String href, URL baseUrl, boolean
public Policy cloneWithDirective(String name, String value) {
Map<String, String> directives = new HashMap<String, String>(this.directives);
directives.put(name, value);
return new InternalPolicy(this, Collections.unmodifiableMap(directives), tagRules);
return new InternalPolicy(this, Collections.unmodifiableMap(directives), tagRules, cssRules);
}

/**
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/org/owasp/validator/html/test/AntiSamyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;
import org.owasp.validator.html.model.Attribute;
import org.owasp.validator.html.model.Property;
import org.owasp.validator.html.model.Tag;

/**
Expand Down Expand Up @@ -1645,5 +1646,21 @@ public void testNoopenerAndNoreferrer() throws ScanException, PolicyException {
assertThat(as.scan("<a target='_blank' rel='noopener'>Link text</a>", revised3, AntiSamy.DOM).getCleanHTML().split("noopener").length, is(2));
assertThat(as.scan("<a target='_blank' rel='noopener'>Link text</a>", revised3, AntiSamy.SAX).getCleanHTML().split("noopener").length, is(2));
}

@Test
public void testLeadingDashOnPropertyName() throws ScanException, PolicyException {
// Test that property names with leading dash are supported, reported on issue #125.
final String input = "<style type='text/css'>\n" +
"\t.very-specific-antisamy { -moz-border-radius: inherit ; -webkit-border-radius: 25px 10px 5px 10px;}\n" +
"</style>";
// Define new properties for the policy
Pattern customPattern = Pattern.compile("\\d+(\\.\\d+)?px( \\d+(\\.\\d+)?px){0,3}", Pattern.DOTALL);
Property leadingDashProperty1 = new Property("-webkit-border-radius", Arrays.asList(customPattern), Collections.<String>emptyList(),Collections.<String>emptyList(),"","");
Property leadingDashProperty2 = new Property("-moz-border-radius", Collections.<Pattern>emptyList(), Arrays.asList("inherit"),Collections.<String>emptyList(),"","");
Policy revised = policy.addCssProperty(leadingDashProperty1).addCssProperty(leadingDashProperty2);
// Test properties
assertThat(as.scan(input, revised, AntiSamy.DOM).getCleanHTML(), both(containsString("-webkit-border-radius")).and(containsString("-moz-border-radius")));
assertThat(as.scan(input, revised, AntiSamy.SAX).getCleanHTML(), both(containsString("-webkit-border-radius")).and(containsString("-moz-border-radius")));
}
}

21 changes: 13 additions & 8 deletions src/test/java/org/owasp/validator/html/test/TestPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.owasp.validator.html.InternalPolicy;
import org.owasp.validator.html.Policy;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.model.Property;
import org.owasp.validator.html.model.Tag;

/**
Expand All @@ -46,8 +47,8 @@ protected TestPolicy(Policy.ParseContext parseContext) throws PolicyException {
super(parseContext);
}

protected TestPolicy(Policy old, Map<String, String> directives, Map<String, Tag> tagRules) {
super(old, directives, tagRules);
protected TestPolicy(Policy old, Map<String, String> directives, Map<String, Tag> tagRules, Map<String, Property> cssRules) {
super(old, directives, tagRules, cssRules);
}

public static TestPolicy getInstance() throws PolicyException {
Expand Down Expand Up @@ -75,20 +76,24 @@ public static TestPolicy getInstance(URL url) throws PolicyException {
public TestPolicy cloneWithDirective(String name, String value) {
Map<String, String> directives = new HashMap<String, String>(this.directives);
directives.put(name, value);
return new TestPolicy(this, Collections.unmodifiableMap(directives), tagRules);
return new TestPolicy(this, Collections.unmodifiableMap(directives), tagRules, cssRules);
}

public TestPolicy addTagRule(Tag tag) {
Map<String, Tag> newTagRules = new HashMap<String, Tag>(tagRules);
newTagRules.put(tag.getName().toLowerCase(), tag);
return new TestPolicy(this, this.directives, newTagRules);

return new TestPolicy(this, this.directives, newTagRules, cssRules);
}

public TestPolicy mutateTag(Tag tag) {
Map<String, Tag> newRUles = new HashMap<String, Tag>(this.tagRules);
newRUles.put( tag.getName().toLowerCase(), tag);
return new TestPolicy(this, this.directives, newRUles);
Map<String, Tag> newRules = new HashMap<String, Tag>(this.tagRules);
newRules.put( tag.getName().toLowerCase(), tag);
return new TestPolicy(this, this.directives, newRules, cssRules);
}

public TestPolicy addCssProperty(Property property) {
Map<String, Property> newCssRules = new HashMap<String, Property>(cssRules);
newCssRules.put(property.getName().toLowerCase(), property);
return new TestPolicy(this, this.directives, tagRules, newCssRules);
}
}

0 comments on commit 46b3253

Please sign in to comment.