boto3, botocore, and the @aws-sdk/* packages are dependencies like any other, and they get CVEs like any other. Because they sit underneath almost every AWS integration in your codebase, a vulnerability in one of them has unusually wide blast radius.
Catching that before it ships is a solved problem: a dependency vulnerability scanner in CI, paired with automated update PRs, closes the loop with very little ongoing effort.
# --- Python (boto3) ---# Install once:# pip install pip-audit# Run against your locked requirements:# pip-audit -r requirements.txt# Exits non-zero if a known CVE is found, so CI fails the build.
// --- TypeScript (AWS SDK v3) ---// Built into npm, no install needed:// npm audit --omit=dev// Reads package-lock.json and checks every @aws-sdk/* package (and// everything else) against the npm advisory database.// Exits non-zero above the configured severity, so CI fails the build.
When to reach for this:
Every CI run, as a required check before merge.
Whenever boto3, botocore, or an @aws-sdk/* package version is bumped.
On a recurring schedule (nightly or weekly), since new CVEs get published against versions already in your lockfile.
Wire the scanner into CI so a PR fails the build on a known vulnerability, and pair it with Dependabot or Renovate so the fix arrives automatically as its own PR.
// --- TypeScript (AWS SDK v3) ---// .github/workflows/security.yml (Node job)// - name: Install dependencies// run: npm ci// - name: Audit dependencies// run: npm audit --omit=dev --audit-level=high//// --audit-level=high fails the build only on high/critical findings,// so low-severity transitive noise doesn't block every PR.
What this demonstrates:
The scan runs on the locked dependency file (requirements.txt/package-lock.json), so it checks what actually ships, not just top-level declarations.
A severity threshold (--audit-level=high, or an equivalent pip-audit filter) keeps the gate meaningful instead of blocking on every low-severity transitive finding.
This is a CI step, not a local-only habit - it runs the same way for every contributor and every PR.
pip-audit checks installed or locked packages against the Python Packaging Advisory Database (which aggregates OSV and PyPI advisories) and reports the CVE id, affected version range, and fixed version for each hit, including boto3 and botocore themselves.
safety is a comparable, longer-established alternative with its own vulnerability database; some teams run both for broader coverage, though either alone is a solid baseline.
Because botocore (the library boto3 wraps) ships new versions extremely frequently to track AWS API changes, pin it deliberately and re-scan on every bump rather than floating an unpinned version range.
npm audit reads package-lock.json and reports against the npm security advisory database - no extra install required, which makes it a reasonable default gate. It covers every @aws-sdk/client-* and @aws-sdk/lib-* package the same as any other npm dependency.
For deeper coverage - supply-chain risk beyond known CVEs, like a package's install scripts or a sudden maintainer change - tools like Snyk or Socket add checks npm audit doesn't perform. They are commercial/freemium products; adopt them as a deliberate decision, not a silent default, since they typically require an account and may have usage-based cost.
Scanning tells you a problem exists; it does not fix it. Dependabot (built into GitHub) or Renovate (self-hosted or SaaS) watches your manifest files and opens a PR automatically the moment a patched version is published, for both the Python and Node ecosystems.
The combination - a scanner gating merges, plus a bot opening upgrade PRs - means a new CVE against botocore or an @aws-sdk/* package typically gets a PR within a day of disclosure, without anyone watching for it manually.
Running the scan only locally, never in CI. - It catches nothing for contributors who don't remember to run it. Fix: make it a required CI check on every PR.
Failing the build on every severity level. - Low-severity transitive findings can make the gate noisy enough that people start ignoring it. Fix: set a severity threshold (--audit-level=high or equivalent) and track lower-severity findings separately.
Scanning requirements.txt without a lockfile equivalent. - Unpinned ranges mean the scan result doesn't match what actually gets installed in production. Fix: scan against a fully pinned/locked dependency file.
Treating every finding as a hard block. - Some CVEs affect a code path your integration never exercises. Fix: triage exploitability before deciding to hold a release, but don't skip the review step entirely.
Letting Dependabot/Renovate PRs pile up unreviewed. - Automated PRs still need someone to merge them. Fix: treat dependency-bump PRs as a routine, low-friction review, not a backlog.
What's the difference between pip-audit and npm audit?
They serve the same role for different ecosystems - pip-audit scans Python packages (including boto3/botocore) against the Python Packaging Advisory Database, and npm audit scans Node packages (including @aws-sdk/*) against the npm advisory database.
Should dependency scanning block a PR from merging?
Yes, as a CI gate at a sensible severity threshold (for example high/critical only), so noisy low-severity transitive findings don't block every merge while real risk still stops the build.
Do I need a commercial tool like Snyk, or is npm audit/pip-audit enough?
For known-CVE coverage, the free tools are enough for most teams. Commercial tools like Snyk or Socket add broader supply-chain checks (install scripts, maintainer changes, typosquatting) - worth it if that risk profile matters to you, not a default requirement.
How do Dependabot and Renovate relate to scanning?
They're complementary. A scanner in CI catches a known CVE at merge time; Dependabot/Renovate proactively opens a PR the moment a patched version exists, so the fix often arrives before the next scan would even find the problem.
Why does botocore update so often, and does that matter for scanning?
botocore ships frequent releases to track new AWS API surface. Pin it deliberately rather than floating a version range, and re-run the scan on every bump so a newly disclosed CVE against a version you already use doesn't slip through unnoticed.
What should I do when a scan finds a CVE in a package I can't immediately upgrade?
Triage exploitability first - does your integration exercise the affected code path. If the risk is real and no patched version is available yet, consider a temporary mitigation (restricting the affected feature, adding input validation around it) and track the upgrade as a tracked follow-up, not a silently ignored finding.