Java Reachability With Gradle
Socket Application-Level Reachability for Gradle Projects
Overview
Socket offers three types of reachability analysis:
| Analysis | Noise Reduction | Requires CLI --reach |
|---|---|---|
| Dependency Reachability (prev. Tier 3) | ~35% | No (automatic) |
| Precomputed Reachability (prev. Tier 2) | ~80% | No (automatic) |
| Full Application Reachability (prev. Tier 1) | ~90% | Yes |
This guide covers Full Application Reachability (previously Tier 1) via the --reach flag. Precomputed and dependency reachability apply automatically in the Dashboard without CLI flags.
Prerequisites
Install Socket CLI:
npm install -g socket
socket loginOr set API key:
export SOCKET_SECURITY_API_TOKEN=sktsec_<your_key>Note:
socket scan createrequires an org slug. Runsocket loginto set a default, or pass--org <your-org-slug>on every command.
Step 1: Prepare the Gradle dependency manifest
The reachability analysis needs a resolved dependency graph for your Gradle build. The recommended approach is to add --dynamic-sbom-inference to your reachability scan command (Step 3 below). It has gradle generate a Socket facts file (such as gradle.socket.facts.json) as part of the scan, covering every Gradle build under the scan target rather than only the one at the root. Reachability is then analyzed and reported per subproject, and works from the graph your own build resolves.
If you'd rather generate the files yourself, run:
socket manifest dynamic-sbom-inferenceThis resolves the full dependency tree for each build and writes a Socket facts file (the preferred SBOM format for Socket), such as gradle.socket.facts.json, to its root directory. For a single build, socket manifest gradle does the same for the current directory. See socket manifest dynamic-sbom-inference --help for the available flags.
Note: If your project commits a
gradle.lockfile(or uses alibs.versions.tomlversion catalog), Socket can read it directly, so the scan works without--dynamic-sbom-inference. The flag is still recommended: a committed file records versions captured at some earlier point and no artifact locations, so it can drift from what your build resolves today, and you give up the per-subproject analysis. See the Gradle setup instructions for the trade-offs.
CycloneDX alternative: If you prefer a CycloneDX SBOM, you can instead run
socket cdxgen -t gradle -o socket-gradle.cdx.json --install-deps --lifecycle build. Without--lifecycle build, cdxgen defaults topre-buildto avoid arbitrary code execution; use--lifecycle buildfor a complete dependency graph that includes build-time resolved dependencies.
Step 2: Run Baseline Scan
Scan without reachability to establish a baseline CVE count. Add --dynamic-sbom-inference here too, so the baseline is built from the same resolved dependency graph the reachability scan in Step 3 will use:
socket scan create --dynamic-sbom-inference .Note the total CVE count.
Step 3: Run Reachability Scan
Execute scan with Full Application Reachability enabled:
socket scan create --reach --dynamic-sbom-inference .Socket performs function-level reachability analysis to determine which CVEs are exploitable. The project does not need to be compiled first — analysis runs on source, but uses class files when found (useful for builds that generate code at compile time).
Performance Tuning
For large Gradle projects, adjust these flags as needed:
socket scan create --reach --dynamic-sbom-inference \
--reach-analysis-timeout 20m \
--reach-analysis-memory-limit 32GB \
--reach-concurrency 4 \
.| Flag | Default | Description |
|---|---|---|
--reach-analysis-timeout | 10m | Per-run analysis timeout; specify with a s, m, or h unit (e.g. 90s, 10m, 1h) |
--reach-analysis-memory-limit | 8GB | Per-run memory limit; specify with an MB or GB unit (e.g. 512MB, 8GB); 16–32 GB recommended |
--reach-concurrency | 1 | Parallel workspace processing |
Step 4: Compare Results
In Socket Dashboard, view the reachability scan and filter by reachability status.
The CLI outputs a Noise% column directly. You can also calculate manually:
Noise% = ((Unreachable + NoSup + NoReach) / Total Vulns) × 100
The CLI outputs a summary table per ecosystem:
Project │ Vulns │ Reach │ Unreach │ NoSup │ NoReach │ Skipped │ Error │ Noise%
Result Categories
| Column | Meaning |
|---|---|
| Reach | Call chain exists from app code to vulnerable function |
| Unreach | No exploitable call chain; safe to ignore |
| NoSup | Socket hasn't classified the vulnerable functions for this CVE yet |
| NoReach | Reachability analysis not possible for this vulnerability |
| Skipped | Filtered out via --exclude-paths or other options |
| Error | Analysis error; check logs or contact support |
| Noise% | Percentage of vulns filtered as non-reachable |
In the Dashboard, additional statuses appear: Potentially Reachable (precomputed reachability indirect chain), Pending Precomputation (precomputed reachability processing), Not Determinable, and Unknown.
Step 5: Triage Reachable CVEs
Review CVEs marked as "Reachable" in Dashboard. For each:
- Check severity and CVSS score
- Evaluate upgrade path
- Prioritize remediation
Step 6: Override Unreachable CVEs (Optional)
For unreachable CVEs with low business impact, click Override in Dashboard to suppress from future scans.
Updated 3 days ago