Java Dependency Analyzer 1.6.0
A Python CLI tool that inspects Java dependency hierarchies in Maven and Gradle projects and reports known vulnerabilities.
Prerequisites
- Python
^3.14 - Poetry
2.2
Installation
Via pip (recommended)
Install directly from PyPI:
pip install java-dependency-analyzer
From source
Clone the repository and install all dependencies using Poetry:
git clone <repository-url>
cd java-dependency-analyzer
poetry install
Usage
jda [--version] <COMMAND> [OPTIONS] [FILE]
COMMAND is one of gradle, maven, sbom, or jar.
Global options
| Option | Description |
|---|---|
--version |
Print the installed version and exit. |
gradle
jda gradle [OPTIONS] [FILE]
FILE is the path to a build.gradle or build.gradle.kts file.
Omit FILE when supplying --dependencies.
Gradle-only options
| Option | Short | Default | Description |
|---|---|---|---|
--module |
(none) | Gradle module name. When supplied, the dependency task becomes <module>:dependencies. Can only be used with --project. |
maven
jda maven [OPTIONS] [FILE]
FILE is the path to a pom.xml file.
Omit FILE when supplying --dependencies.
sbom
jda sbom [OPTIONS] FILE
FILE is the path to an SBOM JSON file. Supported standards: SPDX 2.3 and CycloneDX 1.6.
sbom-only options
| Option | Short | Required | Default | Description |
|---|---|---|---|---|
--standard |
-s |
No | cyclonedx |
SBOM standard of the input file: spdx or cyclonedx (case-insensitive). |
jar
jda jar [OPTIONS] FILE
FILE is a text file listing jar files, one per line. Each entry is an absolute path or a jar file name; blank lines and lines starting with # are ignored.
The Maven coordinates of each jar are identified through the Maven Central search API. When --group-mapping is given and the artifact parsed from the <artifact>-<version>.jar file name is in the mapping, it is searched under each mapped group (in file order) first. Otherwise (or when the mapping finds nothing) the best match is used: when the jar exists on disk (absolute path, or a relative name found beside the list file or in the current directory) its SHA-1 checksum is searched first; then the <artifact>-<version>.jar file name is searched. When several artifacts match a file name, the first match is used and a warning is logged. Jars that cannot be identified are skipped with a warning.
jar-only options
| Option | Short | Default | Description |
|---|---|---|---|
--jar |
false |
Treat FILE as a single jar (absolute path or jar file name with extension) instead of a list of jars. |
|
--group-mapping |
(none) | Text file with one <group>:<artifact> per line (blank lines and lines starting with # are ignored). Artifacts listed in it are searched under the mapped group first; the other artifacts use the best match. |
Options (gradle / maven subcommands)
| Option | Short | Default | Description |
|---|---|---|---|
--project |
-p |
Root directory of the project to analyse. When supplied, the dependency tree is generated automatically and FILE / --dependencies must not be used. |
|
--java-home |
(system JAVA_HOME) |
Directory to use as JAVA_HOME. Can only be used with --project. |
|
--use-wrapper |
false |
Use the project wrapper script (gradlew/mvnw) instead of the system build tool. Can only be used with --project. |
|
--wrapper |
(none) | Custom wrapper script name to use instead of the default (gradlew/gradlew.bat for Gradle, mvnw/mvnw.cmd for Maven). Can only be used with --use-wrapper. |
|
--dependencies |
-d |
Path to a pre-resolved dependency tree text file (see below). When supplied, parsing and transitive resolution are skipped. | |
--output-format |
-f |
all |
Report format: json, html, or all (both). |
--output-dir |
-o |
./reports |
Directory to write the report file(s) into. |
--no-transitive |
false |
Skip transitive dependency resolution; analyse direct dependencies only. | |
--verbose |
-v |
false |
Print progress messages to the console. |
--rebuild-cache |
false |
Delete the vulnerability cache before scanning. | |
--cache-ttl |
7 |
Cache TTL in days. Set to 0 to disable caching. |
Options (sbom subcommand)
| Option | Short | Default | Description |
|---|---|---|---|
--standard |
-s |
cyclonedx |
SBOM standard of the input file: spdx or cyclonedx. |
--output-format |
-f |
all |
Report format: json, html, or all (both). |
--output-dir |
-o |
./reports |
Directory to write the report file(s) into. |
--no-transitive |
false |
Skip transitive dependency resolution; analyse direct dependencies only. | |
--verbose |
-v |
false |
Print progress messages to the console. |
--rebuild-cache |
false |
Delete the vulnerability cache before scanning. | |
--cache-ttl |
7 |
Cache TTL in days. Set to 0 to disable caching. |
Options (jar subcommand)
| Option | Short | Default | Description |
|---|---|---|---|
--jar |
false |
Treat FILE as a single jar instead of a list of jars. |
|
--group-mapping |
(none) | File of <group>:<artifact> lines used to search mapped artifacts under their group first. |
|
--output-format |
-f |
all |
Report format: json, html, or all (both). |
--output-dir |
-o |
./reports |
Directory to write the report file(s) into. |
--no-transitive |
false |
Skip transitive dependency resolution; analyse direct dependencies only. | |
--verbose |
-v |
false |
Print progress messages to the console. |
--rebuild-cache |
false |
Delete the vulnerability cache before scanning. | |
--cache-ttl |
7 |
Cache TTL in days. Set to 0 to disable caching. |
Exit Codes
| Code | Meaning |
|---|---|
0 |
Scan completed successfully; no vulnerabilities found. |
10 |
Scan completed successfully; at least one vulnerability was detected. |
Analysing a project directly (--project)
When a Gradle or Maven project is available locally, pass its root directory to --project and jda will generate the dependency tree automatically before scanning:
# Gradle project using the system gradle
jda gradle --project /path/to/my-project
# Gradle multi-module project, analyse the :api module
jda gradle --project /path/to/my-project --module api
# Maven project using the project wrapper, with a custom JAVA_HOME
jda maven --project /path/to/my-project --use-wrapper --java-home /usr/lib/jvm/java-21
# Gradle project using a custom wrapper script name
jda gradle --project /path/to/my-project --use-wrapper --wrapper gradlew-local
--java-homeoverrides theJAVA_HOMEenvironment variable for the invocation. If neither is set, the command fails with a clear error.--use-wrapperinvokesgradlew/gradlew.bat(Gradle) ormvnw/mvnw.cmd(Maven) from the project root. AUsageErroris raised when the wrapper script is absent.--wrapperoverrides the default wrapper script name used by--use-wrapper. Can only be used with--use-wrapper.--module(Gradle only) specifies a sub-module; the dependency task becomes<module>:dependencies. Can only be used with--project.--projectis mutually exclusive with bothFILEand--dependencies.
Pre-resolved dependency trees (--dependencies)
When a Gradle or Maven project already has a dependency tree available (e.g. from CI), you can pass it directly to skip the parser and transitive resolver:
- Gradle: generate with
gradle dependencies --configuration runtimeClasspath > gradle.txt - Maven: generate with
mvn dependency:tree -Dscope=runtime > maven.txt
The report will reflect the exact tree from the file, including all transitive dependencies.
Generating SBOM files
Use one of the approaches below to produce an SBOM JSON file that jda sbom can consume.
CycloneDX 1.6
Gradle — add the CycloneDX Gradle plugin to build.gradle:
plugins {
id 'org.cyclonedx.bom' version '3.2.4'
}
Or for Kotlin DSL (build.gradle.kts):
plugins {
id("org.cyclonedx.bom") version "3.2.4"
}
Then run:
gradle cyclonedxBom
Output: build/reports/bom.json
Maven — run the CycloneDX Maven plugin without modifying pom.xml:
mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom
Output: target/bom.json
SPDX 2.3
JDA expects a SPDX JSON document where each package entry in the packages array has an externalRefs entry with referenceType: "purl" and a referenceLocator in the form pkg:maven/{groupId}/{artifactId}@{version}.
Gradle and Maven — use syft:
# Gradle project
syft /path/to/gradle-project -o spdx-json=sbom.spdx.json
# Maven project
syft /path/to/maven-project -o spdx-json=sbom.spdx.json
Examples
Analyse a Maven POM and produce both JSON and HTML reports in the current directory:
jda maven pom.xml
Analyse a Gradle build file and write only an HTML report to ./reports/:
jda gradle build.gradle -f html -o reports/
Analyse direct dependencies only, with verbose output:
jda gradle build.gradle.kts --no-transitive -v
Scan using a pre-resolved Gradle dependency tree (skips transitive resolution):
jda gradle --dependencies runtime.txt -f json -o reports/
Scan using a pre-resolved Maven dependency tree (skips transitive resolution):
jda maven --dependencies maven.txt -f json -o reports/
Analyse a Gradle project directly (auto-generates the dependency tree):
jda gradle --project /path/to/my-gradle-project --use-wrapper
Analyse a Maven project directly with a custom JAVA_HOME:
jda maven --project /path/to/my-maven-project --java-home /usr/lib/jvm/java-21
Analyse a specific Gradle module using a custom wrapper script:
jda gradle --project /path/to/my-gradle-project --module api --use-wrapper --wrapper gradlew-local
Scan a CycloneDX SBOM file and produce both JSON and HTML reports:
jda sbom --standard cyclonedx bom.json
Scan an SPDX SBOM file and write an HTML report to a custom directory:
jda sbom --standard spdx sbom.spdx.json -f html -o reports/
Scan every jar listed in a file (one absolute path or jar file name per line):
jda jar jars.txt
Scan a single jar by absolute path, or by file name only (looked up on Maven Central):
jda jar --jar /path/to/log4j-core-2.14.1.jar
jda jar --jar log4j-core-2.14.1.jar
Scan jars, searching the artifacts listed in a mapping file (<group>:<artifact> per line) under their group first:
jda jar --group-mapping groups.txt jars.txt
Configuration
| Environment Variable | Required | Default | Description |
|---|---|---|---|
GITHUB_TOKEN |
No | (none) | A GitHub personal access token. When set, the GhsaScanner uses it to authenticate requests to the GitHub Advisory Database REST API, which significantly increases the rate limit (from ~60 unauthenticated requests/hour to 5 000 authenticated requests/hour). Without it, scans with many dependencies may trigger HTTP 403/429 responses and fall back to the OSV.dev API. |
GHSA_API_URL |
No | https://api.github.com/advisories |
Override the GitHub Advisory Database REST API endpoint used by GhsaScanner. Useful for proxies or air-gapped mirrors. |
OSV_QUERY_URL |
No | https://api.osv.dev/v1/query |
Override the OSV.dev single-query endpoint used by OsvScanner. |
OSV_VULN_URL |
No | https://osv.dev/vulnerability/ |
Override the OSV.dev vulnerability detail base URL embedded in reports. |
MAVEN_CENTRAL_URL |
No | https://maven-central.storage-download.googleapis.com/maven2 |
Override the Maven Central repository URL used by TransitiveResolver to fetch POM files. |
MAVEN_SEARCH_URL |
No | https://central.sonatype.com/solrsearch/select |
Override the Maven Central search endpoint used by JarCoordinateResolver to identify jars. |
JDA_CONFIG_DIR |
No | (none) | Directory used to store and load a custom logging.ini. On first run, the bundled logging.ini is seeded into this directory. If not set, the bundled config is loaded directly from the package. |
Set it in your shell or in a .env file in the working directory before running jda:
# shell
export GITHUB_TOKEN=ghp_yourTokenHere
# or in .env
GITHUB_TOKEN=ghp_yourTokenHere
Logging
The tool writes logs to java_dependency_analyzer.log in the current working directory and prints progress messages to the console via Rich.
A logging.ini is bundled inside the package and loaded automatically — no manual setup is required after installation.
Custom logging configuration
To override the default logging settings, set the JDA_CONFIG_DIR environment variable to a directory path. On first run, jda seeds the bundled logging.ini into that directory; edit the copy there to customise log levels, file paths, or handlers:
# shell
export JDA_CONFIG_DIR=/path/to/my-config
# or in .env
JDA_CONFIG_DIR=/path/to/my-config
Architecture
graph TD
CLI["jda CLI (cli.py)"] --> Parser["DependencyParser (ABC)"]
Parser --> MavenParser
Parser --> GradleParser
Parser --> MavenDepTreeParser
Parser --> GradleDepTreeParser
Parser --> SbomParser
Parser --> JarParser
JarParser --> JarResolver["JarCoordinateResolver<br/>(Maven Central search)"] CLI --> Resolver["TransitiveResolver<br/>(Maven Central)"]
CLI --> Scanner["VulnerabilityScanner (ABC)"]
Scanner --> OsvScanner["OsvScanner<br/>(OSV.dev API)"]
Scanner --> GhsaScanner["GhsaScanner<br/>(GitHub Advisory DB)"]
OsvScanner --> Cache["VulnerabilityCache<br/>(SQLite)"]
GhsaScanner --> Cache
CLI --> Reporter["Reporter (ABC)"]
Reporter --> JsonReporter
Reporter --> HtmlReporter
MavenParser --> Dependency["Dependency / Vulnerability<br/>Dataclasses"]
GradleParser --> Dependency
MavenDepTreeParser --> Dependency
GradleDepTreeParser --> Dependency
SbomParser --> Dependency
JarResolver --> Dependency Resolver --> Dependency
OsvScanner --> Dependency
GhsaScanner --> Dependency
JsonReporter --> ScanResult["ScanResult"]
HtmlReporter --> ScanResult
Dependency --> ScanResult
Components
| Component | Location | Responsibility |
|---|---|---|
| CLI | java_dependency_analyzer/cli.py |
Entry point (gradle / maven / sbom / jar subcommands); orchestrates parsing, resolving, scanning, and reporting. |
MavenParser |
parsers/maven_parser.py |
Parses pom.xml, resolves ${property} placeholders, filters by runtime scope. |
GradleParser |
parsers/gradle_parser.py |
Parses Groovy DSL (build.gradle) and Kotlin DSL (build.gradle.kts) files. |
MavenDepTreeParser |
parsers/maven_dep_tree_parser.py |
Parses mvn dependency:tree text output into a full dependency tree. |
GradleDepTreeParser |
parsers/gradle_dep_tree_parser.py |
Parses gradle dependencies text output into a full dependency tree. |
SbomParser |
parsers/sbom_parser.py |
Parses SBOM JSON files in SPDX 2.3 or CycloneDX 1.6 format; extracts Maven dependencies via package URLs (pkg:maven/…). |
TransitiveResolver |
resolvers/transitive.py |
Fetches transitive dependencies by downloading POM files from Maven Central. |
JarParser |
parsers/jar_parser.py |
Reads a text file listing jars (or a single jar with --jar) and returns the resolved dependencies. |
JarCoordinateResolver |
resolvers/jar_resolver.py |
Identifies a jar's Maven coordinates via the Maven Central search API, by mapped group (--group-mapping), SHA-1 checksum, or file name. |
group_mapping |
util/group_mapping.py |
load_group_mapping() reads the <group>:<artifact> mapping file used by --group-mapping. |
LoggingGroup |
util/logging_group.py |
Click group that writes every command-line error to the log. |
OsvScanner |
scanners/osv_scanner.py |
Queries the OSV.dev batch API for known CVEs. |
GhsaScanner |
scanners/ghsa_scanner.py |
Queries the GitHub Advisory Database REST API for security advisories; automatically falls back to OSV when rate-limited (HTTP 403/429). |
VulnerabilityCache |
cache/vulnerability_cache.py |
SQLite-backed cache for raw vulnerability API payloads with configurable TTL. |
DatabaseManager |
cache/db.py |
Manages SQLite connection lifecycle and schema initialisation. |
xml_helpers |
util/xml_helpers.py |
Shared POM XML utilities: POM_NS constant and detect_pom_namespace() for handling namespace-qualified and namespace-free POM documents. |
JsonReporter |
reporters/json_reporter.py |
Writes a ScanResult to a JSON file. |
HtmlReporter |
reporters/html_reporter.py |
Renders a ScanResult to a styled HTML report via a Jinja2 template. |
Development Setup
Install all dependencies (including dev tools):
poetry install
Running Tests
Run the full test suite with coverage and generate an HTML report:
poetry run pytest --cov=java_dependency_analyzer tests --cov-report html
Code Quality
Format and lint the source code (linter must score 10/10):
poetry run black java_dependency_analyzer
poetry run pylint java_dependency_analyzer
Publishing to PyPI
Prerequisites
- A PyPI account with an API token.
Configure the token
poetry config pypi-token.pypi <your-token>
Build and publish
poetry publish --build
This builds the source distribution and wheel, then uploads them to PyPI in one step.
Note: PyPI releases are immutable. Once a version is published, it cannot be overwritten.
To fix a mistake, yank the release via the PyPI web UI and publish a new version.
Changelog
Author
Ron Webb <ron@ronella.xyz>
Metadata
Release files for java-dependency-analyzer 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| java_dependency_analyzer-1.6.0.tar.gz | 50.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| java_dependency_analyzer-1.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 113.3 kB
Release files / java_dependency_analyzer-1.6.0.tar.gz
| Download URL | java_dependency_analyzer-1.6.0.tar.gz |
|---|---|
| Size | 50.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c2fcd696286238dd8df0a22961aa3693a8a0d72ebaa814d1213384e6d8125a6
|
|
BLAKE2b-256 checksum How to use checksums |
287cd4b04f0af6dcd45d2e735c06b45dd9cb4a6bac91d52e64a0cf64eac0407e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.0 CPython/3.14.8 Linux/6.17.0-1022-azure
|
Release files / java_dependency_analyzer-1.6.0-py3-none-any.whl
| Download URL | java_dependency_analyzer-1.6.0-py3-none-any.whl |
|---|---|
| Size | 63.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
464a560c95f77fc43abd14a7b88a874d2a7a3652888bce47f0485662abccebe9
|
|
BLAKE2b-256 checksum How to use checksums |
fe21ab1d54ef791f8be6320be97719f668064e646b4486028244f55ed9a51688
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.0 CPython/3.14.8 Linux/6.17.0-1022-azure
|
Security for java-dependency-analyzer 1.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.