beam cve check . reads the lockfiles in a project, sends only package names and versions to AgentBeam, and matches them against a CVE database. It exits with code 2 when something meets the severity you set with --fail-on, which is all a CI system needs to turn it into a gate. This guide covers what it reads, how to run it on a laptop and in a pipeline, and how to avoid the failure mode that makes most dependency gates useless: so many findings that the team stops reading them.
| Question | Short answer |
|---|---|
| What does it read? | Lockfiles for npm/yarn/pnpm/bun, pip/poetry/uv/Pipfile, Go, Cargo, composer, Bundler, NuGet, Gradle, mix, Swift, and GitHub Actions workflows |
| What does it send? | Package names and versions only |
| How does it fail a build? | Exit code 2 when a finding meets --fail-on |
| What does CI need? | BEAM_APP_TOKEN as a secret |
| Where do I read advisories? | The CVE database |
Why check in CI and not just on a laptop
A dependency you added six months ago can become vulnerable tomorrow without a single line of your code changing. The package did not change, the advisory did. That is the core reason to check on a schedule and on every pull request, and not only when someone remembers to run a scanner locally.
CI is also where the decision is cheapest to enforce. A reviewer cannot be expected to remember that a transitive dependency three levels down appeared in a lockfile diff. A pipeline step can. If the step fails when a critical advisory matches, nobody has to rely on memory.
This matters more as AI coding agents add dependencies for you. An agent that runs npm install some-package to make a test pass has made a supply-chain decision on your behalf, and the lockfile diff is the only record. Checking that diff automatically closes the gap. For the agent side of the same problem, see AI agent monitoring.
What beam cve check reads
The command takes a path, usually ., and finds the files that describe what your project actually installs:
| Ecosystem | Files read |
|---|---|
| JavaScript | npm, yarn, pnpm and bun lockfiles |
| Python | pip requirements, poetry, uv and Pipfile |
| Go | go.mod |
| Rust | Cargo |
| PHP | composer |
| Ruby | Gemfile |
| .NET | NuGet |
| JVM | Gradle |
| Elixir | mix |
| Swift | Package.resolved |
| CI | GitHub Actions workflows |
Lockfiles are the right input because they record resolved versions, including transitive dependencies. A manifest that says ^4.17.0 tells you very little. The lockfile tells you that 4.17.20 is what shipped.
Reading GitHub Actions workflows is easy to overlook and valuable. Your pipeline pulls in third-party actions with their own supply chains, and several recent incidents began with a compromised action or a mutable tag. A workflow that references an affected action version is as much a part of your exposure as an npm package.
What leaves your machine
beam cve check sends package names and versions. That is the whole payload. It does not upload your source code, your lockfile as a file, or paths from your file system.
That boundary is deliberate. A dependency list reveals less than source does, but it is still information about your stack, so it is worth saying plainly: the service sees that a project uses a particular package at a particular version, and nothing else about the project.
Run it locally first
Install the CLI and run the check from the repository root:
npm install -g @agent-beam/beam
beam cve check .
You will see findings for any package version that matches an advisory. Read a few of them before you add a gate. You want to know what your baseline looks like. A mature project often has a handful of findings that are accepted risks or not reachable in practice, and it is better to learn that now than in the middle of a failed deploy.
For each finding, the questions to ask are the same:
- Is there a fixed version? If yes, upgrading is usually the answer.
- Is the vulnerable code reachable? A vulnerable function you never call is lower priority than one on your request path.
- Is it a direct or a transitive dependency? Transitive findings may need an override or an upgrade of the parent package.
- Is it listed as actively exploited? AgentBeam raises advisories in CISA's Known Exploited Vulnerabilities (KEV) catalog to critical in monitor findings. Those go to the top of the list, regardless of the score.
You can browse the advisories behind a finding in the CVE database, which lists severity and affected versions for each entry.
Gate a CI build
In CI the command authenticates with a token. Create an app in the dashboard, copy its BEAM_APP_TOKEN, and store it as a secret in your CI provider. It is the same per-app token that beam monitor uses: shown once, stored hashed, accepted only by the App monitoring endpoints over HTTPS, and rotatable or revocable. If a build log leaks it, revoke it and issue a new one.
A GitHub Actions job looks like this:
name: dependency-cve-check
on:
pull_request:
schedule:
- cron: '0 6 * * *'
jobs:
cve-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Check dependencies for known CVEs
env:
BEAM_APP_TOKEN: ${{ secrets.BEAM_APP_TOKEN }}
run: npx @agent-beam/beam cve check . --fail-on high
Two details are worth noting. The scheduled trigger catches the case described above, where a new advisory lands for a version you already ship, without any commit. And --fail-on takes a severity threshold, so the step fails only when a finding meets it. Check the App monitoring docs for the accepted values.
Because the command exits with code 2 on a threshold match, every CI system can use it the same way. A non-zero exit fails the step. If you want to distinguish "vulnerabilities found" from "the tool broke", test for exit code 2 specifically:
beam cve check . --fail-on high
status=$?
if [ "$status" -eq 2 ]; then
echo "Vulnerable dependencies found"
exit 1
elif [ "$status" -ne 0 ]; then
echo "Check could not complete" >&2
exit "$status"
fi
Pick a threshold you will keep
The hardest part of a dependency gate is not the tooling. It is choosing a threshold the team will respect.
Starting with --fail-on critical is usually right. A gate that fails rarely and always means something earns trust. After the backlog of critical findings is clear, move to high. Going straight to a strict threshold on a project with an existing backlog produces a permanently red pipeline, and a permanently red pipeline gets bypassed.
When you must ship with a known finding, record why. Put the advisory ID, the reason (not reachable, no fix available, mitigated elsewhere) and a review date in the pull request or an exceptions file. A suppression with no explanation is how a real vulnerability survives for two years.
Triage a failed gate
The first time the gate goes red, the team's reaction decides whether it survives. A short routine keeps it from becoming an argument:
- Open the failing step and note the package, the installed version and the advisory.
- Look the advisory up in the CVE database to see severity and affected versions.
- Find out who pulled the package in. In npm that is
npm ls <package>, in pnpmpnpm why <package>, and similar commands exist elsewhere. A transitive finding is usually fixed by upgrading the parent. - Upgrade, regenerate the lockfile and re-run the check. If the fix is a major version bump, run your test suite before merging.
- If there is no fix yet, decide between removing the package, pinning to a safer version, or accepting the risk with a written reason and a review date.
Treat the pull-request run and the scheduled run differently. A failure on a pull request is a request to the author: this change introduced or touched something vulnerable. A failure on the scheduled run is a new advisory against code you already ship, so route it to whoever owns the service, not to whoever merged last.
Many apps, one pipeline
If a repository holds several services, run the command from the root and let it read every lockfile it finds, or run it once per service directory if different teams own them. Keep the token per app, so each service reports under its own name and its alerts go to its own channel. This matches how App monitoring separates apps in the dashboard, where findings are filtered per app and webhooks can be limited to specific apps.
Where it fits with monitoring
Dependency checks and runtime monitoring answer different questions. beam cve check asks which packages in your build have known advisories. beam monitor asks whether anything in your live logs and traffic looks like an attack. Run both: the first reduces the number of ways in, the second tells you when someone is trying them.
A concrete example is Log4Shell-style exploitation. A dependency check flags the vulnerable logging library before you ship. If something slips through, the monitor flags the JNDI strings arriving in your request logs. Neither one replaces the other, and both use the same per-app token.
What it cannot tell you
Be honest about the limits so the check does not give false comfort:
- A match is not exploitability. It says a version is affected by an advisory, not that your code reaches the vulnerable path.
- No match is not safety. Advisories lag discoveries. A package with a fresh, undisclosed flaw will not match anything.
- Only recorded versions count. If you vendor a library by copying its source, no lockfile describes it and the check cannot see it.
- Malicious packages are a different problem. A typosquat or a compromised release may carry no CVE at all. For that class, read the incident coverage in the blog and pin versions.
Checklist
- Run
beam cve check .locally and read the baseline. - Create an app in the dashboard and store
BEAM_APP_TOKENas a CI secret. - Add the step to pull requests and a daily schedule, starting at
--fail-on critical. - Fix or document each finding, with a review date.
- Tighten the threshold as the backlog clears.
- Pair it with
beam monitorfor the live side.
If you would rather not wire this up by hand, the bundled skills can do it with your coding agent: see Let your coding agent set it up. To get started, use the getting-started link. The CLI is open source under AGPL-3.0 at github.com/whyashthakker/beam-cli.
Frequently asked questions
What does beam cve check read?
Lockfiles and manifests across npm, yarn, pnpm and bun, pip, poetry, uv and Pipfile, go.mod, Cargo, composer, Gemfile, NuGet, Gradle, mix and Swift Package.resolved, plus GitHub Actions workflows.
What data leaves my machine?
Only package names and versions. Your source code, file paths and lockfile contents beyond name and version pairs are not sent. The names and versions are matched against AgentBeam's CVE database.
How do I make a CI build fail on a vulnerability?
Use the --fail-on option. beam cve check exits with code 2 when a finding meets the threshold you set, and most CI systems treat any non-zero exit code as a failed step.
Does it need a token in CI?
Yes. In CI it authenticates with BEAM_APP_TOKEN, the same per-app token used by beam monitor. Store it as a CI secret, never in the repository.
Is a match the same as being exploitable?
No. A match means a package version is listed as affected by an advisory. Whether the vulnerable code path is reachable in your app is a separate question that needs a human to answer.
Where can I read the advisories themselves?
The CVE database at /cve on this site lists the advisories AgentBeam tracks, with severity and affected versions.
Related reading
Details are accurate as of October 23, 2026. App monitoring needs an AgentBeam workspace with it turned on by an owner or admin, and usage counts toward a monthly allowance that depends on your plan.
