Skip to main content
Ben Nadel at the jQuery Conference 2009 (Cambridge, MA) with: John Resig
Ben Nadel at the jQuery Conference 2009 (Cambridge, MA) with: John Resig@jeresig )

Updating OWASP AntiSamy From 1.5.7 To 1.6.5 In ColdFusion 2021

By on
Tags:

A few years ago, I started using the OWASP AntiSamy 1.5.7 project to validate Markdown comments being processed with Flexmark. I'm trying to be better about keeping vendor libraries up-to-date (in order to keep them more secure). So, this morning, I updated OWASP AntiSamy to version 1.6.5 on my ColdFusion 2021 blog. I ran into a few hurdles doing this, so I thought I would just share the errors in case anyone needs some Google-love.

First, I downloaded the latest AntiSamy JAR files from Maven Repository. Then, I just tried to start-up the ColdFusion application to see what would happen. And, I was immediately met with this error:

coldfusion.runtime.java.JavaObjectClassNotFoundException:
Object Instantiation Exception.
ClassNotFound org.owasp.validator.html.Policy

I assumed that the Policy class was part of the core AntiSamy JAR file, which I had locally; so, I didn't believe that the Policy class was actually the issue. I went to look at the release notes; and, I noticed that for version 1.6.1, they replaced Log4j with Slf4j:

The 1.6.0 release erroneously listed slf4j as the logging API, but then directly used log4j. This release eliminates the use of log4j entirely, using slf4j. The 1.6.1 release includes the slf4j-simple logging library, but AntiSamy users can exclude this library and use whatever slf4j logging library they prefer. Please read the README for more details.

This raised some red flags in my mind because I had just recently ran into issues with the Slf4j library when using the Rollbar Java SDK with ColdFusion. I eventually solved the Rollbar SDK issue by pulling in the no-op logger implementation for Slf4j. As such, I tried installing the slf4j-nop-1.7.35 implementation. And, kabalmo! I got a new error message:

cvc-complex-type.2.4.a: Invalid content was found starting with element 'tag-rules'. One of '' is expected.

I knew that tag-rules was part of the polixy.xml file, so I guessed that the format of the XML file had changed. I took a look at the antisamy.xml policy file on the official GitHub page, and I could see that they had a number of elements that I didn't have in my policy file:

  • <common-regexps>
  • <common-attributes>
  • <global-tag-attributes>
  • <css-rules>

I went ahead and added those as empty elements in my policy file and tried booting-up my ColdFusion blog. And, just like that, the site loaded.

At this time, here's the list of JAR files that I'm loading in my Java Class Loader:

component {

	public void function onApplicationStart() {

		var antiSamyJavaLoader = javaLoaderFactory.getJavaLoader([
			expandPath( "/jars/antisamy-1.6.5/antisamy-1.6.5.jar" ),
			expandPath( "/jars/antisamy-1.6.5/batik-constants-1.14.jar" ),
			expandPath( "/jars/antisamy-1.6.5/batik-css-1.14.jar" ),
			expandPath( "/jars/antisamy-1.6.5/batik-i18n-1.14.jar" ),
			expandPath( "/jars/antisamy-1.6.5/batik-shared-resources-1.14.jar" ),
			expandPath( "/jars/antisamy-1.6.5/batik-util-1.14.jar" ),
			expandPath( "/jars/antisamy-1.6.5/commons-codec-1.11.jar" ),
			expandPath( "/jars/antisamy-1.6.5/commons-io-2.6.jar" ),
			expandPath( "/jars/antisamy-1.6.5/commons-logging-1.2.jar" ),
			// expandPath( "/jars/antisamy-1.6.5/httpclient-4.5.13.jar" ),
			// expandPath( "/jars/antisamy-1.6.5/httpcore-4.4.15.jar" ),
			expandPath( "/jars/antisamy-1.6.5/nekohtml-1.9.22.jar" ),
			expandPath( "/jars/antisamy-1.6.5/slf4j-api-1.7.35.jar" ),
			expandPath( "/jars/antisamy-1.6.5/slf4j-nop-1.7.35.jar" ),
			expandPath( "/jars/antisamy-1.6.5/xercesImpl-2.12.2.jar" ),
			expandPath( "/jars/antisamy-1.6.5/xml-apis-1.4.01.jar" ),
			expandPath( "/jars/antisamy-1.6.5/xml-apis-ext-1.3.04.jar" ),
			expandPath( "/jars/antisamy-1.6.5/xmlgraphics-commons-2.6.jar" )
		]);

	}

}

