Analysis_Tools

CPE Applicability Statement Generation

Document Purpose: Technical documentation for Python-native CPE-AS generation system integrated with NVD-ish records
Created: January 12, 2026
Last Updated: January 25, 2026
Implementation: src/analysis_tool/core/cpe_as_generator.py
Tests: test_suites/nvd-ish_collector/test_cpe_as_integration.py


Table of Contents

  1. Overview
  2. Input Specification
  3. Pattern Processing
  4. Pre and Post Processing
  5. NVD-ish Integration
  6. Known Limitations

1. Overview

Purpose

The CPE-AS generation system transforms CVE 5.0 affected array entries into NVD-style CPE Applicability Statement JSON using pure Python. This enables automated generation of machine-readable vulnerability configuration data from CVE records.

System Capabilities

  1. Input Processing: Accepts CVE 5.0 affected[] array entries with CPE base string(s)
  2. Output Generation: Produces NVD-style configurations[] arrays with CPE match objects
  3. NVD-ish Integration: Embeds generated CPE-AS directly into NVD-ish records during collection
  4. Pattern Recognition: Applies 5 distinct processing patterns (3.1-3.5) covering version ranges, exact versions, and metadata-only cases
  5. Quality Tracking: Flags 10 types of data quality concerns for human review

2. Input Specification

Required Inputs

  1. CVE 5.0 affected entry - Single platform from affected[] array
  2. CPE base string - Generated via platform_entry_registry.py CPE cache
  3. Settings/flags (optional) - Pattern detection settings

Affected Entry Field Processing

Essential Fields

Optional Fields


2.1 cpeMatch Object Property Order

Implementation Standard: All cpeMatch objects serialize properties in the following explicit order:

  1. versionsEntryIndex - Maps to source versions[] array index (0-based, null if no versions array)
  2. appliedPattern - (Optional) Pattern reference for traceability (e.g., “exact.single”, “range.lessThan”, “inference.affectedFromWildcardExpansion”). Omitted (null) for truly unknown patterns.
  3. vulnerable - Boolean indicating vulnerability status (true for affected entries, false for metadata-only entries)
  4. criteria - (Optional) Full CPE 2.3 formatted string. Omitted for metadata-only objects.
  5. versionStartIncluding - (Optional) Lower bound version, inclusive
  6. versionStartExcluding - (Optional) Lower bound version, exclusive
  7. versionEndIncluding - (Optional) Upper bound version, inclusive
  8. versionEndExcluding - (Optional) Upper bound version, exclusive
  9. concerns - (Optional) Array of concern identifiers for metadata-only or flagged entries (e.g., ["statusUnaffected"], ["updatePatternsInRange"])
  10. Additional optional fields (e.g., updatePattern) follow core properties

Rationale:

Example Property Order (Standard cpeMatch):

{
  "versionsEntryIndex": 0,
  "appliedPattern": "range.lessThan",
  "vulnerable": true,
  "criteria": "cpe:2.3:a:vendor:product:*:*:*:*:*:*:*:*",
  "versionStartIncluding": "2.0",
  "versionEndExcluding": "2.5"
}

Example Property Order (Metadata-only cpeMatch):

{
  "versionsEntryIndex": 1,
  "vulnerable": false,
  "concerns": ["statusUnaffected"]
}

All examples throughout this document follow this ordering convention.


3. Pattern Processing

3.1 Output Pattern: Single cpeMatch object - No Version

Single cpeMatch with wildcard version (*) when no specific version data is available or all versions are affected.

{
  "versionsEntryIndex": 0,  // Index of versions[] entry, or null if no versions array
  "appliedPattern": "noVersion.allAffected",
  "vulnerable": true,
  "criteria": "cpe:2.3:a:example:cpebasestring:*:*:*:*:*:*:*:*"
}

Note: versionsEntryIndex will be:


Pattern A: Explicit “All Versions” via defaultStatus

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "affected"
  // No versions[] array present
}

Pattern A-Variant: Explicit wildcard version

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "affected",
  "versions": [
    {"version": "*", "status": "affected"}
  ]
}

Pattern B: Empty versions array

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "affected",
  "versions": []
}

Pattern C: Only Version Placeholder Values

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "affected",
  "versions": [
    {"version": "unspecified", "status": "affected"},
    // OR
    {"version": "all", "status": "affected"},
    // OR
    {"version": "n/a", "status": "affected"},
    // OR other placeholder terminology
  ]
}

