Sonar-Runner: Custom Rule Fails at Runtime With NoClassDefFoundError on External .jar

238 views
Skip to first unread message

Fac3Value

unread,
Dec 11, 2015, 12:49:28 PM12/11/15
to SonarQube
Hi all,

I'm entirely new to SonarQube.  However, I have been tasked with using it to scan my company's in-house code base (which is mostly Java) for security vulnerabilities, paying special attention to the OWASP-2013 Top Ten.  While the Sonar Way profile has some excellent coverage of the OWASP vulnerabilities, one of the places it's completely lacking in is A3: XSS (Cross-Site Scripting).  So I have set out to make my first custom Java rule, which is supposed to check to see if strings are sanitized.  

The rule currently uses OWASP's own ESAPI to canonicalize strings, and Jsoup to test for sanitization against a basic whitelist.  As such, both ESAPI and Jsoup have been included as dependencies in the Sonar Plugin's POM.xml as follows:

    <dependency>
    <groupId>org.owasp.esapi</groupId>
    <artifactId>esapi</artifactId>
    <version>2.1.0</version>
    <scope>provided</scope>
    </dependency>
    
    <dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.8.3</version>
    <scope>provided</scope>
    </dependency>

The scopes of both of these are "provided" because the plugin won't build if they aren't.  As it is, the plugin builds, and the rule is visible on the Sonar UI under "Rules."  

Now, the problem: Right now the rule is very basic.  I was hoping to test it out a little before increasing its complexity, but whenever I try to run the Sonar-Runner, I get a NoClassDefFoundError on one of the ESAPI classes (org.owasp.esapi.ESAPI).  This the first "external" (non-Sonar) class used in the rule.  I suspect that, if I took it out, it would fail on the next "external" class call...

I've tried messing with the dependency scope of both of these libraries, but anything other than "provided" results in build failure.  On a hunch, I also tried adding these classes to the list returned by getExtensions() in my plugin entrypoint class (the one that extends SonarPlugin), but this also caused the build to fail.  I've tried researching it but found very little.

So, my question is: How do I use "external" classes in my Sonar rules without them failing at runtime during analysis? 

Any advice is appreciated.  Thanks!

Julien HENRY

unread,
Dec 14, 2015, 5:39:08 AM12/14/15
to SonarQube
Hi,

This is not clear to me if you are using the default SonarQube Scanner (sonar-runner) or the SonarQube Scanner for Maven (mvn sonar:sonar) to run your SQ analysis?

Seems your project is a Maven one so in this case it is easier to use mvn sonar:sonar (it will automatically feed the properties sonar.java.binaries/sonar.java.librairies that are required for proper type resolution.

++

Julien

Fac3Value

unread,
Dec 14, 2015, 10:32:41 AM12/14/15
to SonarQube
Hi Julien,

Thanks for the response.  I'm trying to use Sonar-Runner.  Sorry I didn't specify.  When this project is done the code base I'll be scanning is on Subversion (not Maven).  But I don't have access to it yet so I just wanted to use Sonar-Runner to test my rules on some local .java files I wrote myself.  That's when I get the NoClassDefFoundError...

Thanks,

Julien HENRY

unread,
Dec 14, 2015, 10:43:16 AM12/14/15
to SonarQube
Then you have to pass manually in sonar-project.properties the value of sonar.java.binaries/sonar.java.libraries

Fac3Value

unread,
Dec 14, 2015, 12:35:37 PM12/14/15
to SonarQube
Okay, I've added the paths to the properties.  Still getting the same error on the same class.

Here's the structure of the project I'm trying to analyze:
Project
|
|_src (contains the .java files)
|
|_bin (contains the .class files)
|
|_lib (contains the external JARs)
|
|_sonar-project.properties

and here's my current sonar-project.properties file:

# Required metadata

sonar.projectKey=org.myOrg:security_rule_tests
sonar.projectName=Java :: Security Rule Testing :: SonarQube Runner

sonar.projectVersion=1.0


# Comma-separated paths to directories with sources (required)

sonar.sources=src


# Language

sonar.language=java


# Encoding of the source files

sonar.sourceEncoding=UTF-8

#Authentication
sonar.login=admin
sonar.password=admin

sonar.java.binaries=bin
sonar.java.libraries=lib/*.jar

Note that the lib folder contains the correct version of the .jar files for the OWASP and JSoup libraries, which were downloaded directly from http://mvnrepository.com.  

I'm really sorry to keep bothering you but there must be something that I'm just not getting here...

scot...@gmail.com

unread,
Dec 14, 2015, 1:48:19 PM12/14/15
to SonarQube
Hi.

You said that you set the scopes of the dependencies as "provided" because "the plugin won't build if they aren't". I think you are misinterpreting the Maven scopes.

The "provided" scope indicates you expect the JDK or a container to provide the dependency at runtime. So, with your current configuration you are expecting the sonar-runner provide the jars for esapi and jsoup, and this is the cause of NoClassDefFoundError.

The scope of these dependencies should not be "provided". Please remove the scope definition or change to "compile" and try again. I think this will solve your problem.
Reply all
Reply to author
Forward
0 new messages