Vulnerability Mitigation Strategies & VEX Rules

Discovering vulnerabilities is only the first stepthe critical question is how to respond. Not every vulnerability requires immediate patching, and understanding your response options enables efficient resource allocation while maintaining security posture. DevGuard supports four distinct mitigation strategies based on the VEX standard1 and provides VEX Rules to automate these strategies at scale.

The Four Mitigation Strategies

graph TD
    A[Vulnerability<br/>Discovered] --> B{Analysis}

    Q1[Patch Available?]
    Q2[Not Exploitable?]
    Q3[Business Decision]
    Q4[Need More Info]

    B --> Q1
    B --> Q2
    B --> Q3
    B --> Q4

    Q1 --> C[Fix/Patch]
    Q2 --> D[Not Affected/False Positive]
    Q3 --> E[Accept Risk]
    Q4 --> F[Under Investigation]

    F --> B
    C --> G[Resolved]
    D --> G
    E --> H[Monitored]

    style A fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000
    style B fill:#424242,stroke:#212121,stroke-width:2px,color:#fff
    style Q1 fill:#e0e0e0,stroke:#757575,stroke-width:1px,color:#000
    style Q2 fill:#e0e0e0,stroke:#757575,stroke-width:1px,color:#000
    style Q3 fill:#e0e0e0,stroke:#757575,stroke-width:1px,color:#000
    style Q4 fill:#e0e0e0,stroke:#757575,stroke-width:1px,color:#000
    style C fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#000
    style D fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000
    style E fill:#fce4ec,stroke:#c2185b,stroke-width:2px,color:#000
    style F fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#000
    style G fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px,color:#000
    style H fill:#ffccbc,stroke:#d84315,stroke-width:3px,color:#000

1. Fix/Patch: Eliminate the Vulnerability

Patching involves updating vulnerable components to versions where the security flaw has been corrected. This is the gold standardit eliminates the root cause entirely rather than merely reducing risk.

When to use: This should be your default strategy whenever a patched version is available and can be safely deployed.

Example: Your JSON parsing library has a vulnerability in version 2.3.1. You update to version 2.3.2 which contains the fix, test, and deploycompletely eliminating the vulnerability.

2. Not Affected: Document Why It Doesn't Apply

Not Affected indicates that while a vulnerability exists in your dependencies, it doesn't actually impact your application's security. This prevents wasted effort on vulnerabilities that pose no real risk.

When to use: After analysis, you've determined your application cannot be exploited through this vulnerability. The vulnerable code may be present but isn't used in a way that creates risk.

VEX Justification Categories1:

  • Vulnerable code not present: Your version doesn't contain the flaw
  • Vulnerable code not in execute path: The code exists but is never called
  • Inline mitigations exist: Controls prevent exploitation
  • Component not affected: Only affects specific configurations you don't use

3. Accept Risk: Conscious Business Decision

Accept Risk represents a business decision to knowingly operate with a vulnerability present, accepting the associated risk. You acknowledge the vulnerability could be exploited but choose not to remediate for specific business reasons.

When to use:

  • Remediation cost exceeds potential impact
  • Unlikely conditions required for exploitation
  • Business constraints prevent immediate action
  • Sufficient compensating controls reduce risk to acceptable levels

Document the business justification, risk assessment, compensating controls, and establish a review date. Risk acceptance typically requires stakeholder approval.

4. Under Investigation: Assessment in Progress

Under Investigation is a transitional state indicating active analysis of whether and how a vulnerability affects your application. Every Under Investigation vulnerability should eventually move to Fixed, Not Affected, or Accept Risk.

When to use: Immediately upon discovering vulnerabilities that require analysis before determining appropriate response, especially for newly disclosed findings where impact isn't immediately clear.

Establish investigation timelines based on severity: critical findings within 24 hours, high within 72 hours, medium within one week.

Decision Framework

High CVSS + High EPSS + Direct DependencyPrioritize patching immediately

High CVSS + Low EPSS + Deep TransitiveAnalyze exploitability; likely Not Affected

Vulnerability in Optional FeatureDisable and mark Not Affected

No Patch + Actively ExploitedImplement controls, Accept Risk with documentation

Unclear ImpactMark Under Investigation with timeline

VEX Rules: Automating Mitigation at Scale

Manually triaging every vulnerability is unsustainable. Many vulnerabilities recur across assets, versions, and scansoften with identical conclusions. VEX Rules let you define reusable mitigation decisions that are automatically applied whenever a matching vulnerability is detected.