Pattern C-Variant: Placeholder version AND placeholder changes array

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "affected",
  "versions": [
    {
      "version": "unspecified",
      "status": "affected",
      "changes": [
        {"at": "unknown", "status": "unaffected"}
      ]
    }
  ]
}

Result: Still Pattern 3.1 - all version-related data is placeholders

Pattern D: defaultStatus=”unknown” with no/empty versions

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "unknown"
  // No versions[] array OR versions: []
}

Result: Metadata-only cpeMatch object
Output:

{
  "versionsEntryIndex": null,
  "vulnerable": false,
  "concerns": ["defaultStatusUnknown"]
}

Logic:

VERSION_PLACEHOLDER_VALUES (Centralized in platform_entry_registry.py):

VERSION_PLACEHOLDER_VALUES = [
    'unspecified', 'unknown', 'none', 'undefined', 'various',
    'n/a', 'not available', 'not applicable', 'unavailable',
    'na', 'nil', 'tbd', 'to be determined', 'pending',
    'not specified', 'not determined', 'not known', 'not listed',
    'not provided', 'missing', 'empty', 'null', '-', 
    'multiple versions', 'see references', 'see advisory', 
    'check', 'noted', 'all'
]
# Total: 28 patterns (case-insensitive)
# JavaScript adds: "*" (wildcard) to this list at runtime
# Note: 'all' included - observed in real CVE data as wildcard indicator
# Note: "0" is NOT a placeholder - treated as literal version value

Analysis:


3.2 Output Pattern: No affected platforms - Metadata-only cpeMatch

When no platforms are vulnerable/affected, generate a metadata-only cpeMatch object to indicate the condition was processed.

[
  {
    "versionsEntryIndex": 0,
    "vulnerable": false,
    "concerns": ["noAffectedPlatforms"]
  }
]

Pattern A: defaultStatus=affected with only unaffected versions

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "affected",
  "versions": [
    {"version": "1.0", "status": "unaffected"},
    {"version": "2.0", "status": "unaffected"}
  ]
}

Pattern B: defaultStatus=unaffected (nothing to output)

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "unaffected"
  // No versions[] or all versions are unaffected
}

Pattern C: Placeholder with unaffected status

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "affected",
  "versions": [
    {"version": "unspecified", "status": "unaffected"}
  ]
}

Pattern D: defaultStatus=’unknown’ with all unaffected

{
  "vendor": "acme",
  "product": "widget",
  "defaultStatus": "unknown",
  "versions": [
    {"version": "1.0", "status": "unaffected"},
    {"version": "2.0", "status": "unaffected"}
  ]
}

Pattern E: Changes array results in immediate unaffected

{
  "version": "1.0",
  "status": "affected",
  "changes": [
    {"at": "1.0", "status": "unaffected"}
  ]
}

Note: Change occurs at same version as base → no affected range exists

Logic:

Analysis:


3.3 Output Pattern: Exact versions

One or more cpeMatch objects with exact version values in criteria field (no version range fields).

Pattern A: Single exact version

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “1.2.3”,
“status”: “affected”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:1.2.3:::::::*“
}</pre>

Pattern B: Multiple discrete versions (1:1 transformation)

Input Pattern Output cpeMatch Objects
<pre>{
“versions”: [
{
“version”: “1.2.3”,
“status”: “affected”
},
{
“version”: “1.2.5”,
“status”: “affected”
},
{
“version”: “2.0.1”,
“status”: “affected”
}
]
}</pre>
<pre>[
{
“versionsEntryIndex”: 0,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:1.2.3:::::::
},
{
“versionsEntryIndex”: 1,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:1.2.5:
::::::
},
{
“versionsEntryIndex”: 2,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:2.0.1:::::::*“
}
]</pre>

Note: Three version entries produce three cpeMatch objects (1:1 transformation per entry)

Pattern C: Mixed affected/unaffected/unknown versions

Input Pattern Output cpeMatch Objects
<pre>{
“versions”: [
{
“version”: “1.0”,
“status”: “affected”
},
{
“version”: “1.1”,
“status”: “unaffected”
},
{
“version”: “1.2”,
“status”: “affected”
},
{
“version”: “2.0”,
“status”: “unknown”
}
]
}</pre>
<pre>[
{
“versionsEntryIndex”: 0,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:1.0:::::::
},
{
“versionsEntryIndex”: 1,
“vulnerable”: false,
“concerns”: [“statusUnaffected”]
},
{
“versionsEntryIndex”: 2,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:1.2:
::::::
},
{
“versionsEntryIndex”: 3,
“vulnerable”: false,
“concerns”: [“statusUnknown”]
}
]</pre>

