Full Application Reachability

Full application Reachability enhances the precomputed reachability by filtering out CVEs that affect functions never called in both the application source code and the dependency code.

📘

See Reachability Analysis for an overview of all Reachability Analysis capabilities in Socket. This page is about just one of the reachability techniques that Socket offers.

The Precomputed reachability allows Socket to remove up to 60% of vulnerabilities by looking at how packages in your dependency graph call into other packages in your dependency graph.

Full application reachability uses the same underlying reachability analysis engine, but it scans both the application source code and the dependency code. This allows the full application reachability to flag around 80% of vulnerabilities as irrelevant. For some ecosystems, the noise reduction rate is above 90%.

The benefits of full application reachability analysis include:

  • Excellent noise reduction – Up to 90% of all vulnerability alerts can be flagged as irrelevant.
  • Powerful triaging support – Provides a precise list of function calls from your application source code that lead to reachable vulnerabilities, making it easier to assess impact and severity.
  • Choose where the analysis runs. Run the analysis in your own environment to keep source code on your infrastructure, or use managed scans to let Socket run it for you.
  • Phantom dependency detection – phantom dependencies are automatically detected and considered in the reachability analysis.

There are a few caveats to using the full application reachability analysis. It requires a small amount of manual configuration per repository and can be compute-intensive, depending on the programming language(s) and the size of the application.

Based on your organization’s security needs, you may choose to enable full application analysis for select repositories, while using precomputed reachability analysis for others.

When to use Full Application Reachability

Full application reachability is designed to be used selectively. Most customers start with precomputed reachability across their repositories and enable full application reachability only for a small number of production-critical or high-noise services where maximum precision is required.

Because full application reachability performs deep static analysis across both application code and dependencies, it is more compute-intensive by design. This trade-off allows Socket to deliver significantly higher signal and noise reduction, but it is not required to get value from reachability analysis overall.

Running the Reachability Analysis

🧪

New in beta: managed scans. Socket can run full application reachability for you, once a day on its own infrastructure, for GitHub repositories you pick in the dashboard. You don't need to set anything up in CI. See Managed Scans.

Run the analysis yourself

To run full application reachability yourself, use the Node CLI (the socket command) or the Python CLI (the socketcli command).

📘

Full application reachability requires an Enterprise plan (Enterprise trials qualify) and an API token.

The analysis runs on your machine and is performed by an analysis engine that needs the build toolchain for each language in your project — for example, a Java runtime for Java, Kotlin, and Scala, the Go toolchain for Go, or .NET for C# (see the language-specific requirements below). The engine checks for the required tools when it runs and reports any that are missing; you can skip these checks with --reach-disable-external-tool-checks.

The analysis engine itself requires Node.js 22 or later, whichever CLI you run it from. Separately, the Python CLI (socketcli) checks that Node.js and uv are on your PATH and exits early if either is missing; the Node CLI has no such pre-check.

There are also some requirements that depend on the programming language(s) used in the project scanned by the reachability analysis.