I commented-out the http-client related JAR files because I just can't believe those are needed, especially since I don't allow for any imports. And, it seems to work so far.

And, here's my currently policy (after a bit of tinkering). Since this is for user-provided comments, it's fairly locked-down, allowing for very few HTML entities and attributes:

<?xml version="1.0" encoding="UTF-8" ?>
<anti-samy-rules
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="antisamy.xsd">

	<directives>
		<directive name="embedStyleSheets" value="false" />
		<directive name="formatOutput" value="true" />
		<directive name="maxInputSize" value="100000" />
		<directive name="nofollowAnchors" value="true" />
		<directive name="noopenerAndNoreferrerAnchors" value="true" />
		<directive name="validateParamAsEmbed" value="true" />
		<directive name="omitDoctypeDeclaration" value="true" />
		<directive name="omitXmlDeclaration" value="true" />
		<directive name="onUnknownTag" value="remove" />
		<directive name="useXHTML" value="true" />
		<!-- Allows the use of dynamic attributes (i.e. HTML5 "data-") -->
		<directive name="allowDynamicAttributes" value="false" />
	</directives>

	<common-regexps>
		<regexp name="onsiteURL" value="^(?!//)(?![\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*(&amp;colon))[\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*"/>
		<regexp name="offsiteURL" value="https?://[\p{L}\p{N}]+[\p{L}\p{N}\p{Zs}\.\#@\$%\+&amp;;:\-_~,\?=/!\(\)]*(\s)*"/>
		<regexp name="codeLanguage" value="language-[a-zA-Z0-9]+"/>
	</common-regexps>

	<common-attributes>
		<!-- Nothing to see here. -->
	</common-attributes>

	<global-tag-attributes>
		<!-- Nothing to see here. -->
	</global-tag-attributes>

	<tag-rules>
		<tag name="a" action="validate">
			<attribute name="href" onInvalid="filterTag">
				<regexp-list>
					<regexp name="onsiteURL"/>
					<regexp name="offsiteURL"/>
				</regexp-list>
			</attribute>
			<attribute name="rel">
				<regexp-list>
					<regexp value="(\s*(nofollow|noopener|noreferrer)(\s(nofollow|noopener|noreferrer))*\s*)?"/>
				</regexp-list>
			</attribute>
		</tag>
		<tag name="b" action="validate" />
		<tag name="blockquote" action="validate" />
		<tag name="br" action="validate" />
		<tag name="code" action="validate">
			<attribute name="class">
				<regexp-list>
					<regexp name="codeLanguage"/>
				</regexp-list>
			</attribute>
		</tag>
		<tag name="em" action="validate" />
		<tag name="i" action="validate" />
		<tag name="li" action="validate" />
		<tag name="ol" action="validate">
			<attribute name="start">
				<regexp-list>
					<regexp value="\d+" />
				</regexp-list>
			</attribute>
		</tag>
		<tag name="p" action="validate" />
		<tag name="pre" action="validate">
			<attribute name="class">
				<regexp-list>
					<regexp name="codeLanguage"/>
				</regexp-list>
			</attribute>
		</tag>
		<tag name="strong" action="validate" />
		<tag name="ul" action="validate" />
	</tag-rules>

	<css-rules>
		<!-- Nothing to see here. -->
	</css-rules>

</anti-samy-rules>

I really only allow the most simple formatting and code blocks. Everything else is rejected. I don't trust y'all!

Anyway, just trying to keep my libraries up-to-date. As I mentioned in my my post on adding Strict-Transport-Security (HSTS) Http Headers in ColdFusion, security is a feature of the application that tends to rot over time. And, I'm trying to be better about keeping things as secure as possible.

What Version of AntiSamy Ships With ColdFusion 2021?

As of ColdFusion 11, you can now use a native getSafeHtml() function which is using the OWASP AntiSamy project under the hood. I was curious to see what version ColdFusion ships with; so, I popped into the ColdFusion Admin and looked at the CF Server Java Class Path values in the Info page:

/cfusion/lib/antisamy-1.5.13.jar

Looks like 1.5.13 was released Jan 12, 2021; so, it's not too old. Part of me wonders if I should drop my class-loading approach and just use the one that ships with the Adobe ColdFusion platform. That said, I kind of like having total control over the version.

Want to use code from this post? Check out the license.

Reader Comments

Post A Comment — I'd Love To Hear From You!

Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.