A VEX rule consists of three parts:

  1. A CVE identifierwhich vulnerability to match
  2. A path patternwhich dependency paths to match (with wildcard support)
  3. An actionmark as False Positive or Accept Risk
graph TD
    A["Scan detects vulnerabilities"] --> B["For each vulnerability"]
    B --> C{"CVE matches<br/>a VEX rule?"}
    C -->|No| D["Stays open<br/>(manual triage needed)"]
    C -->|Yes| E{"Dependency path<br/>matches rule pattern?"}
    E -->|No| D
    E -->|Yes| F["Rule action applied<br/>automatically"]
    F --> G["False Positive or<br/>Accept Risk"]

    style A fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000
    style B fill:#e0e0e0,stroke:#757575,stroke-width:1px,color:#000
    style C fill:#424242,stroke:#212121,stroke-width:2px,color:#fff
    style D fill:#ffccbc,stroke:#d84315,stroke-width:2px,color:#000
    style E fill:#424242,stroke:#212121,stroke-width:2px,color:#fff
    style F fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000
    style G fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000

When a scan discovers vulnerabilities, DevGuard matches each one against all enabled VEX rules. If a rule matches (same CVE and matching dependency path), the corresponding action is applied automaticallyno manual intervention required.

Path Pattern Matching

VEX rules use suffix-based path pattern matching with wildcard support to target specific dependency paths. Each vulnerability in DevGuard has a dependency paththe chain of packages from your application root down to the vulnerable component.

For example, a vulnerability path might look like:

pkg:npm/my-app@1.0.0 → pkg:npm/express@4.18.0 → pkg:npm/qs@6.5.0

A path pattern is an ordered list of elements where each element is either a literal package identifier or a wildcard (*). The pattern matches against the suffix of the vulnerability path.

Pattern Examples

PatternMatchesExplanation
["pkg:npm/qs@6.5.0"]Any path ending in qs@6.5.0Exact match on the vulnerable package regardless of how it's reached
["*", "pkg:npm/qs@6.5.0"]Any path ending in qs@6.5.0Wildcard before target—equivalent to above since suffix matching is used
["pkg:npm/express@4.18.0", "*", "pkg:npm/qs@6.5.0"]Paths where express@4.18.0 leads (through any intermediaries) to qs@6.5.0Scoped match—only applies when qs is reached through express
["*"]Any pathBlanket rule—applies regardless of dependency path

How Matching Works

The matching algorithm works by trying the pattern against increasingly longer suffixes of the vulnerability path:

  1. Count the non-wildcard elements in the pattern to determine the minimum path length
  2. Starting from the shortest possible suffix, try to match the pattern
  3. A wildcard (*) matches zero or more path elements at that position
  4. If any suffix produces a match, the rule applies

This means ["pkg:npm/qs@6.5.0"] matches the path [my-app, express, qs@6.5.0] because the suffix [qs@6.5.0] matches the pattern.

Rule Sources

VEX rules can enter DevGuard through three paths:

Manual creationA developer analyzes a vulnerability and creates a rule through the DevGuard UI or API. The rule is immediately applied to all matching existing vulnerabilities.

VEX document uploadExternal VEX documents (CycloneDX VEX format) are parsed and converted into VEX rules. This is the primary way to import assessments from upstream vendors or security tools. The DevGuard scanner supports this via devguard-scanner vex <vex-file>.

External VEX referencesWhen an SBOM contains external reference URLs pointing to VEX documents, DevGuard fetches and ingests those documents automatically. This enables upstream library maintainers to publish VEX assessments that flow downstream to all consumers.

Paranoid Mode

By default, VEX rules from external sources (uploaded VEX documents, external references) are automatically enabled and applied. For environments requiring stricter control, assets can be configured with Paranoid Mode.

When Paranoid Mode is enabled, externally-sourced rules are created in a disabled state. They appear in the VEX rules list but have no effect until a team member manually reviews and enables them. This gives security teams full control over which external assessments they trust.

Sharing VEX Assessments

One of the most powerful aspects of VEX is that assessments are shareable. When you determine a vulnerability is a false positive in your library, every downstream consumer of that library benefits from your analysis.

How Sharing Works

DevGuard generates standardized CycloneDX VEX documents from your assessments. These can be:

  • Published as external references in your SBOM, so downstream consumers automatically ingest your assessments
  • Exported and shared with customers, auditors, or partner organizations
  • Attached to releases in your CI/CD pipeline so they travel alongside your artifacts
graph TD
    subgraph Upstream ["Library Maintainer"]
        A1[Analyze CVE-2024-1234] --> A2[Create VEX: Not Affected]
        A2 --> A3[Publish VEX reference in SBOM]
    end

    subgraph DevGuard ["DevGuard"]
        B1[Ingest upstream SBOM] --> B2[Fetch VEX reference]
        B2 --> B3[Create VEX Rule]
        B3 --> B4{Paranoid Mode?}
        B4 -->|No| B5[Rule enabled,<br/>auto-applied]
        B4 -->|Yes| B6[Rule disabled,<br/>awaiting review]
    end

    A3 --> B1

    style Upstream fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#000
    style A1 fill:#e8f5e9,stroke:#388e3c,stroke-width:1px,color:#000
    style A2 fill:#e8f5e9,stroke:#388e3c,stroke-width:1px,color:#000
    style A3 fill:#e8f5e9,stroke:#388e3c,stroke-width:1px,color:#000
    style DevGuard fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000
    style B1 fill:#e3f2fd,stroke:#1976d2,stroke-width:1px,color:#000
    style B2 fill:#e3f2fd,stroke:#1976d2,stroke-width:1px,color:#000
    style B3 fill:#e3f2fd,stroke:#1976d2,stroke-width:1px,color:#000
    style B4 fill:#424242,stroke:#212121,stroke-width:2px,color:#fff
    style B5 fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
    style B6 fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000

This creates a chain of trust: library maintainers assess vulnerabilities once, and all downstream consumers automatically benefitdramatically reducing the industry-wide duplication of vulnerability analysis work.

Why Path Patterns Are Essential for Sharing

Consider a vulnerability (CVE-2024-XXXX) in the debug package, discovered through this dependency chain:

next@14.0.0 → react@18.2.0 → debug@4.3.0 (CVE-2024-XXXX)

The Next.js team analyzes this and concludes: not affected. But the critical question for the community is: why is it not affected, and where in the chain is the vulnerability blocked?

Scenario A: Next.js never calls the React APIs that lead to debug. The false positive lives at the boundary between Next.js and React. Any other consumer of React that does call those APIs could still be affected.

Scenario B: React never calls the vulnerable function in debug. The false positive lives at the boundary between React and debug. This means no consumer of React is affectedthe assessment is generalizable to the entire ecosystem.

The path pattern in the VEX rule captures exactly this distinction:

PatternWhere is it blocked?Who benefits?
["pkg:npm/next@14.0.0", "*", "pkg:npm/debug@4.3.0"]At Next.js — Next.js doesn't reach the vulnerable code through ReactOnly projects using Next.js
["pkg:npm/react@18.2.0", "*", "pkg:npm/debug@4.3.0"]At React — React never calls the vulnerable debug functionAll React consumers

Without the path pattern, there is no way to determine whether a "not affected" assessment can be generalized beyond the original project or whether it only applies to one specific consumer.

Importantly, DevGuard itself is both a producer and consumer of VEX. When you triage a vulnerability in DevGuardwhether manually or through a VEX rulethat assessment becomes part of the VEX document DevGuard generates for your SBOM. If another DevGuard instance (or any VEX-compatible tool) consumes your SBOM, it automatically picks up your assessments as VEX rules. This means two teams using DevGuard on related projects can benefit from each other's triage work without any extra configurationDevGuard's output feeds directly back into DevGuard as input.

Crowdsourced VEX (coming soon)

Today, most vulnerability triage is duplicated effort. When a CVE is published against a widely-used library, thousands of organizations independently analyze whether it affects themoften reaching the same conclusion. This is wasteful.

DevGuard is designed with crowdsourced vulnerability assessment as a first-class concept. Rather than treating VEX as something each organization does in isolation, DevGuard aggregates assessments from a crowd of independent sources to build community consensus.

How It Works

Each participant in the crowd submits VEX assessments for open-source components. DevGuard aggregates these assessments and, when a sufficient majority agrees on a conclusion, surfaces that as a community recommendation. Each source in the crowd is assigned a trust score based on its track recordhow often its assessments align with the eventual consensus, and how consistently it produces accurate results.

