Snyk Dependency Scanning: Automated Vulnerability Testing in PRs and CI

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_TOKEN

In 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=high

The --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:      myapp

The "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=poetry

For 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.sarif

Uploading 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.json

When 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=high

License 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-org

License 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=medium

Snyk 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.

Read more