Snyk Dependency Scanning: Automated Vulnerability Testing in PRs and CI
Snyk scans your dependencies, container images, infrastructure-as-code, and source code for vulnerabilities and license violations. This guide covers CLI integration for Node.js and Python, pull request checks in GitHub Actions, container image scanning, and managing false positives with policy files.
Key Takeaways
Snyk finds vulnerabilities in transitive dependencies, not just direct ones. A vulnerability in a dependency of a dependency is just as exploitable — Snyk's full dependency graph analysis catches what npm audit misses in complex trees.
Severity thresholds prevent pipeline bloat. Using --severity-threshold=high ensures your CI only fails on High and Critical findings while still reporting Medium and Low issues in the Snyk dashboard.
The .snyk policy file makes suppressions auditable. Ignoring a CVE inline with a comment and expiry date is far better than blanket filtering — it creates an audit trail and forces periodic review.
License compliance scanning protects against legal risk. Snyk's license check identifies dependencies under GPL, AGPL, or other copyleft licenses that may be incompatible with your project's license.
Snyk Code (SAST) finds logic flaws in your own code. Unlike dependency scanning, Snyk Code uses machine learning to identify injection vulnerabilities, path traversal, and hardcoded secrets in your source files.
Supply chain attacks and vulnerable dependencies have become one of the most common entry points for security breaches. The Log4Shell vulnerability (CVE-2021-44228), the XZ Utils backdoor, and countless npm package hijacks demonstrate that your application's security posture is only as strong as your weakest transitive dependency.
Snyk addresses this by scanning your dependency manifests against a continuously updated vulnerability database, integrating directly into pull requests to block vulnerable dependencies before they merge, and extending coverage to container images, Kubernetes manifests, and your own source code.
Installing and Authenticating the Snyk CLI
Snyk provides a Node.js CLI package and standalone binaries for all platforms.
# Install globally via npm
npm install -g snyk
<span class="hljs-comment"># Or use npx for one-off runs without installation
npx snyk --version
<span class="hljs-comment"># Authenticate (opens browser for OAuth flow)
snyk auth
<span class="hljs-comment"># Authenticate with a token in CI environments
snyk auth <span class="hljs-variable">$SNYK_TOKENIn CI pipelines, generate a service account token from the Snyk dashboard under Settings → Service Accounts and store it as a repository secret.
Scanning Node.js Projects
Basic Dependency Test
# Test the current project for vulnerabilities
snyk <span class="hljs-built_in">test
<span class="hljs-comment"># Show full vulnerability paths in the output
snyk <span class="hljs-built_in">test --all-projects --print-deps
<span class="hljs-comment"># Output results as JSON for further processing
snyk <span class="hljs-built_in">test --json > snyk-results.json
<span class="hljs-comment"># Fail only on High and Critical findings
snyk <span class="hljs-built_in">test --severity-threshold=highThe --all-projects flag discovers all manifest files (package.json, package-lock.json, yarn.lock) in the repository, making it suitable for monorepos.
Understanding the Output
Testing /app...
✗ High severity vulnerability found in lodash
Description: Prototype Pollution
Info: https://snyk.io/vuln/SNYK-JS-LODASH-567746
Introduced through: myapp@1.0.0 › some-library@2.3.0 › lodash@4.17.15
From: myapp@1.0.0 › some-library@2.3.0 › lodash@4.17.15
Fix: Upgrade some-library to 2.4.1 (which upgrades lodash to 4.17.21)
✗ Medium severity vulnerability found in axios
Description: Server-Side Request Forgery (SSRF)
Info: https://snyk.io/vuln/SNYK-JS-AXIOS-1579269
Introduced through: myapp@1.0.0 › axios@0.21.1
From: myapp@1.0.0 › axios@0.21.1
Fix: Upgrade axios to 0.21.2
Organization: my-org
Package manager: npm
Target file: package.json
Open source: no
Project name: myappThe "Introduced through" chain shows the full dependency path, and Snyk almost always provides a fix recommendation with the minimum version that resolves the issue.
Monitoring Projects for New Vulnerabilities
# Send current snapshot to Snyk for ongoing monitoring
snyk monitor --project-name=<span class="hljs-string">"production-app"snyk monitor differs from snyk test in that it uploads your dependency snapshot to the Snyk platform, which then sends alerts when new CVEs are published against your locked dependency versions — even if you have not changed your package.json.
Scanning Python Projects
Snyk supports pip, Pipenv, Poetry, and conda.
# Scan requirements.txt
snyk <span class="hljs-built_in">test --file=requirements.txt --package-manager=pip
<span class="hljs-comment"># Scan Pipenv project
snyk <span class="hljs-built_in">test --file=Pipfile
<span class="hljs-comment"># Scan Poetry project
snyk <span class="hljs-built_in">test --file=pyproject.toml --package-manager=poetryFor Python, Snyk resolves the full dependency tree by actually installing packages in a virtual environment during the scan. Ensure your CI runner has the appropriate Python version available.
GitHub Actions Integration
Here is a complete workflow that runs Snyk on every PR and push to main:
name: Snyk Security Scan
on:
pull_request:
branches: [main, develop]
push:
branches: [main]
schedule:
- cron: "0 6 * * 1" # Weekly Monday 6am
jobs:
snyk-dependency-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
run: npm ci
- name: Run Snyk dependency scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high --sarif-file-output=snyk.sarif
- name: Upload SARIF to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: snyk.sarif
snyk-code-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk Code (SAST)
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
command: code test
args: --sarif-file-output=snyk-code.sarif
- name: Upload Code SARIF
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: snyk-code.sarifUploading SARIF results means findings appear in the Security → Code scanning tab of your GitHub repository, giving developers a centralised view alongside CodeQL results.
Container Image Scanning
# Scan a local Docker image
snyk container <span class="hljs-built_in">test myapp:latest
<span class="hljs-comment"># Scan with base image recommendations
snyk container <span class="hljs-built_in">test myapp:latest --file=Dockerfile
<span class="hljs-comment"># Specify platform for multi-arch images
snyk container <span class="hljs-built_in">test myapp:latest --platform=linux/amd64
<span class="hljs-comment"># Output as JSON
snyk container <span class="hljs-built_in">test myapp:latest --json > container-results.jsonWhen you include --file=Dockerfile, Snyk analyses your build instructions and recommends alternative base images with fewer vulnerabilities. For example, switching from node:18 to node:18-alpine might reduce your vulnerability count from 400 to 12.
Container Scanning in GitHub Actions
snyk-container-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan container image
uses: snyk/actions/docker@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
image: myapp:${{ github.sha }}
args: --file=Dockerfile --severity-threshold=highLicense Compliance Scanning
# Test for license issues alongside vulnerabilities
snyk <span class="hljs-built_in">test --all-projects
<span class="hljs-comment"># Get license information only
snyk <span class="hljs-built_in">test --json <span class="hljs-pipe">| jq <span class="hljs-string">'.licensesPolicy'
<span class="hljs-comment"># Use organisation-level license policy
snyk <span class="hljs-built_in">test --org=my-orgLicense policies are configured in the Snyk dashboard under Settings → Licenses. You can set severity levels for specific license types — for example, flagging GPL-3.0 as high severity in a commercial project while allowing MIT and Apache-2.0.
Managing False Positives with the .snyk Policy File
The .snyk file lives in your repository root and provides version-controlled suppression of false positives with mandatory expiry dates and justification comments.
# .snyk
version: v1.25.0
ignore:
SNYK-JS-LODASH-567746:
- "*":
reason: >
This vulnerability requires prototype pollution via a code path
that is unreachable in our application — all user input is
validated against a strict JSON schema before reaching lodash.
expires: "2026-09-01T00:00:00.000Z"
created: "2026-05-19T00:00:00.000Z"
SNYK-PYTHON-REQUESTS-3233415:
- "requests > 2.27.1":
reason: >
CVE only affects requests when used with the chardet library.
We use charset-normalizer as specified in requirements.txt.
expires: "2026-08-01T00:00:00.000Z"
patch: {}Key discipline points for .snyk management:
- Always set an expiry date. Without expiry, suppressions accumulate indefinitely. Quarterly expiry forces review.
- Always include a reason. "Business decision" is not a reason. Explain why the specific code path is not exploitable.
- Review expired ignores in your security stand-up. Snyk will start failing again when they expire — that is intentional.
Snyk Code (SAST) Basics
Snyk Code analyses your source files for security vulnerabilities using a flow-based analysis engine that understands how data moves through your application.
# Run SAST scan on current directory
snyk code <span class="hljs-built_in">test
<span class="hljs-comment"># Focus on specific directory
snyk code <span class="hljs-built_in">test src/
<span class="hljs-comment"># Set severity threshold
snyk code <span class="hljs-built_in">test --severity-threshold=mediumSnyk Code finds issues like:
- SQL Injection — unsanitised user input reaching database queries
- Path Traversal — user-controlled filenames used in
fs.readFile()or similar - Hardcoded credentials — API keys or passwords in source files
- Cross-Site Scripting — user input rendered without encoding
Unlike dependency scanning, SAST findings require manual triage because the exploitability depends on your application's specific control flow. Use SAST findings as a risk signal rather than a hard build gate until you have calibrated it to your codebase's typical false positive rate.
Setting Severity Thresholds Strategically
Rather than treating all vulnerabilities equally, map Snyk severity levels to CI actions:
| Severity | CI Action | Response SLA |
|---|---|---|
| Critical | Block PR merge | Fix before merge |
| High | Block PR merge | Fix within 24 hours |
| Medium | Warn in PR comment | Fix within 2 weeks |
| Low | Dashboard only | Fix at next sprint boundary |
In your .github/workflows/snyk.yml, set --severity-threshold=high for the step that can fail the build, and run a separate snyk test --severity-threshold=low --json step whose output is uploaded as an artifact for the security dashboard.
Summary
Snyk provides a pragmatic, developer-friendly approach to supply chain security. Its integration with GitHub pull requests means vulnerabilities are surfaced in the developer's existing workflow rather than requiring context-switching to a separate security dashboard. The .snyk policy file ensures suppressions are explicit, time-bounded, and version-controlled — avoiding the "just add --all to suppress everything" failure mode. Combined with container scanning and Snyk Code, it provides coverage across the full application attack surface from a single tool.