Vulnerability management

Decide each finding once. Record it. Move on.

When a scanner flags a CVE you have three options — fix it, accept it, or prove it doesn't apply. These guides cover all three, ending in the same place: a VEX statement that records what you decided so nobody re-investigates the same finding next sprint.

How these guides are written

The guides assume you work in GitLab or GitHub. Where they say merge request — what GitHub calls a pull request — the concept is interchangeable; we've picked the GitLab term throughout. If you're on Bitbucket, Azure DevOps, or self-hosted Forgejo the ideas still apply, only the menus differ.

Every CI example uses shell commands in a pipeline file — a .gitlab-ci.yml stanza or a GitHub Actions run: step. We don't reach for vendor plugins or marketplace actions when the same job fits in five lines of bash, because the bash works regardless of which CI vendor you migrate to next year and stays readable as a script you can run locally.

The audience is developers, not security teams. The goal is to give you enough context to make the right call on a finding in the time you have between merging this feature and being asked to merge the next one. Your decision ends up as evidence the security team can verify without interrupting you twice.

Each scanner speaks its own dialect.

These guides translate each scanner's output into the same destination — a VEX statement that records what you decided about each finding.

Vulnetix Code Scanner
Unified SCA / SAST / secrets / containers / IaC scanner — emits CycloneDX 1.7 and SARIF 2.1 natively.
Snyk OSS
Snyk's dependency vulnerability scanner — JSON or SARIF output, SNYK-* identifiers cross-referenced to CVE / GHSA.
Snyk Code (SAST)
Snyk's taint-flow static analysis — SARIF 2.1.0 output with code-flow traces source-to-sink.
gosec (Go Security Checker)
Securego's Go SAST scanner — AST + SSA pattern matching with intra-procedural taint, JSON / SARIF output, CWE-tagged.
GitLab Dependency Scanning
GitLab's first-party dep scanner — runs on every pipeline, JSON artefact with CVE / GHSA cross-references.
GitLab Secret Detection
GitLab's Gitleaks-driven secret scanner — JSON report, fires on token shapes, surfaces in the MR widget.
GitLab DAST
OWASP ZAP under the hood, probes a deployed environment, JSON report with reproducible request/response evidence.
GitHub Dependabot
GitHub's first-party dep scanner — Security tab alerts + auto-upgrade MRs, accessed via GraphQL / REST.
GitHub Secret Scanning
GitHub's first-party secret scanner — partner-token verification, Push Protection, REST + GraphQL access.
GitHub CodeQL
Semantic query-based SAST — extracts a relational model of your code and runs security queries against it.
Grype
Anchore's vulnerability scanner — JSON / SARIF output, native OpenVEX consumption via `--vex`.
Prisma Cloud (twistcli)
Palo Alto Networks Prisma Cloud Compute — twistcli CLI for build-time image / repo / serverless / IaC scans; Prisma Defender for runtime.
Trivy
Aqua Security's polyscanner — SCA + secrets + IaC + SBOM + license in one binary; native VEX consumption (CycloneDX + OpenVEX).
osv-scanner
Google's OSV-database scanner — fast, account-free, native OSV-schema records with cross-feed aliases.
Semgrep / Opengrep
Pattern-matching SAST that reads like the language it scans — and a community fork that drops the cloud licence.
Ruff
Astral's Rust-powered Python linter — 800+ built-in rules plus the Vulnetix opa-py-ruff Rego port that the Vulnetix CLI consumes.
KICS
Checkmarx's open-source IaC scanner — Rego-based queries across 20+ platforms, SARIF + CycloneDX + JSON output.
OWASP Dependency-Track
OWASP Flagship Component Analysis platform — SBOM-consuming, policy-driven, CycloneDX VEX round-tripping.

When the fix isn't in the code.

A WAF rule blocks the attack vector. An IPS signature drops the exploit packet. A YARA rule catches the payload on disk. A Sigma rule alerts when the attempt hits your logs. Each is a valid response to a vulnerability — but only when the mitigation is documented somewhere a scanner can read.

If SBOM and VEX are new to you, start here.

Background on the two attestation formats the scanner and rules guides assume — what they are, why they exist, and why generating them yourself during normal development flow saves everyone time downstream.

Glossary
A–Z reference for the jargon that lands cold on a first-time reader — PURL, SBOM, VEX, KEV, EPSS, SSVC, CWE, CWSS, SARIF, MAL-, EOL, safe-harbour, reachability tiers.
AI Coding Agent — triage, remediation, VEX
The Vulnetix plugin for Claude Code, Cursor, Windsurf, Copilot, Gemini, and a dozen other editors. Removes the burden of picking VEX formats, remediation strategies, and SSVC inputs by hand.
CycloneDX SBOM
A machine-readable inventory of what your build actually contains — and the foundation everything else here rests on.
JavaScript — npm, pnpm, Yarn
Lockfile mechanics, transitive coercion, integrity for the three Node.js package managers.
SSVC — Engineer Triage for developers
The decision framework that turns a scanner finding into one of four actions — NIGHTLY_AUTO_PATCH, BACKLOG, SPIKE_EFFORT, or DROP_TOOLS.
Python — pip, Pipenv, Poetry, uv
Lockfile mechanics for the four Python dependency-management workflows.
VEX — overview
What VEX is, why it exists, which of the two formats to pick, and why writing one is worth your time.
Reachability — the three-tier model
Stated booleans vs real call-graph evaluation vs semantic intent-to-use. The model the SSVC Reachability input is graded against, and where each scanner sits on it.
CycloneDX VEX
VEX as part of CycloneDX — travels with the SBOM, points to components by PURL.
SARIF — the SAST output format
Static Analysis Results Interchange Format. The JSON shape every SAST tool emits, with the dialect differences that catch you out.
EOL gating — when a CVE means migrate, not patch
End-of-life detection for runtimes, packages, and container base images. The SSVC mapping when no upstream fix will ever exist.
Supply-chain threats beyond CVEs
Typosquatting, dependency confusion, namespace squatting, maintainer takeover, protestware, install-script abuse. CVE-shaped triage doesn't fit any of them; OpenVEX against a MAL- record does.
JVM — Maven, Gradle, Ivy, SBT
Dependency management for Java, Kotlin, and Scala. Maven and Gradle each carry a dozen distinct ways to specify, coerce, override, and pin a dependency — pick the one whose blast radius matches your finding.
OpenVEX
Standalone, lightweight VEX — for findings that don't map to an SBOM component.
Go modules
go.mod, go.sum, replace directives, GOSUMDB integrity, vendor mode.
Rust — Cargo
Cargo.lock, [patch.crates-io], cargo update mechanics.
Ruby — Bundler
Gemfile, Gemfile.lock, transitive coercion via explicit declaration.
.NET — NuGet
packages.lock.json, Directory.Packages.props, Central Package Management.
PHP — Composer
composer.json, composer.lock, conflict declarations.
Swift / iOS — SwiftPM, CocoaPods, Carthage
Three competing dependency managers for the Apple ecosystem.
Other ecosystems
Dart pub, Mix, Rebar3, Cabal/Stack, opam, Nix flakes, Conan, vcpkg.