Java Application Analysis

JVM Ecosystems 

IQ server Java application analysis supports most JVM-based languages and is not limited to Java only. These include the most popular languages in use by the developer community, e.g., Kotlin, Scala, Groovy, Clojure, Fantom, Ceylon, JRuby, Golo, etc.

On this page

Evaluation: Advance Binary Fingerprinting

Evaluation: Source code and manifest analysis

Evaluation: Advance Binary Fingerprinting

Java scanning supports packaged archives including (.ear/.war/.jar/.zip/.tar.gz) files. For the best results, we recommend using the post-build artifact as the scan target (what you are planning to deploy) as it will contain all the direct and transitive dependencies required by the project. After a normal CI build, add a post-build step to do the analysis using the CI Plugins or the CLI Scanner .  A Lifecycle evaluation will pick up any dependencies packaged into the archive or included in the target directory.

  • Uber/Shaded Archives

    Uber jars are a way to include dependencies by copying in their contents when the jar is built. The Lifecycle algorithms will not identify them as separate dependencies, as these jars could be similarly matched to modified open-source components.  This will lead to confusing results for development teams.  For more accurate results, you will need to call the index goal of the Maven plugin at the time of building the uber/shaded jar. This will generate a dependency index (module.xml file) of direct and transitive dependencies found in the shaded jar's POM file.  Any module.xml files found in the scan path by the CI Scanners will be included in the results.

  • Alternate Methods

    Custom jar files typically do not include their dependencies in the scan context so scanning them will not produce results. The maven copy dependencies command can be used: mvn dependency:copy-dependencies to include the dependencies into a separate directory. This directory can be scanned via the CLI scanner or similar tools.

  • Android

    The Lifecycle scanner does not support scanning a `.apk` directly due to the compilers converting the open-source code into a DEX (Dalvik Executable) file: a minified/modified version of the code. For this reason, scanning prior to the assembling of the `.apk` is required.  We suggest embedding the native Maven or Gradle scanners instead.

  • SBT Assembly

    To perform an analysis of a sbt assembly, a temporary pom.xml file will need to be created using the sbt makePom command.  We recommend using the Maven plugin for the best results.  See the example steps below.

  • Similar Matching

    Evaluation of modified dependencies is supported for Java.  The inner contents of components are analyzed along with their fingerprints to determine the best match of the original source component. Components that have been changed from their published source are susceptible to additional risk.

  • InnerSource

    When using the Maven plugin  or Grade plugin , Java components created by insider teams will be labeled in the application scan report.  Any dependencies only brought in by the Innersource component will be considered direct dependencies of those components.  Innersource components will need to be scanned before the current project in order to determine if a component is Innersource or not.  Refer to Innersource for more details.

  • Direct and Transitive Dependencies

    The project's manifest is used to determine if a dependency is directly called by the project or not.   Any dependencies not found in the manifest are   considered transitive dependencies.  The Transitive Solver provides remediation recommendations based on the direct dependency of transitive dependency violations.

  • Gradle Community Plugin

    This plugin can be used to natively scan Gradle projects using Lifecycle.

  • Software Bill of Materials (SBOMs)

    The Lifecycle scanner can scan SBOMs generated from CycloneDX for Java. See the CycloneDX pages for details.

Evaluation: Source code and manifest analysis

A Java project's source code could be analyzed for direct dependencies using just the coordinates provided in the manifest files.  When any binaries are detected in the scan path, the manifest files are not used for identifying components.  Pointing directly to the path of the manifest is recommended to force a manifest analysis

  • The transitive dependencies are not automatically resolved, therefore not included during this analysis.  The Maven plugin 'evaluate' goal should be used to resolve transitive dependencies.
  • Dependencies with a group, artifact id, and exact version number are required. 
  • The extension and classifier fields are optional.
  • 142
    pom.xml files are ignored if they are inside a META-INF directory. This is because these files do not necessarily represent the application, particularly in the case of uber/shaded archives.
  • 149
    Although pom.xml files are ignored if they are inside a META-INF directory by default, this can now be changed if needed by configuring the scan-pom-files-in-meta-inf-directory feature using the Feature Configuration REST API - v2.

Maven

  • Target the primary pom.xml file.
  • The 'test' and 'provided' scoped dependencies are not evaluated
<dependency>
  <groupId>org.example</groupId>
  <artifactId>ACME-business</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

Gradle

  • Target the primary build.gradle file.
  • Only build.gradle files written in Groovy are supported
  • Supported scopes: "api", "apiElements", "compileClasspath", "implementation", "compileOnly", "compileOnlyApi", "compile"  
  • Other dependency scopes are not evaluated.

dependencies {
  compile  'org.example:ACME-business:1.0-SNAPSHOT'
}

SBT Assembly

  1. Create a pom file (case sensitive):  sbt makePom
  2. Copy the generated pom file to the root directory and rename it.
    • cp target/scala-2.13/real-world-example-project_2.13-1.0.pom pom.xml
    • or manually copy and rename it
  3. Run the maven plugin evaluate goal. Example:

mvn com.sonatype.clm:clm-maven-plugin:evaluate -Dclm.serverUrl=http://localhost:8070 -Dclm.username=admin -Dclm.password=admin123 -Dclm.applicationId=scala-play -Dclm.stage=build

Example: pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.example</groupId>
   <artifactId>ACME-Consumer</artifactId>
   <packaging>pom</packaging>
   <version>1.0-SNAPSHOT</version>
   <modules>
      <module>Consumer-Service</module>
      <module>Consumer-Data</module>
   </modules>
   <properties>
      <commons.version>2.6</commons.version>
   </properties>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons.version}</version>
         </dependency>
         <dependency>
            <groupId>org.example</groupId>
            <artifactId>ACME-data</artifactId>
            <version>1.0-SNAPSHOT</version>
         </dependency>
      </dependencies>
   </dependencyManagement>
</project>

Using the Jenkins CI Plugin to scan manifests

The Jenkins plugin will not evaluate manifest files by default so a custom scan pattern is required.  See the documentation for details.

nexusPolicyEvaluation iqApplication:  'SampApp' , iqScanPatterns: [[scanPattern:  '**/pom.xml' ], [scanPattern:  '**/build.gradle']], iqStage:  'build'