Scenario 20 helps engineers and AppSec specialists examine third-party packages: which dependencies the project uses, where known vulnerabilities were found, and which licenses are listed for the packages. Results can be collected into an SBOM — a software bill of materials — and used when choosing updates.
Start with the dependency inventory. For example, a server library belongs to the application, while the TypeScript compiler is used during development. The development-dependency filter produces the lists needed for each task. Then compare packages against a vulnerability feed and the project’s license rules.
Choose an analysis workflow
| Task | Workflow | Result |
|---|---|---|
| Local manifest inventory | Python: DependencyGraphBuilder.scan_project() |
Package names, version specifications, and direct/development flags. A complete example follows. |
| Vulnerability checks | SCA and SBOM | An SBOM and OSV report based on the project lockfile. |
| License checks | python -m src.cli deps licenses |
License identifiers compared with project rules. |
| Registered-project SCA | /api/v1/security/sca/projects/{project_name}/... |
Inventory, vulnerabilities, and SBOM for a project in the server registry. |
| AppSec analysis of the results | Typed Scenario 20 invocation | An answer for the task with references to the inventory and reports. |
Follow a concrete inventory example
Prepare the project Python environment using the CLI guide. From the CodeGraph repository root, create a dependency_example directory and save this manifest as dependency_example/package.json:
{
"name": "dependency-example",
"version": "1.0.0",
"dependencies": {
"express": "4.18.2"
},
"devDependencies": {
"typescript": "5.4.5"
}
}
Save the following program as dependency_inventory.py in the repository root:
import json
from src.dependencies import DependencyGraphBuilder
builder = DependencyGraphBuilder()
for include_dev in (True, False):
graph = builder.scan_project("dependency_example", include_dev=include_dev, max_depth=10)
packages = sorted(
({"name": dep.name, "version_spec": dep.version_spec,
"is_dev": dep.is_dev, "is_direct": dep.is_direct}
for dep in graph.dependencies.values()),
key=lambda dep: dep["name"],
)
print(json.dumps({"include_dev": include_dev, "files": len(graph.files),
"packages": packages}))
Run it in PowerShell:
python dependency_inventory.py
The program prints two JSON objects. Both report one manifest in files. With include_dev=true, packages contains express with version specification 4.18.2 and typescript with 5.4.5. With include_dev=false, it contains only express. Both packages are direct dependencies; typescript has is_dev=true.
scan_project discovers supported manifest files, selects their parsers and adds the parsed dependencies to the inventory. It applies the development filter while adding packages. This call reads the manifest and returns the graph in memory. Vulnerability-feed lookups and license assessment are separate steps. The two versions above are fixed example inputs for parsing, rather than version recommendations.
Check vulnerabilities and licenses through the CLI
For a vulnerability report and package inventory export, follow the SCA and SBOM guide. It shows how to prepare a lockfile, generate an SBOM, and check it against OSV. Keep the report with the project revision, analysis settings, and exit code so you can compare results after updating a package.
In the current version, deps check-vulns stops with ValueError when OSV returns a finding with severity unknown; no JSON report is written. This command is excluded from this page’s executable instructions.
For a license check, switch to the project root. Make CodeGraph available to Python through the installed package or PYTHONPATH, and prepare the local config.yaml as described in the CLI guide. The command reads manifests in the current directory:
python -m src.cli deps licenses --check-compliance --allow MIT Apache-2.0 --deny GPL-3.0
Set the allowed and denied licenses from your project’s rules. The command compares identifiers from manifests and lockfiles with these lists. For example, a package licensed under ISC is reported with not in allowed list for the shown MIT Apache-2.0 allowlist; the command returns exit code 1. An allowed MIT package does not produce that violation.
The check processes packages with a populated license field. It skips UNKNOWN when comparing the lists. If the license is absent, obtain its identifier from the package source and complete the inventory before assessment.
In the current version, deps scan, deps list, deps graph, deps health, and deps update fail with AttributeError. Use the Python example above for the inventory; these five CLI commands are excluded from this page’s executable instructions.
Account for network, cache, and freshness
The checker uses OSV, a database of known vulnerabilities, by default. A lookup needs outbound network access unless a matching entry is available in the local cache. Additional sources for the registered-project audit are enabled through configuration: GitHub Advisory uses GITHUB_TOKEN, and NVD uses NVD_API_KEY.
Keep the enabled sources, query time, response timeout, cache path, and cache TTL — the entry’s retention period — with the report. Record the entry’s age for a cached result. If a feed fails, retain its error message and repeat the check after restoring access so the report stays linked to the data actually received.
Retrieve results through the REST API
The REST API is available under /api/v1/security/sca. Prepare a registered project with its source_path and sign in as a user with project access. Use the access token returned by POST /api/v1/auth/token. For an integration with an issued API key, use X-API-Key instead of the Bearer header. Authentication routes are listed in the REST API reference.
The read routes use local SCA results. If there is no saved summary, CodeGraph reads manifests from source_path and builds an inventory. These GET requests use locally stored vulnerability data and do not query external feeds.
GET /api/v1/security/sca/projects/{project_name}/summary— the summary and its data status.GET /api/v1/security/sca/projects/{project_name}/dependencies— the paginated package list.GET /api/v1/security/sca/projects/{project_name}/vulnerabilities— findings from local SCA results.GET /api/v1/security/sca/projects/{project_name}/sbom— SBOM export;formatselectsspdx(the default) orcyclonedx.
In PowerShell, set the server URL without a trailing slash, the registered project name, and its UUID. Load the access token into CODEGRAPH_ACCESS_TOKEN through your approved configuration channel. This example gets the summary and the first page of packages:
$api = '<api-base-url>'
$project = [uri]::EscapeDataString('<project-name>')
if (-not $env:CODEGRAPH_ACCESS_TOKEN) { throw 'Access token is not configured' }
$headers = @{
Authorization = "Bearer $env:CODEGRAPH_ACCESS_TOKEN"
'X-Project-Id' = '<project-uuid>'
}
$summary = Invoke-RestMethod -Uri "$api/api/v1/security/sca/projects/$project/summary" -Headers $headers
$dependencies = Invoke-RestMethod -Uri "$api/api/v1/security/sca/projects/$project/dependencies?limit=20&offset=0" -Headers $headers
$summary.scan_status
$dependencies | Select-Object total, limit, offset, has_next, has_prev
$dependencies.items | Select-Object name, version, resolved_version, is_dev, is_direct, license
A collected summary has scan_status=ready. total is the total package count, items is the current page, and has_next indicates whether another page is available. For the next page, increase offset by limit.
For 401, check the credential and authentication method; 404 means an unknown project. Summary states source-path-missing, source-path-invalid, and scan-error indicate an unset path, an unavailable directory, and a parsing error respectively. Keep the response with the project name and source revision.
Run the typed AppSec scenario
Use the configured environment from the programmatic guide, with the accepted AppSec task and required runtime services. Save the example as a Python file and replace its project, namespace, task and evidence-reference placeholders. Configure the LLM for the scenario workflow. Preserve the manifest inventory and feed warnings alongside the answer.
from src.digital_employees.runtime.scenarios import (
RoleBoundScenarioInvocationRequest,
invoke_role_bound_scenario_request,
)
request = RoleBoundScenarioInvocationRequest(
query="Analyze dependency, vulnerability, license, and SBOM risk for the bounded project.",
employee_id="codegraph_appsec",
scenario_id="scenario_20",
event_type="appsec_start",
context={
"project_key": "codegraph",
"namespace": "default",
"task_id": "<task-id>",
"source_refs": ["<revision-ref>", "<dependency-artifact-ref>"],
},
)
result = invoke_role_bound_scenario_request(request)
if result.get("error"):
raise RuntimeError(result["error"])
if not result.get("scenario_id") or not result.get("answer"):
raise RuntimeError("Scenario returned no scenario identity or answer")
print(result["answer"])
In the answer, identify the packages associated with risks, the basis for each conclusion, and the proposed actions. Compare these conclusions with the attached reports. After updating packages, repeat the inventory and vulnerability check to see how the package list and findings have changed.