graph TD
    subgraph Crowd ["The Crowd"]
        direction LR
        S1["Organization A<br/>(trust: 0.85)"]
        S2["Organization B<br/>(trust: 0.72)"]
        S3["Automated Analyzer<br/>(trust: 0.91)"]
        S4["Upstream Maintainer<br/>(trust: 0.95)"]
    end

    subgraph Aggregation ["DevGuard Aggregation"]
        A1["Collect assessments<br/>for CVE-2024-1234"]
        A2["Weight by trust score"]
        A3{"Weighted majority<br/>consensus?"}
        A4["Community recommendation:<br/>Not Affected"]
    end

    S1 -->|not_affected| A1
    S2 -->|not_affected| A1
    S3 -->|not_affected| A1
    S4 -->|not_affected| A1
    A1 --> A2 --> A3
    A3 -->|Yes| A4

    subgraph Consumer ["New User"]
        C1["Sees consensus + trust info"] --> C2{Trust level?}
        C2 -->|Auto-apply| C3["Rule enabled"]
        C2 -->|Paranoid Mode| C4["Rule disabled,<br/>awaiting review"]
    end

    A4 --> C1

    style Crowd fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#000
    style S1 fill:#e8f5e9,stroke:#388e3c,stroke-width:1px,color:#000
    style S2 fill:#e8f5e9,stroke:#388e3c,stroke-width:1px,color:#000
    style S3 fill:#e8f5e9,stroke:#388e3c,stroke-width:1px,color:#000
    style S4 fill:#e8f5e9,stroke:#388e3c,stroke-width:1px,color:#000
    style Aggregation fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000
    style A1 fill:#e3f2fd,stroke:#1976d2,stroke-width:1px,color:#000
    style A2 fill:#e3f2fd,stroke:#1976d2,stroke-width:1px,color:#000
    style A3 fill:#424242,stroke:#212121,stroke-width:2px,color:#fff
    style A4 fill:#e3f2fd,stroke:#1976d2,stroke-width:1px,color:#000
    style Consumer fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000
    style C1 fill:#fff3e0,stroke:#f57c00,stroke-width:1px,color:#000
    style C2 fill:#424242,stroke:#212121,stroke-width:2px,color:#fff
    style C3 fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000
    style C4 fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000

Who Is in the Crowd?

The crowd is not limited to human reviewers. Any entity that can produce a VEX assessment is a valid participant:

  • Organizations sharing their manual assessments (anonymized) for components they use
  • Upstream library maintainers publishing VEX statements alongside their releases
  • Automated reachability analyzers that use static analysis to determine whether vulnerable code is actually callable

Automated tools are particularly valuable because they operate at ecosystem scale. For example, VeXing NPM2 is an automated pipeline that uses call graph analysis to assess npm packages at scale. By analyzing over 172,000 npm packages, it found that roughly 70% of vulnerabilities reported by metadata-based scanners like npm audit are false positivesthe vulnerable code is simply never called. These automated assessments feed directly into the crowd as a high-trust source.

Trust Scores

Not all assessments carry equal weight. A trust score reflects how reliable a source has been historically:

  • Automated analyzers with proven precision (like reachability tools) can earn high trust scores through validation against known ground truths
  • Upstream maintainers who publish VEX for their own packages naturally have high authority over those specific components
  • Organizations build trust over time as their assessments consistently align with community consensus
  • New participants start with a lower trust score that increases as their contributions are validated

This trust-weighted model means a single high-confidence automated analysis can be more influential than several unverified human opinionsand vice versa, expert human judgment on context-specific questions outweighs generic automated output.

DevGuard Support

Issue Tracker Integration: Automatically create and sync tickets in GitHub, GitLab, or Jira. Status updates flow bidirectionally.

VEX Statement Generation: Export assessments as standardized VEX documents for customers and auditors.

Automated State Detection: Automatically transitions vulnerabilities to Fixed when you deploy patched versions.

Risk-Based Notifications: Configure webhooks for high-risk discoveries or risk score changes.

VEX Rule Management: Create, review, enable/disable, and delete VEX rules through the UI or API. Each rule shows how many vulnerabilities it currently matches.


References

Footnotes

  1. CISA, Vulnerability Exploitability eXchange (VEX), Cybersecurity and Infrastructure Security Agency, 2023, https://www.cisa.gov/sbom 2

  2. Bastin, T., VeXing NPMCall Graph Analysis for False Positive Reduction in JavaScript Vulnerability Detection, Master's Thesis, 2025, https://github.com/l3montree-dev/vexing-npm