Skip to content

SC4 (OSV known vulnerable dependency) reports all historical CVEs when requirements.txt uses >= operator #42

Description

@woxinsj

User says they have the GitHub new-issue page open. They want to know what to write. Let me give them the issue body content in a format that's easy to copy into GitHub's "New Issue" form.

GitHub's new issue form has two main fields:

  1. Title (one line)
  2. Body (markdown)

Let me give them both, formatted for easy copy-paste. I'll structure it to be clear and concise — GitHub issues are usually a bit shorter than full bug reports, with the key info upfront.

复制下面两块到 GitHub New Issue 页:

Title(标题)

SC4 (OSV known vulnerable dependency) reports all historical CVEs when `requirements.txt` uses `>=` operator

Body(正文)

## Summary

When `requirements.txt` uses `>=` (e.g. `numpy>=1.26.0`), `SC4` ignores the bound and reports **all historical CVEs** for that package, not just the ones affecting the bound version. The bound can be raised above the CVE-fixed release and the scanner still reports every old CVE.

## Environment

- SkillSpector 2.1.3
- Scan command: `skillspector scan <path> --no-llm --format json`
- Target: `requirements.txt` (PEP 508 style)

## Repro

Create a `requirements.txt`:

numpy>=1.26.0
Pillow>=10.4.0
scikit-learn>=1.5.0
httpx>=0.27.0


All four bounds are above the fixed versions of the CVEs the scanner reports.

Run:

skillspector scan .


Observed: 4× CRITICAL findings, each listing 2–10 historical CVEs that the bound should exclude.

## Root cause

`src/skillspector/nodes/analyzers/static_patterns_supply_chain.py` lines 396–399:

​```python
m = re.match(r"^([a-zA-Z][a-zA-Z0-9._-]*)(?:\[.*?\])?\s*(?:([=<>!~]=?)\s*([\d.*]+))?", line)
if m:
    name = m.group(1)
    version = m.group(3) if m.group(2) in ("==", "<=") else None
    results.append((name, version, i))
​```

`version` is set to `None` for any operator other than `==` / `<=`. The `None` propagates to the OSV query, which then returns every advisory ever filed for the package, instead of the subset that applies to the bound.

## Expected

For `numpy>=1.26.0`, the scanner should either:
- Query OSV with `version=1.26.0` and return only CVEs affecting that version, or
- Use a proper PEP 508 parser (e.g. `packaging.requirements.Requirement`) to extract the lowest acceptable version and filter CVEs against the affected range.

## Suggested fix

1. Replace the ad-hoc regex with `packaging.requirements.Requirement(line).specifier`.
2. Pick the lowest valid version (e.g. `>=1.26.0` → `1.26.0`) and query OSV with that version.
3. Filter returned CVEs to those whose `affected` range intersects the specifier's accepted set.
4. (Optional) Add an inline-skip syntax (e.g. `# skillspector: ignore=SC4 reason=...`) so users can whitelist known false positives.

## Workaround

In our project we upgraded all `>=` bounds to versions clearly above the CVE-fixed releases and accepted the scanner noise as informational. The bound values are correct at install time; only the scanner output is wrong.

## References

- PEP 508: https://peps.python.org/pep-0508/
- OSV.dev batch API: https://google.github.io/osv.dev/post-v1-querybatch/
- `packaging` library: https://packaging.pypa.io/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions