# vens-action: reranking Trivy/Grype CVEs by real risk in CI

> Source: <https://dev.to/fahed-dorgaa/vens-action-reranking-trivygrype-cves-by-real-risk-in-ci-1eec>
> Published: 2026-05-28 09:06:12+00:00

If you run Trivy or Grype in CI and triage the output by CVSS, this is the thing I wish I'd had two years ago.

Quick recap. Trivy and Grype hand you a list of CVEs. CVSS is a score in a vacuum — it doesn't know whether a service runs in a private subnet behind mTLS, or sits on the open internet handling payment cards. [vens](https://github.com/venslabs/vens) reads your scan output plus a YAML describing the service (exposure, data sensitivity, business criticality, controls, compliance, …), runs every CVE through an LLM with that context, and emits a CycloneDX VEX with OWASP Risk Rating scores. You gate the build on those instead.

[ vens-action](https://github.com/venslabs/vens-action) is the GitHub Action wrapper — install, invocation, build gate, packaged as a composite. Here's the minimum to drop it in.

`.vens/config.yaml`

. Three context fields are the floor; the full annotated reference is in `examples/quickstart/config.yaml`

`serialNumber`

of your CycloneDX SBOM (or an ad-hoc one — see below).The bare minimum:

```
project:
  name: "checkout-api"
context:
  exposure: "internet"
  data_sensitivity: "high"
  business_criticality: "critical"
```

For scoring that actually reflects your service, fill in the rest — security controls (WAF, IDS, segmentation, …), compliance requirements, availability target, free-form notes. The annotated reference lives in [ examples/quickstart/config.yaml](https://github.com/venslabs/vens/blob/main/examples/quickstart/config.yaml). Wrong values → wrong scores, so this file deserves the same review process as the rest of your code (CODEOWNERS, PR review, the works).

vens writes a CycloneDX VEX whose `vulnerabilities[].affects[].ref`

entries are [BOM-Link](https://cyclonedx.org/docs/1.7/json/#vulnerabilities_items_affects_items_ref_anyOf_i0) references — they must point back to the `serialNumber`

of the SBOM the scan was produced from.

If you already have a CycloneDX SBOM for the artifact, pull the serial from it:

```
SBOM_UUID=$(jq -r .serialNumber sbom.cdx.json)
```

If you don't have one yet, generate an ad-hoc serial and reuse it across rescans of the same service so the BOM-Link stays stable:

```
SBOM_UUID="urn:uuid:$(uuidgen | tr '[:upper:]' '[:lower:]')"
```

Store the value as a repo variable, say `vars.SBOM_SERIAL`

. Flag reference: [ vens generate --sbom-serial-number](https://venslabs.github.io/vens/reference/generate/#-sbom-serial-number-urnuuid).

`.github/workflows/scan.yml`

:

```
name: scan
on: [push]
permissions:
  contents: read
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Trivy scan
        run: trivy image python:3.11-slim --format json --output report.json

      - name: vens
        id: vens
        uses: venslabs/vens-action@v0.1.0
        with:
          version: v0.3.2
          config-file: .vens/config.yaml
          input-report: report.json
          sbom-serial-number: ${{ vars.SBOM_SERIAL }}
          llm-provider: openai
          llm-model: gpt-4o
          llm-api-key: ${{ secrets.OPENAI_API_KEY }}
          fail-on-severity: critical
          enrich: "true"

      - uses: actions/upload-artifact@v4
        with:
          name: vens
          path: |
            ${{ steps.vens.outputs.vex-file }}
            ${{ steps.vens.outputs.enriched-report }}
```

Each run gives you a CycloneDX VEX (`vex-file`

), your original Trivy report annotated with `Custom.owasp_score`

(`enriched-report`

, when `enrich: true`

), and per-severity counts as step outputs (`count-critical`

, `count-high`

, …). Pipe the counts into dashboards, PR comments, whatever you already do with scan metrics.

`fail-on-severity: critical`

makes the step fail if any CVE comes out CRITICAL by OWASP (score ≥ 60). Drop the line if you just want artifacts and a manual review.

`llm-provider: ollama`

+ `llm-base-url: http://ollama.corp:11434`

.`bin-path`

instead of `version`

. Skips the download + checksum step entirely.`uses: venslabs/vens-action@<commit-sha>`

. Renovate and Dependabot both follow SHA-pinned actions.CVSS sorts vulnerabilities like a smoke detector that can't tell if you're cooking or your kitchen is on fire. A 9.8 on an internal service with no PII and no internet exposure is rarely your urgent problem. A 5.4 on the auth path with cleartext token logging probably is. Your team knows the difference — but a spreadsheet per service doesn't scale, and most tools that do contextual scoring are paid SaaS with their own opinions.

vens is OSS, Apache 2.0. The action is a thin composite around the CLI. Issues, feedback, PRs — I read them.
