Safeguard
Developer Tools•

How do you scan dependencies in a Bazel repository?

Bazel records module resolution in MODULE.bazel.lock, but that file is not a package list. See what it holds and how to build an inventory you can scan.

Safeguard Security Team
3 min read

Do not point a generic scanner at the repository and hope. Bazel's MODULE.bazel.lock records module resolution, not a language level package list. Build the inventory from the language specific lockfiles or pinned files your rules use, then scan those, and use the Bazel lockfile to prove reproducibility.

What MODULE.bazel.lock holds

The Bazel documentation says the lockfile sits at the workspace root and stores the results of module resolution and module extension evaluation. It records hashes of remote registry files used in resolution, any yanked versions chosen, and for each module extension its inputs and outputs. Its stated purposes are reproducible builds, faster incremental resolution and protection against unexpected dependency updates.

It only includes dependencies used in the current build invocation, and the docs recommend running the tidy command regularly to keep it current.

That makes it an input to reproducibility, not a bill of materials. Many third party language libraries come in through extensions or separate pinned files that your rules read.

Lockfile modes

The lockfile mode flag has four values, according to the docs.

ModeBehaviour
update (default)Uses the lockfile and adds missing information
refreshLike update, but refreshes mutable information about hourly
errorFails if information is missing or outdated, no changes or network during resolution
offLockfile neither checked nor updated

For CI, error mode is a good choice. It fails the build when the lockfile is stale, so the scan input matches what you build. Extensions marked reproducible may still use the network, as the docs note.

Building a scannable inventory

  1. List the module dependencies from your MODULE.bazel file.
  2. Find each language ruleset and its pinned file, such as a Maven pin file, a Python requirements lock or a Go sum file.
  3. Scan those files with a normal dependency scanner.
  4. Map each result to the Bazel targets that use it, so owners can act.

Step four is the hard one in practice. Check Bazel's query documentation for how to list the targets that depend on an external repository, and use that to route findings.

Pitfalls

  1. A scan of source folders misses everything Bazel downloads.
  2. A scan of the output directory can mix build tools and test dependencies with shipped ones.
  3. Hermetic builds are reproducible, not necessarily vulnerability free. See Bazel hermetic builds for what hermeticity does and does not give you.

Run it per deliverable

Pick the targets that you ship, and scope the inventory to those, so tools and tests do not pollute results.

Safeguard scans dependencies from manifests and lockfiles and generates SBOMs. The free scan at https://gold.safeguard.sh/scan accepts a project so you can see the output for one pinned file.

Quick check

Is MODULE.bazel.lock a package list?

No. It records module resolution and extension results, with hashes of registry files.

Which lockfile mode fails on a stale lockfile?

Error mode, which fails if needed information is missing or outdated.

Sources

Last reviewed: 19 October 2026.

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.