Snyk Integration Guide: Fix Dependency Vulnerabilities in CI/CD

Snyk Integration Guide: Fix Dependency Vulnerabilities in CI/CD

Your application code may be secure, but the 500+ open-source packages it depends on are a different story. Snyk continuously monitors those dependencies, finds known vulnerabilities, and — unlike most scanners — tells you exactly how to fix them.

This guide covers installing Snyk, integrating it into CI/CD, and configuring policies that don't turn into alert fatigue.

What Snyk Scans

Snyk works across four areas:

Open Source (SCA) — Scans package.json, requirements.txt, go.mod, Gemfile, and other manifests. Checks against Snyk's vulnerability database (sourced from CVE, NVD, GitHub Advisory, and their own research). Shows the dependency path that introduced the vulnerability.

Code (SAST) — Static analysis of your own code. Finds SQL injection, XSS, path traversal, hardcoded secrets. Uses a data-flow engine rather than pattern matching, which reduces false positives.

Container — Scans Docker images for vulnerable OS packages and language dependencies. Integrates with container registries.

Infrastructure as Code — Scans Terraform, Kubernetes manifests, CloudFormation for misconfigurations.

Most teams start with Open Source scanning since it delivers immediate value and requires no code changes.

Setup

Install the CLI

npm install -g snyk

Or download the binary:

# macOS/Linux
curl -fsSL https://static.snyk.io/cli/latest/snyk-macos -o snyk
<span class="hljs-built_in">chmod +x snyk
<span class="hljs-built_in">sudo <span class="hljs-built_in">mv snyk /usr/local/bin/

Authenticate

snyk auth

Opens a browser for OAuth login. Once authenticated, Snyk stores credentials at ~/.config/configstore/snyk.json.

For CI environments, use an API token:

snyk auth $SNYK_TOKEN
<span class="hljs-comment"># or
<span class="hljs-built_in">export SNYK_TOKEN=your-token-here

Get tokens from app.snyk.io → Settings → Service Accounts.

Running Your First Scan

cd your-project
snyk <span class="hljs-built_in">test

Output for a typical Node.js project:

Testing /your-project...

✗ High severity vulnerability found in lodash
  Description: Prototype Pollution
  Info: https://snyk.io/vuln/SNYK-JS-LODASH-567746
  Introduced through: your-package@1.0.0 › lodash@4.17.15
  Fix: upgrade lodash to 4.17.21

✗ Medium severity vulnerability found in axios
  Description: Server-Side Request Forgery
  Info: https://snyk.io/vuln/SNYK-JS-AXIOS-1579269
  Introduced through: your-package@1.0.0 › axios@0.21.1
  Fix: upgrade axios to 0.21.2

Organization:      your-org
Package manager:   npm
Target file:       package.json
Open source:       no
Project name:      your-project
Licenses:          enabled

Tested 512 dependencies for known issues, found 12 issues, 10 vulnerable paths.

Each finding shows:

  • Severity (High/Medium/Low)
  • Vulnerability type
  • The dependency chain that introduced it
  • The fix (usually a version upgrade)

Fixing Vulnerabilities

Automatic Fix PRs

The easiest path — let Snyk open a PR:

snyk fix

This updates package.json and package-lock.json with the fixed versions. Review the diff and merge.

Manual Fix

For each finding, check the "Fix" line in the output and update accordingly:

npm install lodash@4.17.21
npm install axios@0.21.2

Then rerun snyk test to confirm the fixes.

Understanding the Dependency Tree

Sometimes you can't directly upgrade a vulnerable package because it's a transitive dependency — something your dependency depends on. Snyk shows the full path:

your-package → some-library@2.1.0 → vulnerable-dep@1.0.0

Options:

  1. Upgrade some-library if a newer version includes a fix
  2. Add a resolution/override in your package manager
  3. Accept the risk if no fix is available

Check with snyk test --show-vulnerable-paths=all to see all paths.

CI/CD Integration

GitHub Actions

name: Security Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  snyk:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run Snyk vulnerability scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high --fail-on=upgradable

      - name: Upload Snyk report
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: snyk.sarif

The --fail-on=upgradable flag only fails the build when a fix is available — prevents blocking on vulnerabilities with no fix yet.

GitLab CI

snyk-test:
  image: snyk/snyk:node
  stage: test
  script:
    - snyk auth $SNYK_TOKEN
    - snyk test --severity-threshold=high --json > snyk-report.json
  artifacts:
    when: always
    paths:
      - snyk-report.json
  allow_failure: true

CircleCI