Note: All four version entries produce cpeMatch objects. Affected versions generate full criteria; unaffected and unknown versions produce metadata-only objects with concerns array.

Pattern D: defaultStatus conflict - version.status takes precedence

Input Pattern Output cpeMatch Object
<pre>{
“defaultStatus”: “unaffected”,
“versions”: [
{
“version”: “1.2.3”,
“status”: “affected”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:1.2.3:::::::*“
}</pre>

Note: version.status=’affected’ overrides defaultStatus=’unaffected’ - produces vulnerable=true output

Logic (per version entry):

Analysis:

Iteration Example (1:1 transformation):

Input Pattern Output cpeMatch Objects
<pre>{
“versions”: [
{“version”: “1.0”, “status”: “affected”},
{“version”: “2.0”, “status”: “affected”},
{“version”: “3.0”, “status”: “affected”}
]
}</pre>
<pre>[
{
“versionsEntryIndex”: 0,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:1.0:::::::
},
{
“versionsEntryIndex”: 1,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:2.0:
::::::
},
{
“versionsEntryIndex”: 2,
“appliedPattern”: “exact.single”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product:3.0:::::::*“
}
]</pre>

Note: Three version entries produce three cpeMatch objects (1:1 transformation per entry)


3.4 Output Pattern: Single range per entry (1:1 transformation)

Single cpeMatch object with version range properties (versionStartIncluding/Excluding, versionEndIncluding/Excluding).

Pattern A: Explicit range with lessThan

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “0”,
“status”: “affected”,
“lessThan”: “2.0”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.lessThan”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “0”,
“versionEndExcluding”: “2.0”
}</pre>

Pattern B: Explicit range with lessThanOrEqual

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “1.0”,
“status”: “affected”,
“lessThanOrEqual”: “1.9.5”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.lessThanOrEqual”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “1.0”,
“versionEndIncluding”: “1.9.5”
}</pre>

Note on Update Patterns in Ranges: If range boundaries contain update patterns (e.g., "10.0 SP 1" to "10.0 SP 3"), current implementation DETECTS but does NOT APPLY transformations. The original untransformed values are used in versionStartIncluding/versionEndExcluding. This is flagged in metadata with blocked_by_ranges: true for visibility.

Pattern C: Wildcard in lessThanOrEqual (open-ended)

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “1.0”,
“status”: “affected”,
“lessThanOrEqual”: “*“
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.openEnd”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “1.0”
}</pre>

Note: Wildcard upper bound means “all versions from 1.0 onward” - versionEnd field omitted

Pattern D: Single status change (changes array)

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “5.0”,
“status”: “affected”,
“changes”: [
{
“at”: “5.0.3”,
“status”: “unaffected”
}
]
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.changesFixed”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “5.0”,
“versionEndExcluding”: “5.0.3”
}</pre>

Note: Range from base version to change point

Pattern D-Variant: Placeholder version with real changes data

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “unspecified”,
“status”: “affected”,
“changes”: [
{
“at”: “1.2.3”,
“status”: “unaffected”
}
]
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.placeholderChanges”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionEndExcluding”: “1.2.3”
}</pre>

Note: version field is placeholder - versionStart omitted, changes[].at provides end boundary

Pattern E: Inverse single change (unaffected→affected)

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “1.0”,
“status”: “unaffected”,
“changes”: [
{
“at”: “1.5”,
“status”: “affected”
}
]
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.changesIntroduced”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “1.5”
}</pre>

Note: Range starts where status changes to affected, no end boundary (open-ended)

Pattern F: Open-ended beginning (no version field)

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“status”: “affected”,
“lessThan”: “2.0”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.openStart”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionEndExcluding”: “2.0”
}</pre>

Note: Everything before 2.0 is affected - versionStart omitted

Pattern G: Placeholder in upper bound

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “1.0”,
“status”: “affected”,
“lessThan”: “unknown”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.placeholderUpperBound”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “1.0”
}</pre>

Note: Placeholder in lessThan treated as open-ended - versionEnd omitted

Pattern H: version=”0” special case

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “0”,
“status”: “affected”,
“lessThan”: “2.0”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.zeroStart”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “0”,
“versionEndExcluding”: “2.0”
}</pre>

