Dependency vulnerabilities
Shield360 finds vulnerable open-source packages in three ways. All three land in Protect → Application security → Code security, each as its own target:
| Target type | Where the package list comes from | What you install |
|---|---|---|
filesystem, image | shield360 scan in CI or on a laptop | The Shield360 CLI |
runtime | The packages each app’s Shield360 SDK reports from its running process | Nothing more than the SDK |
repository | The lock files of a connected GitHub repository, once you turn it on for that repository | Nothing |
This page covers the two server-side paths, runtime and repository, and the matching they share. Each target keeps the findings of its latest match only, plus a history of its counts.
Runtime packages
Section titled “Runtime packages”Every Shield360 SDK that is given a Shield360 URL and API key reports the packages its process runs: the language runtime and each package’s name and version. The report goes to /api/guard/events with the app’s API key, shortly after the app starts and then once a day.
| SDK | What it reports |
|---|---|
| TypeScript | npm packages loaded through require, plus the app’s direct dependencies as installed |
| Python | The distributions of every module imported so far, then the other installed distributions (importlib.metadata) |
| Go | The modules the binary was built with (runtime/debug.ReadBuildInfo) and the Go version |
| .NET | The NuGet packages of the assemblies loaded, from the app’s .deps.json |
| Java, PHP, Rust | The same report, when runtime protection is on |
Because the list comes from the running process, a finding on a runtime target means the vulnerable package is loaded in that app, not only declared somewhere in a repository.
Turn the report off per app with the SDK option (runtimePackages: false in TypeScript, runtime_packages=False in Python, DisableRuntimePackages in Go, RuntimePackages = false in .NET) or the environment variable SHIELD360_RUNTIME_PACKAGES=off.
What leaves your app
Section titled “What leaves your app”Only package names and versions, the app’s service name, its environment, the host name and the SDK version. No file path, source code, environment variable or configuration value is sent. At most 500 packages are reported per process.
Repository lock files
Section titled “Repository lock files”Repositories you connected for AI code tracking (a GitHub scanner connector with a read-only token) can also have their dependencies scanned. Nothing needs installing in the repository or in CI. The scan is off for every repository until someone with Manage AI app security turns it on for that repository: open Protect → Application security → Code security → Repositories and switch it on for the repository. The same setting is available through the API with PATCH /api/code-security/repositories and a body that names the connector:
{ "connectorId": "<connector id>", "dependencyScan": true }GET /api/code-security/repositories lists the current project’s repositories with their setting and last scan. Every change is recorded in the audit log with the setting before and after. Turning the scan off also deletes what it stored for that repository.
When it is on, Shield360 runs a first scan straight away, then one every day:
- It reads the branch’s head commit (the connector’s branch, or the repository’s default branch) and the list of file names in its tree.
- It fetches only the lock and manifest files below, by blob, through the GitHub API. Nothing is cloned and no other file is read. Files under
node_modules,vendor,dist,build,target,.venvand similar directories are skipped, and the scan reads at most 40 files, each up to 5 MB, 20 MB in total. - It parses them inside Shield360, keeps each package’s name, exact version and the file it came from, and discards the file contents.
- It matches the packages against OSV and stores the result as the repository’s
repositorytarget, namedowner/repo@branch, with the commit.
When the head commit has not moved since the last scan, the stored package list is matched again without reading GitHub, so new advisories still appear.
| Ecosystem | Files read |
|---|---|
| npm | package-lock.json, npm-shrinkwrap.json, pnpm-lock.yaml, yarn.lock (classic and Berry) |
| PyPI | requirements*.txt (pinned == lines only), poetry.lock, Pipfile.lock |
| Go | go.mod (require lines; // indirect marks transitive modules) |
| crates.io | Cargo.lock (registry and git crates; the workspace’s own crates are left out) |
| RubyGems | Gemfile.lock |
| NuGet | packages.lock.json |
| Maven | pom.xml (dependencies with a literal version; ${property} versions are skipped), gradle.lockfile |
Version ranges (such as ^1.2 in a package.json) cannot be matched, so only lock files and pinned versions count. Secret scanning and reading source code are not part of this; use shield360 scan in CI for those.
What leaves your repository
Section titled “What leaves your repository”The repository’s file list for one commit, and the contents of the lock and manifest files above. Shield360 keeps only package names, versions, file paths of those lock files, the branch and the commit. The token stays on the connector and is never shown or logged.
Matching
Section titled “Matching”Once a day Shield360 reads the packages each app reported in the last two days and looks them up in OSV.dev, the open-source vulnerability database run by Google. The result is stored as that app’s runtime target, so an advisory published since yesterday appears without anyone scanning again.
- What Shield360 sends to OSV: package ecosystem, name and version. Never your app, organization, host or file names.
- Caching: OSV’s answers are cached for every organization alike, since they are public data: which advisories affect a package version for 20 hours, and each advisory until OSV reports it changed.
- Severity: computed from the advisory’s CVSS v3 vector (or v2), and otherwise taken from the source database’s own label (for example GitHub’s
MODERATEis shown asMEDIUM). An advisory with neither isUNKNOWN. CVSS v4 vectors are not scored; their database label is used. - Fixed version: the versions the advisory says fix the package, joined when there are several.
- Withdrawn advisories are left out.
- When OSV cannot be reached, nothing is stored for that app, so its previous result stands until the next run.
Supported ecosystems: npm, PyPI, Go (modules and the standard library), Maven, NuGet, crates.io, RubyGems and Packagist.
Self-hosted and air-gapped installs
Section titled “Self-hosted and air-gapped installs”The daily match needs outbound HTTPS to api.osv.dev. Two environment variables on the Shield360 server change that:
| Variable | Effect |
|---|---|
SHIELD360_OSV=off | No lookups leave the deployment; runtime and repository targets are not matched. |
SHIELD360_OSV_URL | An HTTPS mirror that serves OSV’s /v1/querybatch and /v1/vulns/{id} API. |
CODE_SECURITY_MATCH_SCHEDULE | The cron schedule of the daily match (default 41 3 * * *). |
Data sources and attribution
Section titled “Data sources and attribution”OSV.dev aggregates advisories from other databases, each under its own license. Each stored advisory keeps the database it came from, which you can tell from its id:
| Id prefix | Database | License |
|---|---|---|
GHSA- | GitHub Advisory Database | CC-BY-4.0 |
PYSEC- | PyPI Advisory Database | CC-BY-4.0 |
GO- | Go Vulnerability Database | CC-BY-4.0 |
RUSTSEC- | RustSec Advisory Database | CC0-1.0 |
MAL- | OpenSSF Malicious Packages | Apache-2.0 |
Shield360 does not redistribute this data; it fetches it at run time and caches it.