Safeguard
Application Security•

ASVS 5.0 V15.1.2: Maintain an SBOM and Trusted Sources

ASVS 5.0 V15.1.2 (Level 2): keep an inventory such as an SBOM of every third party library and verify it comes from trusted repositories.

Safeguard Security Team
3 min read

ASVS 5.0 V15.1.2 is a Level 2 requirement. You must maintain an inventory catalog, such as a software bill of materials (SBOM), of all third party libraries in use. You must also verify that components come from pre defined, trusted and continually maintained repositories.

Two parts: know what you ship, and know where it came from.

Why it matters

When a new vulnerability lands, the first question is "are we affected?". Without an inventory, you answer by searching repositories for hours. With one, it is a query.

Source matters too. Dependency confusion, typosquatted names and abandoned packages all work because projects accept anything that resolves. A list of approved registries and a rule that anything else is rejected closes that door.

How to implement it

Generate the SBOM from the build, not by hand, and store it with each release.

# CycloneDX for a Node project
npx @cyclonedx/cyclonedx-npm --output-file sbom.cdx.json

# Python
cyclonedx-py environment -o sbom.cdx.json

# Container image
syft myapp:1.4.2 -o cyclonedx-json > sbom.cdx.json

Include transitive dependencies, versions and, ideally, hashes and package URLs.

Pin sources so builds cannot pull from elsewhere:

# .npmrc
registry=https://registry.internal.example.com/
@yourorg:registry=https://registry.internal.example.com/
# pip.conf
[global]
index-url = https://pypi.internal.example.com/simple

Use lock files with integrity hashes, and fail CI when the lock file and the manifest disagree:

npm ci
pip install --require-hashes -r requirements.txt

Add an allowlist check to the pipeline. For npm, every package in the lock file records the URL it was resolved from:

import json, sys
from urllib.parse import urlparse

approved = {"registry.internal.example.com"}
lock = json.load(open("package-lock.json"))
bad = []
for path, pkg in lock.get("packages", {}).items():
    url = pkg.get("resolved")
    if url and urlparse(url).hostname not in approved:
        bad.append(path)
if bad:
    sys.exit("unapproved sources: " + ", ".join(bad))

Other ecosystems have equivalents in their lock files. The point is that the check exists and fails the build.

You can start without installing anything: the free in browser dependency scan at gold.safeguard.sh/scan lists your dependencies and their known issues, and the dependency inventory demo shows what a maintained inventory looks like.

Click through it at your own pace, or open it full screen.

How to test it

  1. Ask for the SBOM of the version currently in production. It must exist and match that version.
  2. Pick five libraries at random from the running application and find each in the SBOM.
  3. For each, confirm the registry it was fetched from is on the approved list.
  4. Try adding a dependency from an unapproved source in a branch. The pipeline should reject it.
  5. Check how old the SBOM is relative to the last deploy.

Common mistakes

  • An SBOM generated once for an audit and never refreshed.
  • Listing direct dependencies only.
  • Approving a registry but allowing a fallback to the public index, which enables dependency confusion.
  • No view into base images and system packages in containers.
  • Treating a package as maintained because it is popular, without checking release activity.

Quick check

Which SBOM format should I use?

The requirement names no format. CycloneDX and SPDX are both common, so pick the one your tools and customers can read.

Is a lock file an inventory?

It is a start, since it records exact versions, but it does not cover container layers or give you a portable, queryable catalog.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.