Note: “0” is treated as a literal version value, not a placeholder. Current implementation includes “0” NOT in VERSION_PLACEHOLDER_VALUES, so it outputs versionStartIncluding="0" explicitly. Infer Affected Ranges also defaults to “0” when no start version is available.

Pattern I: defaultStatus override - version.status takes precedence

Input Pattern Output cpeMatch Object
<pre>{
“defaultStatus”: “unaffected”,
“versions”: [
{
“version”: “2.0”,
“status”: “affected”,
“lessThan”: “3.0”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.statusOverride”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “2.0”,
“versionEndExcluding”: “3.0”
}</pre>

Note: version.status=’affected’ overrides defaultStatus=’unaffected’ - produces vulnerable=true output

Logic (per version entry):

Analysis:

Iteration Example (1:1 transformation):

Input Pattern Output cpeMatch Objects
<pre>{
“versions”: [
{
“version”: “1.0”,
“status”: “affected”,
“lessThan”: “2.0”
},
{
“version”: “3.0”,
“status”: “affected”,
“lessThan”: “4.0”
}
]
}</pre>
<pre>[
{
“versionsEntryIndex”: 0,
“appliedPattern”: “range.lessThan”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “1.0”,
“versionEndExcluding”: “2.0”
},
{
“versionsEntryIndex”: 1,
“appliedPattern”: “range.lessThan”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “3.0”,
“versionEndExcluding”: “4.0”
}
]</pre>

Note: Two range entries produce two cpeMatch objects (1:1 transformation per entry)


3.5 Output Pattern: Multiple ranges from one entry (1:M transformation)

Single version entry with multiple status transitions producing multiple ranges.

Implementation Status: Not currently implemented in JavaScript - documented for Python implementation requirements.

Pattern A: Multiple status flip-flops

Input Pattern Output cpeMatch Objects
<pre>{
“versions”: [
{
“version”: “3.0”,
“status”: “affected”,
“changes”: [
{
“at”: “3.0.5”,
“status”: “unaffected”
},
{
“at”: “3.1.0”,
“status”: “affected”
},
{
“at”: “3.1.2”,
“status”: “unaffected”
}
]
}
]
}</pre>
<pre>[
{
“versionsEntryIndex”: 0,
“appliedPattern”: “multiRange.exactStatusTransitions”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “3.0”,
“versionEndExcluding”: “3.0.5”
},
{
“versionsEntryIndex”: 0,
“appliedPattern”: “multiRange.exactStatusTransitions”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “3.1.0”,
“versionEndExcluding”: “3.1.2”
}
]</pre>

Note: affected → unaffected → affected → unaffected creates two vulnerable ranges (vulnerability reintroduced)

Pattern B: Changes combined with range bounds

Input Pattern Output cpeMatch Objects
<pre>{
“versions”: [
{
“version”: “2.0”,
“status”: “affected”,
“lessThan”: “5.0”,
“changes”: [
{
“at”: “3.0”,
“status”: “unaffected”
},
{
“at”: “4.0”,
“status”: “affected”
}
]
}
]
}</pre>
<pre>[
{
“versionsEntryIndex”: 0,
“appliedPattern”: “multiRange.rangeStatusTransitions”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “2.0”,
“versionEndExcluding”: “3.0”
},
{
“versionsEntryIndex”: 0,
“appliedPattern”: “multiRange.rangeStatusTransitions”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “4.0”,
“versionEndExcluding”: “5.0”
}
]</pre>

Note: Changes array splits the overall lessThan range into sub-ranges based on status transitions

Logic:

Analysis:


Inference and Special Cases

Patterns requiring version ordering knowledge, inference, or complex interpretation.


3.6 Output Pattern: Multiple cpeMatch objects - Wildcard expansion

Implementation Priority: DEFERRED - Advanced feature with parsing complexity

Wildcard version patterns translated to version ranges.

Pattern A: Wildcard in lessThanOrEqual

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “5.4.0”,
“status”: “affected”,
“lessThanOrEqual”: “5.4.*“
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “inference.affectedFromWildcardExpansion”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “5.4.0”,
“versionEndExcluding”: “5.5.0”
}</pre>

Note: Wildcard “5.4.*” expanded to range [5.4.0, 5.5.0) by incrementing minor version

Pattern B: Wildcard in version field

Input Pattern Output cpeMatch Object
<pre>{
“versions”: [
{
“version”: “2.*”,
“status”: “affected”
}
]
}</pre>
<pre>{
“versionsEntryIndex”: 0,
“appliedPattern”: “inference.affectedFromWildcardExpansion”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “2.0”,
“versionEndExcluding”: “3.0”
}</pre>

Note: Wildcard “2.*” expanded to range [2.0, 3.0) by incrementing major version

Logic:

Analysis:


3.7 Output Pattern: Multiple cpeMatch objects - Infer Affected Ranges

Implementation Priority: DEFERRED - High-risk inference pattern with soundness concerns

Inferred vulnerable ranges from defaultStatus=’affected’ with unaffected RANGES (not exact versions).

Applicability Constraint: Infer Affected Ranges ONLY applies when unaffected versions have range constraints (lessThan, lessThanOrEqual). Exact unaffected versions without range constraints do NOT trigger inferred affected range detection.

Pattern A: Gaps between unaffected ranges

Input Pattern Output cpeMatch Objects
<pre>{
“defaultStatus”: “affected”,
“versions”: [
{
“version”: “1.0”,
“status”: “unaffected”,
“lessThan”: “2.0”
},
{
“version”: “3.0”,
“status”: “unaffected”,
“lessThan”: “4.0”
},
{
“version”: “5.0”,
“status”: “unaffected”,
“lessThanOrEqual”: “6.0”
}
]
}</pre>
<pre>[
{
“versionsEntryIndex”: null,
“appliedPattern”: “inference.affectedFromUnaffectedRanges”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionEndExcluding”: “1.0”
},
{
“versionsEntryIndex”: null,
“appliedPattern”: “inference.affectedFromUnaffectedRanges”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “2.0”,
“versionEndExcluding”: “3.0”
},
{
“versionsEntryIndex”: null,
“appliedPattern”: “inference.affectedFromUnaffectedRanges”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartIncluding”: “4.0”,
“versionEndExcluding”: “5.0”
},
{
“versionsEntryIndex”: null,
“appliedPattern”: “inference.affectedFromUnaffectedRanges”,
“vulnerable”: true,
“criteria”: “cpe:2.3:a:vendor:product::::::::”,
“versionStartExcluding”: “6.0”
}
]</pre>

Note: Unaffected ranges: [1.0-2.0), [3.0-4.0), [5.0-6.0]. Gaps filled with affected ranges.

Logic:


4. Pre and Post Processing

Transformations applied before pattern matching (preprocessing) and after output generation (postprocessing).

4.1 Update/Patch Pattern Extraction (Preprocessing)

Implementation Status: Fully implemented in JavaScript - comprehensive pattern library (500+ lines)

Version strings containing update/patch/service pack indicators must be parsed into base version + update component.

Supported Term Groups (standardized output):

Pattern Recognition (each term group supports):

  1. Space-separated: "10.0 SP 1"10.0:sp1
  2. Concatenated: "7.0.1update2"7.0.1:update2
  3. Dash-notation: "1.2.3-patch.4"1.2.3:patch4
  4. Flexible separators: "16.0.0_mr_7"16.0.0:mr7

Output: Base version in criteria position 5, update component in position 6 (normalized: lowercase, no spaces)

Application Scope:

Current JavaScript Behavior: Update patterns in range boundaries are detected and logged with blocked_by_ranges: true flag, but the original version string is used unchanged for versionStartIncluding/versionEndExcluding properties.

Implementation Note: JavaScript uses regex pattern library with specific-to-general ordering. Python implementation should port this proven logic.


4.2 CPE Update Field Specificity Enforcement (Postprocessing)

Implementation Status: Fully implemented in JavaScript

When multiple cpeMatch objects share the same base CPE components but differ in the update field, enforce non-overlapping specificity.

Problem: Version extraction may generate both:

Resolution: Convert wildcard update (*) to no-update (-) when specific updates exist for same base, ensuring each match has distinct scope

Example:

Before After
cpe:...:1.0:*:...
cpe:...:1.0:patch1:...
cpe:...:1.0:-:...
cpe:...:1.0:patch1:...

Logic:

  1. Group cpeMatch objects by base components (excluding update field at position 6)
  2. Identify groups with both wildcard (*) and specific update values
  3. Change wildcard to - (no update) to eliminate overlap
  4. Preserve all specific update values unchanged

Application: Applied after all pattern processing complete, before final output


5. NVD-ish Integration

Where CPE-AS Gets Embedded

Generated CPE-AS data is embedded in the NVD-ish record’s enrichedCVEv5Affected.cveListV5AffectedEntries[].cpeAsGeneration section.
Each CVE 5.0 affected[] entry produces one analysis entry with generated cpeMatch objects.

Mockup Example

Output: NVD-ish record with generated CPE-AS (partial - showing only enrichedCVEv5Affected structure)

{
  "id": "CVE-2024-1234",
  "sourceIdentifier": "cna@example.com",
  "published": "2024-01-15T00:00:00.000",
  "lastModified": "2024-01-15T00:00:00.000",
  "vulnStatus": "Analyzed",
  
  "descriptions": [...],
  "references": [...],
  "metrics": {...},
  
  "enrichedCVEv5Affected": {
    "toolExecutionMetadata": {...},
    "cpeDeterminationMetadata": [...],
    "cveListV5AffectedEntries": [
      {
        "originAffectedEntry": {
          "sourceId": "cna@example.com",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[0]",
          "vendor": "example",
          "product": "webapp",
          "defaultStatus": "unaffected",
          "versions": [
            {
              "version": "1.0",
              "status": "affected"
            },
            {
              "version": "2.0",
              "status": "affected",
              "lessThan": "2.5"
            },
            {
              "version": "3.0",
              "status": "affected",
              "changes": [
                {
                  "at": "3.2.1",
                  "status": "unaffected"
                }
              ]
            }
          ]
        },
        "sourceDataConcerns": {...},
        "aliasExtraction": {...},
        "cpeDetermination": {...},
        "cpeAsGeneration": {
          "sourceId": "Hashmire/Analysis_Tools v0.3.0",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[0]",
          "generatedCpeMatch": [
            {
              "versionsEntryIndex": 0,
              "appliedPattern": "exact.single",
              "vulnerable": true,
              "criteria": "cpe:2.3:a:example:webapp:1.0:*:*:*:*:*:*:*"
            },
            {
              "versionsEntryIndex": 1,
              "appliedPattern": "range.lessThan",
              "vulnerable": true,
              "criteria": "cpe:2.3:a:example:webapp:*:*:*:*:*:*:*:*",
              "versionStartIncluding": "2.0",
              "versionEndExcluding": "2.5"
            },
            {
              "versionsEntryIndex": 2,
              "appliedPattern": "range.changesFixed",
              "vulnerable": true,
              "criteria": "cpe:2.3:a:example:webapp:*:*:*:*:*:*:*:*",
              "versionStartIncluding": "3.0",
              "versionEndExcluding": "3.2.1"
            }
          ]
        }
      },
      {
        "originAffectedEntry": {
          "sourceId": "cna@example.com",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[1]",
          "vendor": "example",
          "product": "library",
          "defaultStatus": "affected",
          "versions": []
        },
        "sourceDataConcerns": {...},
        "aliasExtraction": {...},
        "cpeDetermination": {...},
        "cpeAsGeneration": {
          "sourceId": "Hashmire/Analysis_Tools v0.3.0",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[1]",
          "generatedCpeMatch": [
            {
              "versionsEntryIndex": null,
              "appliedPattern": "noVersion.allAffected",
              "vulnerable": true,
              "criteria": "cpe:2.3:a:example:library:*:*:*:*:*:*:*:*"
            }
          ]
        }
      },
      {
        "originAffectedEntry": {
          "sourceId": "cna@example.com",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[2]",
          "vendor": "example",
          "product": "server",
          "defaultStatus": "unaffected",
          "versions": [
            {
              "version": "16.0.0 MR 7",
              "status": "affected"
            }
          ]
        },
        "sourceDataConcerns": {...},
        "aliasExtraction": {...},
        "cpeDetermination": {...},
        "cpeAsGeneration": {
          "sourceId": "Hashmire/Analysis_Tools v0.3.0",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[2]",
          "generatedCpeMatch": [
            {
              "versionsEntryIndex": 0,
              "appliedPattern": "exact.single",
              "vulnerable": true,
              "criteria": "cpe:2.3:a:example:server:16.0.0:mr7:*:*:*:*:*:*"
            }
          ]
        }
      },
      {
        "originAffectedEntry": {
          "sourceId": "cna@example.com",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[3]",
          "vendor": "example",
          "product": "platform",
          "defaultStatus": "affected",
          "versions": [
            {
              "version": "abc123def",
              "versionType": "git",
              "status": "affected"
            },
            {
              "version": "10.0 SP 1",
              "status": "affected",
              "lessThanOrEqual": "10.0 SP 3"
            }
          ]
        },
        "sourceDataConcerns": {...},
        "aliasExtraction": {...},
        "cpeDetermination": {...},
        "cpeAsGeneration": {
          "sourceId": "Hashmire/Analysis_Tools v0.3.0",
          "cvelistv5AffectedEntryIndex": "cve.containers.cna.affected.[3]",
          "generatedCpeMatch": [
            {
              "versionsEntryIndex": 0,
              "concerns": ["versionTypeGit"]
            },
            {
              "versionsEntryIndex": 1,
              "appliedPattern": "range.lessThanOrEqual",
              "vulnerable": true,
              "criteria": "cpe:2.3:a:example:platform:*:*:*:*:*:*:*:*",
              "versionStartIncluding": "10.0 SP 1",
              "versionEndIncluding": "10.0 SP 3",
              "concerns": ["updatePatternsInRange"]
            }
          ]
        }
      }
    ]
  }
}

Pattern-to-Output Mapping

affected[] Entry Applied Pattern cpeMatch Objects in cpeAsGeneration
webapp v1.0 (exact) Section 3.3 Pattern A Single exact version: criteria="...webapp:1.0:...", appliedPattern="exact.single"
webapp v2.0-2.5 (range) Section 3.4 Pattern A Single range: versionStartIncluding="2.0", versionEndExcluding="2.5", appliedPattern="range.lessThan"
webapp v3.0 with change at 3.2.1 Section 3.4 Pattern D Single range: versionStartIncluding="3.0", versionEndExcluding="3.2.1", appliedPattern="range.changesFixed"
library (no versions) Section 3.1 Pattern A Single wildcard: criteria="...library:*:...", appliedPattern="noVersion.allAffected"
server v16.0.0 MR 7 (update pattern) Section 3.3 Pattern A + Section 4.1 Exact version with update component: criteria="...server:16.0.0:mr7:...", appliedPattern="exact.single"
platform git commit (versionType: git) Section 6.1 Metadata-only: versionsEntryIndex=0, concerns=["versionTypeGit"]
platform 10.0 SP 1-3 (update in range) Section 3.4 Pattern B + Section 6.2 Range with untransformed update patterns: versionStartIncluding="10.0 SP 1", concerns=["updatePatternsInRange"]

Key Integration Points

  1. One affected entry → One cveListV5AffectedEntries element: Each platform in CVE 5.0 affected[] produces one complete analysis entry
  2. cpeAsGeneration.generatedCpeMatch[]: Array of cpeMatch objects generated from Section 3 patterns
  3. appliedPattern field: Each cpeMatch includes pattern reference (e.g., “exact.single”, “range.changesFixed”, “inference.affectedFromWildcardExpansion”) for traceability
  4. versionsEntryIndex field: Maps to source versions[] array index (0-based, null if no versions array)
  5. concerns field (optional): Array of known limitation identifiers when automated translation cannot fully represent source data (see Section 6)
  6. Post-processing: CPE update field specificity enforcement (Section 4.2) applied before storing in generatedCpeMatch[]

6. Known Limitations

This section catalogs known failure conditions, edge cases, and limitations in CVE 5.x to CPE-AS translation logic. These represent areas where automated translation is not possible, produces incomplete results, or requires human review.

Documentation Requirements: All limitations MUST be documented in affected cpeMatch objects via the concerns[] array and logged to audit trail with specific CVE ID, affected entry index, and limitation details.

CPE-AS Concerns Array Enumerations

The concerns array in each cpeMatch object identifies conditions that may require human review or special handling. These concern identifiers enable programmatic filtering and analysis of potential data quality issues.

Concern Identifier Trigger Condition cpeMatch Type Notes
Status-Based Concerns      
statusUnaffected affected.[*].versions[*].status: "unaffected" Metadata-only Version explicitly marked as unaffected
statusUnknown affected.[*].versions[*].status: "unknown" Metadata-only Version status is unknown/unclear
defaultStatusUnknown affected.[*].defaultStatus: "unknown" Metadata-only Default status for entry is unknown
noAffectedPlatforms affected.[*] has no platforms or all unaffected Metadata-only Entry has no platform data
Version Type Concerns      
versionTypeGit affected.[*].versions[*].versionType: "git" Metadata-only Git commit hashes (not semantic versions)
CPE Mapping Concerns      
cpeUnconfirmedWithSuggestions No confirmed CPE mapping, but CPE suggestions exist Metadata-only Requires manual CPE confirmation
cpeUnconfirmedNoSuggestions No confirmed CPE mapping or suggestions Metadata-only Requires manual CPE research
Pattern Detection Concerns      
inferredAffectedFromWildcardExpansion affected.[*].versions[*].version contains "*" pattern Metadata-only or Full appliedPattern = "inference.affectedFromWildcardExpansion"
updatePatternsInRange affected.[*].versions[*].lessThan* contains update patterns Full cpeMatch Version boundaries contain update patterns (untransformed)
patternUnsupported No recognized pattern matched version entry structure Metadata-only appliedPattern omitted (null)

Implementation Guideline: All conditions are logged with specific CVE ID, affected entry index, and reason. Multiple concerns may be present in a single cpeMatch object’s concerns[] array.

Pattern Tracking: The appliedPattern field distinguishes between known patterns with values (like "inference.affectedFromWildcardExpansion") and truly unknown patterns where the field is omitted (null) with patternUnsupported concern.

6.1 Version Type Git

Issue: Certain version ordering schemes cannot be processed with general alphanumeric comparison.

General Approach: Every version entry is processed and generates a cpeMatch object. Incompatible version types generate metadata-only cpeMatch objects with concerns rather than being skipped entirely.

Processing Rules:

Failure Condition: "versionType": "git"

Required Behavior:

Audit Log Format:

"Detected 'versionType': 'git' | Cannot generate CPE criteria | Generated metadata-only cpeMatch | cve.containers.cna.affected.[X].versions[Y]"

Example Scenarios:

Scenario 1: Mixed versionTypes within single affected entry

Input:

{
  "vendor": "example",
  "product": "webapp",
  "versions": [
    {"version": "1.0.0", "status": "affected"},
    {"version": "abc123def", "versionType": "git", "status": "affected"},
    {"version": "2.0.0", "status": "affected"}
  ]
}

Output: 3 cpeMatch objects generated

[
  {
    "versionsEntryIndex": 0,
    "appliedPattern": "exact.single",
    "vulnerable": true,
    "criteria": "cpe:2.3:a:example:webapp:1.0.0:*:*:*:*:*:*:*"
  },
  {
    "versionsEntryIndex": 1,
    "concerns": ["versionTypeGit"]
  },
  {
    "versionsEntryIndex": 2,
    "appliedPattern": "exact.single",
    "vulnerable": true,
    "criteria": "cpe:2.3:a:example:webapp:2.0.0:*:*:*:*:*:*:*"
  }
]

Scenario 2: Only git versionType

Input:

{
  "vendor": "example",
  "product": "library",
  "versions": [
    {"version": "abc123def", "versionType": "git", "status": "affected"}
  ]
}

Output: 1 metadata-only cpeMatch object

[
  {
    "versionsEntryIndex": 0,
    "concerns": ["versionTypeGit"]
  }
]

6.2 Update Patterns in Range Boundaries

Issue: CPE 2.3 specification lacks mechanism to express update/patch components in range boundary values.

Failure Condition: Range boundaries (lessThan, lessThanOrEqual) contain update pattern indicators (e.g., "10.0 SP 1", "7.0 Update 3")

Required Behavior:

Example:

Input:

{
  "version": "10.0 SP 1",
  "status": "affected",
  "lessThanOrEqual": "10.0 SP 3"
}

Required Output:

{
  "versionsEntryIndex": 0,
  "appliedPattern": "range.lessThanOrEqual",
  "vulnerable": true,
  "criteria": "cpe:2.3:a:vendor:product:*:*:*:*:*:*:*:*",
  "versionStartIncluding": "10.0 SP 1",
  "versionEndIncluding": "10.0 SP 3",
  "concerns": ["updatePatternsInRange"]
}

Audit Log Format:

"Detected update pattern in range boundary for cve.containers.cna.affected.[0].versions[1] | CPE-AS will use untransformed values for boundaries | 

Rationale:

Impact:


6.3 Wildcard Expansion in Ranges

Issue: Wildcard patterns in range boundaries (e.g., "lessThanOrEqual": "2.4.*") require expansion logic that may not align with vendor versioning schemes.

Failure Condition: Range boundary contains wildcard character (*) in version string

Current Behavior:


6.4 Complex Version Semantics

Issue: Version strings with non-standard formatting may not parse correctly or compare as expected.

Examples:

Current Behavior: General alphanumeric comparison without semantic awareness

Limitations:

Impact: Incorrect version ordering, potential gaps or overlaps in ranges

Mitigation: Leverage versionType field when available, manual review for non-standard schemes