Repository navigation
Description
Summary
_severity_from_vuln() in src/skillspector/nodes/analyzers/osv_client.py reads
database_specific.severity straight from OSV.dev's response for GHSA advisories. GHSA's own
severity scale is LOW / MODERATE / HIGH / CRITICAL — GitHub's own term is "moderate", not
"medium". This is confirmed live against api.osv.dev right now, for example querying lodash
4.17.15 returns several advisories whose database_specific.severity is the literal string
"MODERATE" (e.g. GHSA-29mw-wpgm-hmr9, a prototype-pollution advisory):
$ curl -s -X POST https://api.osv.dev/v1/query \
-d '{"package":{"name":"lodash","ecosystem":"npm"},"version":"4.17.15"}' \
| python3 -c "import json,sys; [print(v['id'], v['database_specific']['severity']) for v in json.load(sys.stdin)['vulns']]"
GHSA-29mw-wpgm-hmr9 MODERATE
GHSA-35jh-r3h4-6jhm HIGH
GHSA-f23m-r3pf-42rh MODERATE
GHSA-p6mc-m468-83gw HIGH
GHSA-r5fr-rjxr-66jc HIGH
GHSA-xxjr-mmjv-4gpg MODERATE
_sc4_from_osv_detailed() in static_patterns_supply_chain.py takes that string and looks it up
in three tables — _SEVERITY_ORDER, _osv_severity_to_app(), _SEVERITY_CONFIDENCE — that only
recognize LOW / MEDIUM / HIGH / CRITICAL. "MODERATE" matches none of them, so
_osv_severity_to_app() falls through its final return Severity.LOW, and
_SEVERITY_ORDER.get("MODERATE", 0) returns the same rank as an actual LOW advisory, so a
MODERATE-only vulnerability list never even updates worst_severity away from its "LOW"
initial value.
Expected Behavior
A package with only MODERATE-severity GHSA advisories should produce an SC4 finding at
Severity.MEDIUM (confidence 0.7, matching _SEVERITY_CONFIDENCE["MEDIUM"]).
Actual Behavior
It is reported at Severity.LOW (confidence 0.6) — indistinguishable from a package OSV has no
real concerns about.
Impact
Scan a skill whose dependency manifest pins a package version with only MODERATE-severity known
CVEs (a common real-world case — GHSA rates the large middle band of its own advisories this way,
not HIGH/CRITICAL). The SC4 finding is still produced, but its severity is silently
downgraded, which can push it below whatever severity threshold a downstream triage step,
CI gate, or human reviewer uses to decide what to act on — with no error or log line indicating the
downgrade happened.
Suggested Fix
Normalize "MODERATE" to "MEDIUM" once, where the raw external string is read in
_severity_from_vuln(), so every downstream table keeps working against the app's own
four-level vocabulary.
Activity
rng1995 commentedon Sep 21, 2026
A proposed fix is open in PR #588. It normalizes GHSA/OSV
MODERATEseverity to SkillSpector'sMEDIUMat the ingestion boundary, with regression coverage. The PR has not merged, so this issue remains open pending review and merge.rng1995 commentedon Sep 23, 2026
Resolution verification: PR #588 merged and automatically closed this issue. OSV/GHSA
MODERATEis normalized toMEDIUMbefore downstream severity selection. The normalization and batch-query regressions pass onmainat94f5cc8.This supersedes the earlier in-progress comment. The fix is merged on
mainbut not yet in the latest published release, v2.11.2.