jobs:
  snyk-scan:
    docker:
      - image: cimg/node:20.0
    steps:
      - checkout
      - run:
          name: Install Snyk
          command: npm install -g snyk
      - run:
          name: Authenticate Snyk
          command: snyk auth $SNYK_TOKEN
      - run:
          name: Run Snyk test
          command: snyk test --severity-threshold=medium

Configuring Policies

Severity Threshold

Only fail on high and critical:

snyk test --severity-threshold=high

Ignoring Known Issues

Sometimes a vulnerability can't be fixed immediately — no upgrade path, or you've assessed the risk and accepted it. Use .snyk file:

# .snyk
version: v1.25.1
ignore:
  SNYK-JS-LODASH-567746:
    - '*':
        reason: No fix available, lodash used only for server-side data processing
        expires: '2026-09-01T00:00:00.000Z'

Provide a reason and expiry date. The expiry forces you to revisit the decision.

Or ignore via CLI (adds to .snyk automatically):

snyk ignore --id=SNYK-JS-LODASH-567746 --reason=<span class="hljs-string">"No fix available" --expiry=2026-09-01

Excluding Dev Dependencies

snyk test --dev
<span class="hljs-comment"># or to exclude dev deps
snyk <span class="hljs-built_in">test --production

For CI builds, typically use --production since dev dependencies don't ship with the app.

Snyk in the Developer Workflow

IDE Plugin

Snyk has plugins for VS Code, JetBrains, and Eclipse. Issues appear inline in the editor — you see the vulnerability in package.json before you even commit.

Install: search "Snyk" in your IDE's extension marketplace.

Git Repository Monitoring

Connect your GitHub/GitLab/Bitbucket repository to Snyk's web UI. Snyk monitors the default branch continuously and opens automatic fix PRs when new vulnerabilities are discovered in packages you already use.

This catches new CVEs even when you haven't changed your code.

Pre-commit Hook

Add Snyk to your pre-commit hook to catch issues before they reach CI:

# .git/hooks/pre-commit
<span class="hljs-comment">#!/bin/bash
snyk <span class="hljs-built_in">test --severity-threshold=high
<span class="hljs-keyword">if [ $? -ne 0 ]; <span class="hljs-keyword">then
  <span class="hljs-built_in">echo <span class="hljs-string">"Snyk found high severity vulnerabilities. Commit blocked."
  <span class="hljs-built_in">exit 1
<span class="hljs-keyword">fi

Monitoring vs. Testing

Snyk has two modes:

snyk test — Point-in-time scan. Used in CI to block builds.

snyk monitor — Takes a snapshot and uploads it to Snyk's platform for continuous monitoring. Run this after successful deployments:

snyk monitor --project-name=production

Snyk will notify you via email/Slack when new vulnerabilities are discovered in the packages your monitored snapshot uses — even if you haven't changed the code.

Language Support

Language Package Manager File
Node.js npm, Yarn, pnpm package.json
Python pip, Poetry, Pipenv requirements.txt, pyproject.toml
Java Maven, Gradle pom.xml, build.gradle
Go Go modules go.mod
Ruby Bundler Gemfile
.NET NuGet *.csproj
PHP Composer composer.json

Common Gotchas

Lock files matter: Snyk reads package-lock.json or yarn.lock for the exact installed versions. Always commit lock files. Without them, Snyk scans the ranges in package.json, which gives less precise results.

Monorepos: Use --all-projects to scan all package.json files in subdirectories:

snyk test --all-projects

Docker images: Snyk scans both the OS layer and application dependencies inside the image:

snyk container test node:20-alpine
snyk container <span class="hljs-built_in">test your-app:latest --file=Dockerfile

False positives in code scanning: Snyk Code's SAST can flag issues that aren't exploitable in your context. Review each finding — "Mark as not applicable" removes it from future scans.

Free vs. Paid

Snyk's free tier covers:

  • Open source scanning (unlimited repos, but limited monthly tests)
  • One developer, up to 200 open source tests/month
  • Manual fix suggestions

Paid plans add:

  • Unlimited testing
  • Snyk Code (SAST)
  • Container and IaC scanning
  • Team features, reporting, policies

For most small teams, the free tier handles dependency scanning. Code and container scanning requires a paid plan.

What Snyk Doesn't Replace

Snyk catches known vulnerabilities in known packages. It doesn't:

  • Find business logic flaws
  • Test that your access controls actually work
  • Scan for runtime injection vulnerabilities
  • Test for OWASP Top 10 issues in your own code (beyond what SAST covers)

Pair Snyk with DAST tools like OWASP ZAP for runtime scanning, and functional security tests for access control — together they cover the vulnerability landscape that matters.

Read more