Language-specific Requirements

  • Maven, Gradle, and sbt (Java, Kotlin, Scala)
    • Java 8 to 27
    • With --dynamic-sbom-inference, the Java version and build tool your project builds with (Gradle, sbt, or Maven, or the project's wrapper)
  • Python
    • Python 3.11 or newer. PyPy is recommended, as it can speed up the analysis 2-3x
    • uv version 0.6.8 or newer
  • Nuget (C#)
    • .NET 6 or newer
    • With --dynamic-sbom-inference, the .NET SDK your project builds with, able to restore its packages
  • Go
    • Same version as used to build the project
  • Cargo (Rust)
    • For your project: the toolchain it selects (such as from rust-toolchain.toml, or the rustup default), Rust 1.74 or newer, able to resolve its crates (including any mirrors or source replacement in .cargo/config.toml) and run its build scripts and procedural macros
    • For the analysis: the rust-src component on your project's toolchain, which the analysis installs if it is missing. If your network restricts outbound traffic, install it beforehand by running rustup component add rust-src in your project directory
    • The analysis uses the workspace's Cargo.lock, and generates one in the workspace root if it is missing
📘

Which Rust build is analyzed

By default, each workspace member is analyzed with its default features, for the target that Cargo builds for by default (CARGO_BUILD_TARGET or build.target if set, otherwise the host). Shipped code, tests, and build scripts are analyzed separately.

To analyze a different build, set SOCKET_REACH_CARGO_BUILD_OPTS to the cargo build options for it:

export SOCKET_REACH_CARGO_BUILD_OPTS="--features tls --target x86_64-unknown-linux-gnu"
socket scan create --reach   # or: socketcli --reach

Accepted options select the features, one --target, the profile, and which of the package's targets to build (such as --tests), plus --workspace, --locked, --frozen, and --offline. Any other option stops the analysis with an error. With --tests or --all-targets, the tests and build scripts are analyzed, and the shipped code is not analyzed separately.

Network Access and Caching

Both CLIs download the analysis engine from Socket the first time they run a given engine version, and the engine then downloads the analyzers it needs the same way. If your network restricts outbound traffic, allow HTTPS to storage.googleapis.com.

socket fix runs the same engine, so it needs the same access.

The downloads are cached in ${XDG_CACHE_HOME:-~/.cache}/socket/coana, which must be writable. Later runs of the same engine version skip the download.

For any project built with Gradle, sbt, Maven, or .NET, we recommend adding --dynamic-sbom-inference to your reachability scans with the Node CLI:

socket scan create --reach --dynamic-sbom-inference

--dynamic-sbom-inference has your build tool generate a Socket facts file as part of the scan, covering every Gradle, sbt, Maven, and .NET build (solution or project) under the scan target rather than only the one at the scan root. That gives you two things:

  • Per-subproject analysis — reachability for those builds is analyzed and reported per subproject rather than as a single unit. This applies to a single multi-module build as much as to a repository containing several independent builds, including builds that share a directory. On large repositories it is also considerably faster (see Project structure under Factors Affecting Performance).
  • More accurate results — the dependency graph comes from the build tool that resolves it, and it records where each dependency actually lives, so the analysis can reliably install the dependencies it needs.

Note: The flag applies to the maven and nuget ecosystems only — Socket's names for the JVM ecosystem (Gradle, sbt, and Maven builds alike) and for .NET. Your npm, PyPI, Go and other dependencies are unaffected and behave exactly as they would without the flag, both in the scan and in the reachability analysis.

For those builds, reachability then works from the generated files rather than the manifest files in your project (such as pom.xml, gradle.lockfile, libs.versions.toml, *.csproj, or packages.lock.json), so you don't need --reach-use-only-pregenerated-sboms to get that effect for them. Any per-project defaults you've configured in a socket.json file are applied to each build; for a repository with several builds, the socket manifest setup --dynamic-sbom-inference wizard configures them one build at a time.

If no Gradle, sbt, Maven, or .NET build is found anywhere under the target, the scan stops with an error rather than continuing silently — either you are not scanning the intended directory (use --cwd), or this repository has no JVM or .NET build and the flag should be dropped.

By default the flag covers every ecosystem it supports. To generate Socket facts for only some of them, pass --dynamic-sbom-inference-ecosystems with a comma-separated list of maven and nuget, as for --reach-ecosystems. Builds of the ecosystems you leave out are scanned and analyzed from their manifest files, as without the flag.

The Python CLI (socketcli) has no equivalent flag. You can still get the accurate per-build dependency graphs by pre-generating the files with the Node CLI's socket manifest dynamic-sbom-inference before running socketcli --reach; the per-subproject analysis is Node CLI only.

⚠️ Without --dynamic-sbom-inference, a dependency manifest must be generated before the reachability analysis runs for any sbt project, or any Gradle project without a gradle.lockfile or libs.versions.toml. You can pre-generate the manifests yourself by running socket manifest dynamic-sbom-inference (or socket manifest gradle / socket manifest scala for a single build) before the scan; learn how on this page. Note that libs.versions.toml has some limitations — for the most accurate reachability results, generate a Socket facts file (or, if you prefer a committed file, use a gradle.lockfile).

To create a scan with reachability information, run the CLI from your project directory (with the Node CLI on a Gradle, sbt, Maven, or .NET project, add --dynamic-sbom-inference as described above):

Node CLI

socket scan create --reach

Python CLI

export SOCKET_SECURITY_API_TOKEN=<your-token>
socketcli --reach

Both commands run the analysis locally and then submit a full scan to Socket. The Python CLI derives your organization from the API token and auto-detects the repository and branch from git; the Node CLI uses the organization configured by socket login (or --org).

During analysis, the reachability results are written to a .socket.facts.json file in the analyzed directory (your current working directory by default). The Node CLI (socket) deletes this file once the scan completes successfully; pass --reach-retain-facts-file to keep it for inspecting or debugging the reachability output.

⚠️

Warning: If you retain the .socket.facts.json file, delete or move it before you run a fresh scan. Later reachability scans with the Node CLI ignore it, but a scan without --reach uploads it as an SBOM, so that scan would show the old file's reachability results.

Command-line flags

The reachability flags used in the examples below (such as --reach-analysis-timeout, --reach-analysis-memory-limit, --reach-concurrency, and --exclude-paths) work the same way in both CLIs. A few flags are available in only one of them:

PurposeNode CLI (socket)Python CLI (socketcli)
Minimum CVE severity to report(not available)--reach-min-severity
Reachability output file(always .socket.facts.json)--reach-output-file
Per-build SBOM generation for Gradle, sbt, Maven, and .NET--dynamic-sbom-inference(not available — pre-generate with socket manifest dynamic-sbom-inference)

For the complete, up-to-date flag list, see each CLI's reference: the Node socket scan create reference and the Python CLI reference.

Resource and Performance Requirements

Full application reachability analysis is compute-intensive, with resource requirements varying by ecosystem and project size. This section provides guidance on memory allocation and expected analysis times.

Factors Affecting Performance

Several factors influence the resource requirements and duration of the reachability analysis:

Language type

Dynamically typed languages such as JavaScript, Python, and Ruby are computationally more expensive to analyze than statically typed languages such as Java and Rust. Static type information allows the analysis to more precisely determine which functions may be called, reducing the amount of code that needs to be considered.

Program size

Larger programs require more resources. Program size includes not only your application code but also the size of your dependencies. A small application with many large dependencies may take longer to analyze than a large application with few dependencies.

Number of CVEs

The number of CVEs in your dependency graph affects performance. More CVEs typically means the analysis must consider a larger fraction of the codebase to determine reachability for each vulnerability.

Project structure

Splitting applications into smaller subprojects or workspaces typically results in better performance than having everything in a single project. For example, a JavaScript project with 5 million lines of code can be very computationally intensive to analyze as a single unit. However, if those 5 million lines are split across 100 workspaces, the analysis can process each workspace independently, which is typically much faster overall.

Memory Requirements

All ecosystems require a minimum of 8 GB of memory. The recommended memory allocation depends on the ecosystem and project size:

EcosystemMinimum MemoryRecommended Memory
npm8 GB32 GB (64 GB for very large projects)
Python8 GB32 GB
Ruby8 GB32 GB
Go8 GB16 GB
Maven8 GB16 GB
NuGet8 GB16 GB
Cargo8 GB32 GB

Expected Analysis Time

The table below shows expected analysis times across different ecosystems. Times are reported as percentiles across all scanned projects.

EcosystemP50 (Median)P90P99
npm1 min10 min40 min
Python1 min3 min30 min
Ruby1 min3 min30 min
Go1 min3 min30 min
Maven1 min3 min20 min
NuGet1 min3 min20 min
Cargo1 min3 min30 min
📘

The reported times are per-project. If scanning a repository containing multiple subprojects (a monorepo), you need to multiply by the number of subprojects. Using the --reach-concurrency flag may be beneficial in this scenario.

Troubleshooting Analysis Timeouts

If the reachability analysis is running slower than expected or is timing out, consider the following options:

Increase the analysis timeout

Use --reach-analysis-timeout to extend the analysis timeout beyond the default of 10 minutes. Specify the duration as a number followed by a s, m, or h unit (for example 90s, 10m, or 1h). When increasing the timeout, it is recommended to also allocate additional memory—approximately 10 GB of extra memory per additional 10 minutes of timeout.

socket scan create --reach --reach-analysis-timeout 20m

Increase analysis memory

Use --reach-analysis-memory-limit to increase the maximum available memory to the analysis (default is 8GB). Specify the memory as a number followed by an MB or GB unit (for example 512MB or 8GB). If running in CI, remember to consider if you need to use a larger runner.

socket scan create --reach --reach-analysis-memory-limit 32GB

Enable parallel workspace processing

Use the --reach-concurrency flag to process multiple workspaces in parallel. This is useful for projects that contain multiple subprojects or workspaces, such as projects using npm workspaces or monorepos with subprojects located in different subdirectories.

socket scan create --reach --reach-concurrency 4
⚠️

The --reach-analysis-memory-limit flag applies to each concurrent instance. For example, if you allocate 16 GB of memory per instance and run 4 concurrent instances, you should run the analysis on a machine with at least 64 GB of memory.


How Full Application Function-level Reachability Works

1. Invoking the scan

The analysis is started using the Socket CLI as described above. You can set up the scan to run at regular intervals in your CI system or be triggered by other events depending on policy.

2. Scanning for CVEs

The analysis identifies all manifest files (package.json, go.mod, Gemfile, pom.xml, build.gradle, and others) in your application. From these files, a complete list of direct and transitive dependencies, along with the dependency graph that connects them, is extracted.

Socket scans for CVEs in the dependency graph using a standard vulnerability scan.

3. Computing Vulnerability Reachability

For every detected CVE, a static analysis is performed to check the reachability of the affected functions (You can learn more about Socket's static reachability analysis here).

This step involves constructing a model of your application called a call graph, which represents which functions call other functions throughout the application. Depending on the size and complexity of your codebase, this process may require significant memory and CPU resources, and can take up to a few minutes to complete for some CVEs.

4. Reachable vs Unreachable CVEs

If the affected function(s) are unreachable, the CVE is marked as unreachable. Unreachable CVEs are safe to ignore, as the vulnerable code cannot be invoked at runtime.

If the CVE is reachable through one or more paths, the vulnerability is flagged as reachable. For reachable CVEs, Socket shows the list of function calls in your dependencies that may trigger the vulnerability.

Limitations

See the Static Reachability Analysis for more information about what the static reachability analysis can and cannot detect.

FAQ

How does Socket determine which functions are affected by a CVE?

Socket records this in a reachability specification for each vulnerability. By default, only human-verified specifications are used; organizations can opt in to also use AI-generated specifications for broader coverage, at a slightly higher risk of an incorrect result. You can learn more about how the Socket team identifies functions affected by vulnerabilities in the FAQ section of the Static Reachability Analysis page.

How does Full Application Reachability compare to Precomputed Reachability

Precomputed reachability analysis considers only the code within your dependencies, whereas the full application analysis also scans your application’s own source code. While the full application analysis provides better noise reduction and richer context for triaging reachable vulnerabilities, it comes with some trade-offs: it requires manual setup and is generally slower, as the static analysis is compute-intensive.


Did this page help you?