curl --request POST \
--url https://api.scanoss.com/v3/cryptography/reachability/dep-tree \
--header 'Content-Type: application/json' \
--data '
{
"dependencies": [
{
"purl": "pkg:maven/org.bouncycastle/bcprov-jdk18on",
"requirement": "=1.78.1"
},
{
"purl": "pkg:maven/com.google.crypto.tink/tink",
"requirement": ">=1.13.0,<2.0.0"
}
],
"include_call_chains": true,
"include_supporting_calls": true
}
'import requests
url = "https://api.scanoss.com/v3/cryptography/reachability/dep-tree"
payload = {
"dependencies": [
{
"purl": "pkg:maven/org.bouncycastle/bcprov-jdk18on",
"requirement": "=1.78.1"
},
{
"purl": "pkg:maven/com.google.crypto.tink/tink",
"requirement": ">=1.13.0,<2.0.0"
}
],
"include_call_chains": True,
"include_supporting_calls": True
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
dependencies: [
{purl: 'pkg:maven/org.bouncycastle/bcprov-jdk18on', requirement: '=1.78.1'},
{purl: 'pkg:maven/com.google.crypto.tink/tink', requirement: '>=1.13.0,<2.0.0'}
],
include_call_chains: true,
include_supporting_calls: true
})
};
fetch('https://api.scanoss.com/v3/cryptography/reachability/dep-tree', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scanoss.com/v3/cryptography/reachability/dep-tree",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'dependencies' => [
[
'purl' => 'pkg:maven/org.bouncycastle/bcprov-jdk18on',
'requirement' => '=1.78.1'
],
[
'purl' => 'pkg:maven/com.google.crypto.tink/tink',
'requirement' => '>=1.13.0,<2.0.0'
]
],
'include_call_chains' => true,
'include_supporting_calls' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scanoss.com/v3/cryptography/reachability/dep-tree"
payload := strings.NewReader("{\n \"dependencies\": [\n {\n \"purl\": \"pkg:maven/org.bouncycastle/bcprov-jdk18on\",\n \"requirement\": \"=1.78.1\"\n },\n {\n \"purl\": \"pkg:maven/com.google.crypto.tink/tink\",\n \"requirement\": \">=1.13.0,<2.0.0\"\n }\n ],\n \"include_call_chains\": true,\n \"include_supporting_calls\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.scanoss.com/v3/cryptography/reachability/dep-tree")
.header("Content-Type", "application/json")
.body("{\n \"dependencies\": [\n {\n \"purl\": \"pkg:maven/org.bouncycastle/bcprov-jdk18on\",\n \"requirement\": \"=1.78.1\"\n },\n {\n \"purl\": \"pkg:maven/com.google.crypto.tink/tink\",\n \"requirement\": \">=1.13.0,<2.0.0\"\n }\n ],\n \"include_call_chains\": true,\n \"include_supporting_calls\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scanoss.com/v3/cryptography/reachability/dep-tree")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"dependencies\": [\n {\n \"purl\": \"pkg:maven/org.bouncycastle/bcprov-jdk18on\",\n \"requirement\": \"=1.78.1\"\n },\n {\n \"purl\": \"pkg:maven/com.google.crypto.tink/tink\",\n \"requirement\": \">=1.13.0,<2.0.0\"\n }\n ],\n \"include_call_chains\": true,\n \"include_supporting_calls\": true\n}"
response = http.request(request)
puts response.read_body{
"rules_version": "v1.19.0",
"info_message": "2 of 2 dependencies returned data",
"data": [
{
"purl": "pkg:maven/org.bouncycastle/bcprov-jdk18on",
"version": "1.78.1",
"requirement": "=1.78.1",
"requested_version": "1.78.1",
"resolved_version": "1.78.1",
"fallback": false,
"method": "exact",
"info_code": "READY",
"finding_count": 1,
"schemas": {
"findings": "1.5",
"callgraph": "6.10"
},
"findings": [
{
"file_path": "core/src/main/java/org/bouncycastle/crypto/util/CipherFactory.java",
"language": "java",
"cryptographic_assets": [
{
"finding_id": "8f3a2c41",
"match": "cipher = new CBCBlockCipher(new AESEngine());",
"source": "direct",
"start_line": 92,
"end_line": 92,
"metadata": {
"assetType": "algorithm",
"algorithmName": "AES",
"algorithmFamily": "AES",
"algorithmPrimitive": "block-cipher",
"algorithmMode": "CBC",
"api": "org.bouncycastle.crypto.engines.AESEngine",
"library": "bouncycastle"
},
"reachability": "reachable",
"call_chains": [
[
{
"function_name": "org.bouncycastle.crypto.util.CipherFactory.createContentCipher",
"canonical_signature": "org.bouncycastle.crypto.util.CipherFactory#createContentCipher(boolean,CipherParameters,AlgorithmIdentifier):Object",
"return_type": "Object",
"parameter_types": [
"boolean",
"CipherParameters",
"AlgorithmIdentifier"
],
"visibility": "public",
"file_path": "core/src/main/java/org/bouncycastle/crypto/util/CipherFactory.java",
"start_line": 39
}
]
],
"supporting_call_ids": [
"sup-init-001"
]
}
]
}
],
"supporting_calls": [
{
"supporting_id": "sup-init-001",
"function_name": "org.bouncycastle.crypto.BufferedBlockCipher.init",
"canonical_signature": "org.bouncycastle.crypto.BufferedBlockCipher#init(boolean,CipherParameters):void",
"category": "config",
"file_path": "core/src/main/java/org/bouncycastle/crypto/util/CipherFactory.java",
"start_line": 49,
"end_line": 49
}
]
},
{
"purl": "pkg:maven/com.google.crypto.tink/tink",
"version": "1.13.0",
"requirement": ">=1.13.0,<2.0.0",
"requested_version": ">=1.13.0,<2.0.0",
"resolved_version": "1.13.0",
"fallback": false,
"method": "range",
"info_code": "READY",
"finding_count": 1,
"schemas": {
"findings": "1.5",
"callgraph": "6.10"
},
"findings": [
{
"file_path": "src/main/java/com/google/crypto/tink/subtle/AesGcmJce.java",
"language": "java",
"cryptographic_assets": [
{
"finding_id": "c47d9e02",
"match": "Cipher cipher = Cipher.getInstance(\"AES/GCM/NoPadding\");",
"source": "direct",
"start_line": 61,
"end_line": 61,
"metadata": {
"assetType": "algorithm",
"algorithmName": "AES-256-GCM",
"algorithmFamily": "AES",
"algorithmPrimitive": "ae",
"algorithmMode": "GCM",
"api": "javax.crypto.Cipher.getInstance",
"library": "jca"
},
"reachability": "reachable",
"call_chains": [
[
{
"function_name": "com.google.crypto.tink.subtle.AesGcmJce.encrypt",
"canonical_signature": "com.google.crypto.tink.subtle.AesGcmJce#encrypt(byte[],byte[]):[B",
"return_type": "byte[]",
"parameter_types": [
"byte[]",
"byte[]"
],
"visibility": "public",
"file_path": "src/main/java/com/google/crypto/tink/subtle/AesGcmJce.java",
"start_line": 55
}
]
]
}
]
}
]
}
],
"info_code": "READY",
"status": {
"status": "SUCCESS",
"message": "Reachability computed"
}
}Reachability for a caller-supplied frozen dependency tree.
A batch of independent GetComponentReachability evaluations. The
dependencies field is a FLAT list of already-resolved components; the
server does not auto-resolve the list itself.
Every requested dependency yields exactly one data[] block, in
request order, carrying its own info_code. A dependency without
data no longer suppresses the others — branch on each block’s
info_code, not on the envelope’s.
Each block reports that component’s full contained tree: its own crypto
plus crypto reached through its own recorded dependency closure
(source: "indirect").
Exact versions in the request are treated as globally authoritative and
are applied wherever that component appears, including inside another
root’s closure — see applied_dependency_overrides. Two different
exact versions for one component reject the request with
INVALID_REQUEST.
Best-effort stored membership plus client pins; not Maven-coherent re-resolution.
curl --request POST \
--url https://api.scanoss.com/v3/cryptography/reachability/dep-tree \
--header 'Content-Type: application/json' \
--data '
{
"dependencies": [
{
"purl": "pkg:maven/org.bouncycastle/bcprov-jdk18on",
"requirement": "=1.78.1"
},
{
"purl": "pkg:maven/com.google.crypto.tink/tink",
"requirement": ">=1.13.0,<2.0.0"
}
],
"include_call_chains": true,
"include_supporting_calls": true
}
'import requests
url = "https://api.scanoss.com/v3/cryptography/reachability/dep-tree"
payload = {
"dependencies": [
{
"purl": "pkg:maven/org.bouncycastle/bcprov-jdk18on",
"requirement": "=1.78.1"
},
{
"purl": "pkg:maven/com.google.crypto.tink/tink",
"requirement": ">=1.13.0,<2.0.0"
}
],
"include_call_chains": True,
"include_supporting_calls": True
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
dependencies: [
{purl: 'pkg:maven/org.bouncycastle/bcprov-jdk18on', requirement: '=1.78.1'},
{purl: 'pkg:maven/com.google.crypto.tink/tink', requirement: '>=1.13.0,<2.0.0'}
],
include_call_chains: true,
include_supporting_calls: true
})
};
fetch('https://api.scanoss.com/v3/cryptography/reachability/dep-tree', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scanoss.com/v3/cryptography/reachability/dep-tree",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'dependencies' => [
[
'purl' => 'pkg:maven/org.bouncycastle/bcprov-jdk18on',
'requirement' => '=1.78.1'
],
[
'purl' => 'pkg:maven/com.google.crypto.tink/tink',
'requirement' => '>=1.13.0,<2.0.0'
]
],
'include_call_chains' => true,
'include_supporting_calls' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scanoss.com/v3/cryptography/reachability/dep-tree"
payload := strings.NewReader("{\n \"dependencies\": [\n {\n \"purl\": \"pkg:maven/org.bouncycastle/bcprov-jdk18on\",\n \"requirement\": \"=1.78.1\"\n },\n {\n \"purl\": \"pkg:maven/com.google.crypto.tink/tink\",\n \"requirement\": \">=1.13.0,<2.0.0\"\n }\n ],\n \"include_call_chains\": true,\n \"include_supporting_calls\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.scanoss.com/v3/cryptography/reachability/dep-tree")
.header("Content-Type", "application/json")
.body("{\n \"dependencies\": [\n {\n \"purl\": \"pkg:maven/org.bouncycastle/bcprov-jdk18on\",\n \"requirement\": \"=1.78.1\"\n },\n {\n \"purl\": \"pkg:maven/com.google.crypto.tink/tink\",\n \"requirement\": \">=1.13.0,<2.0.0\"\n }\n ],\n \"include_call_chains\": true,\n \"include_supporting_calls\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scanoss.com/v3/cryptography/reachability/dep-tree")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"dependencies\": [\n {\n \"purl\": \"pkg:maven/org.bouncycastle/bcprov-jdk18on\",\n \"requirement\": \"=1.78.1\"\n },\n {\n \"purl\": \"pkg:maven/com.google.crypto.tink/tink\",\n \"requirement\": \">=1.13.0,<2.0.0\"\n }\n ],\n \"include_call_chains\": true,\n \"include_supporting_calls\": true\n}"
response = http.request(request)
puts response.read_body{
"rules_version": "v1.19.0",
"info_message": "2 of 2 dependencies returned data",
"data": [
{
"purl": "pkg:maven/org.bouncycastle/bcprov-jdk18on",
"version": "1.78.1",
"requirement": "=1.78.1",
"requested_version": "1.78.1",
"resolved_version": "1.78.1",
"fallback": false,
"method": "exact",
"info_code": "READY",
"finding_count": 1,
"schemas": {
"findings": "1.5",
"callgraph": "6.10"
},
"findings": [
{
"file_path": "core/src/main/java/org/bouncycastle/crypto/util/CipherFactory.java",
"language": "java",
"cryptographic_assets": [
{
"finding_id": "8f3a2c41",
"match": "cipher = new CBCBlockCipher(new AESEngine());",
"source": "direct",
"start_line": 92,
"end_line": 92,
"metadata": {
"assetType": "algorithm",
"algorithmName": "AES",
"algorithmFamily": "AES",
"algorithmPrimitive": "block-cipher",
"algorithmMode": "CBC",
"api": "org.bouncycastle.crypto.engines.AESEngine",
"library": "bouncycastle"
},
"reachability": "reachable",
"call_chains": [
[
{
"function_name": "org.bouncycastle.crypto.util.CipherFactory.createContentCipher",
"canonical_signature": "org.bouncycastle.crypto.util.CipherFactory#createContentCipher(boolean,CipherParameters,AlgorithmIdentifier):Object",
"return_type": "Object",
"parameter_types": [
"boolean",
"CipherParameters",
"AlgorithmIdentifier"
],
"visibility": "public",
"file_path": "core/src/main/java/org/bouncycastle/crypto/util/CipherFactory.java",
"start_line": 39
}
]
],
"supporting_call_ids": [
"sup-init-001"
]
}
]
}
],
"supporting_calls": [
{
"supporting_id": "sup-init-001",
"function_name": "org.bouncycastle.crypto.BufferedBlockCipher.init",
"canonical_signature": "org.bouncycastle.crypto.BufferedBlockCipher#init(boolean,CipherParameters):void",
"category": "config",
"file_path": "core/src/main/java/org/bouncycastle/crypto/util/CipherFactory.java",
"start_line": 49,
"end_line": 49
}
]
},
{
"purl": "pkg:maven/com.google.crypto.tink/tink",
"version": "1.13.0",
"requirement": ">=1.13.0,<2.0.0",
"requested_version": ">=1.13.0,<2.0.0",
"resolved_version": "1.13.0",
"fallback": false,
"method": "range",
"info_code": "READY",
"finding_count": 1,
"schemas": {
"findings": "1.5",
"callgraph": "6.10"
},
"findings": [
{
"file_path": "src/main/java/com/google/crypto/tink/subtle/AesGcmJce.java",
"language": "java",
"cryptographic_assets": [
{
"finding_id": "c47d9e02",
"match": "Cipher cipher = Cipher.getInstance(\"AES/GCM/NoPadding\");",
"source": "direct",
"start_line": 61,
"end_line": 61,
"metadata": {
"assetType": "algorithm",
"algorithmName": "AES-256-GCM",
"algorithmFamily": "AES",
"algorithmPrimitive": "ae",
"algorithmMode": "GCM",
"api": "javax.crypto.Cipher.getInstance",
"library": "jca"
},
"reachability": "reachable",
"call_chains": [
[
{
"function_name": "com.google.crypto.tink.subtle.AesGcmJce.encrypt",
"canonical_signature": "com.google.crypto.tink.subtle.AesGcmJce#encrypt(byte[],byte[]):[B",
"return_type": "byte[]",
"parameter_types": [
"byte[]",
"byte[]"
],
"visibility": "public",
"file_path": "src/main/java/com/google/crypto/tink/subtle/AesGcmJce.java",
"start_line": 55
}
]
]
}
]
}
]
}
],
"info_code": "READY",
"status": {
"status": "SUCCESS",
"message": "Reachability computed"
}
}Body
Request body for dep-tree reachability. There is no root field —
the dependency tree IS the unit. Supply the flat list of dependencies
to stitch; no application identity is required.
Flat list of every (purl, version) to be stitched. Every entry
MUST carry a version, either as an exact pin (=1.5.2) or as a
SemVer constraint expression (>=1.0, ^2.0, ~1.5).
Range constraints resolve to the mined version nearest their lower
bound (the highest when they have none). The server does NOT
auto-resolve transitive deps.
Show child attributes
Show child attributes
Optional exact-match filter on entry-point canonical signatures.
When non-empty, findings[] is restricted to assets reachable
from at least one supplied entry point. Findings unreachable
from any supplied entry are REMOVED entirely — they do NOT appear
as reachability: unreachable entries. An empty array (or absent
field) means no filter; all findings are returned.
Matching is against crypto_entry_points[].canonical_signature,
so every entry point the service can publish is a usable filter
value — including the majority that head none of the emitted
call_chains[]. Supply the signature exactly as that field
spells it, spaces included.
Signatures matching no entry point in any block are listed in
unmatched_signatures at the top level of the response
(diagnostic for typos).
When true, decorates each asset with its call_chains[] array
(raw callgraph 6.x frame arrays) and the reachability verdict.
Default false produces a pure CBOM response (findings without
reachability decoration). Independent of entry_point_signatures
(which controls whether assets are PRUNED to reachable ones).
Independent of include_crypto_entry_points and
include_supporting_calls.
When true, populates crypto_entry_points[] at the top level
of each ComponentData block — the public reachability surface
(entry-point functions with their reachable_findings[]).
This is the projection that replaced the legacy
entry_point_index field.
Independent of include_call_chains and include_supporting_calls.
When true, populates supporting_calls[] at the top level of
each ComponentData block (deduped object-lifecycle calls such
as IV generation and key-size initialisation) AND attaches
supporting_call_ids[] to each cryptographic_asset whose
finding graph references supporting calls. Each
supporting_call_id resolves to a supporting_calls[].supporting_id
in the same block.
Independent of include_call_chains and include_crypto_entry_points.
When true, attaches a bounded forward_calls graph to each asset.
When false or absent, responses retain their previous shape.
Optional forward traversal depth. Applies only when
include_forward_calls: true. When omitted, the producer default
of 4 is used. Values outside 1..16 are rejected with HTTP 400.
1 <= x <= 16Per-asset cap on call_chains[] length. Hard cap 128. 0 (the
default) applies no cap here, but the traversal already bounds chains
at 128 per finding, so 128 is the ceiling either way. Positive
integer asks for fewer.
0 <= x <= 128Response
Request processed. Inspect info_code for READY / error.
Response envelope for dep-tree reachability. Top-level shape:
{data, info_code, info_message, missing_components, rules_version, status, unmatched_signatures, callgraph}.
There is no root field — the dependency tree is self-contained.
This endpoint is a batch of independent /component evaluations.
data has exactly one ComponentData block per supplied dependency,
in request order, and each block carries its OWN info_code. One
dependency lacking data never suppresses another's: expect blocks with
findings and blocks without in the same response, and branch per block
rather than on the envelope. Component identity (purl, version,
requirement) lives inside each data[] element, not at the top level.
Each block reports that component's full contained tree — its own
crypto plus crypto reached through its own recorded dependency closure
(source: "indirect"). There is no cross-set stitch over the supplied
list: a chain A→B→C is reported inside A's block, whether or not C was
requested.
Client-resolved versions are global. Every exact version in
dependencies[] is treated as authoritative for that component
wherever it appears, including inside another root's closure. Supplying
two different exact versions for the same component rejects the whole
request with INVALID_REQUEST. Identical duplicate entries are legal
and collapse into a single block, in first-occurrence order.
This is best-effort membership from a flattened dependency store plus the client's pins. It is not Maven-coherent re-resolution and does not reconstruct direct-edge lineage or dependency mediation.
unmatched_signatures and callgraph live at the TOP LEVEL.
Envelope summary only — read data[].info_code for outcomes.
READY— at least one block isREADY(bucket-fallback results areREADYblocks and count).NO_INFO— the request was well-formed but no block carries data.INVALID_REQUEST— emptydependenciesarray, or two different exact versions supplied for the same component.
Per-dependency conditions never appear here and never reject the request. Whole-request rejection is reserved for malformed requests and conflicting client version authority.
READY, INVALID_PURL, INVALID_SEMVER, COMPONENT_NOT_FOUND, VERSION_NOT_FOUND, UNSUPPORTED_SCHEMA, NO_INFO, DEPENDENCY_UNRESOLVED, INVALID_REQUEST Top-level outcome for the request as a whole.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Signatures from entry_point_signatures that matched zero chains
in EVERY data-bearing block.
Raw merged callgraph as JSON, populated only when
include_raw_callgraph: true. Shape: crypto-finder callgraph
6.x verbatim.
Highest rules_version among the dependency rows that contributed
to this response. Dependencies may have been mined at different
points in time under different rules_versions; this field reports
the most recent contributor (by mining created_at), NOT a
uniform "all deps under this version" guarantee. Use this when
comparing two dep-tree responses to detect whether new rules
have landed since the last call. Present only when at least one
block is data-bearing.
"v1.19.0"
Convenience summary listing the resolved (purl, version) of
exactly those dependencies whose block carries
info_code: NO_INFO. The per-block info_code is authoritative —
this list is a shortcut, not a separate verdict, and it does not
cover blocks that failed for other reasons
(VERSION_NOT_FOUND, UNSUPPORTED_SCHEMA, INVALID_PURL).
Show child attributes
Show child attributes
Summary of how many dependencies returned data, e.g.
"3 of 4 dependencies returned data".
"3 of 4 dependencies returned data"