osv-scanner-mcp 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +4 -3
- package/dist/osv/candidateCheck.js +15 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -445,7 +445,7 @@ For npm, Go, and PyPI, the "same release line" is the range npm's caret (`^`) tr
|
|
|
445
445
|
- PyPI: update the version in `requirements.txt`, `pyproject.toml`, or `Pipfile` and regenerate the lockfile; for a transitive dependency, use a pip constraints file (`-c`) or the override settings of uv or Poetry
|
|
446
446
|
- When the relation is `unknown` or `mixed`, both cases are described (no hint is given for Maven packages from `gradle.lockfile`)
|
|
447
447
|
- **Checking recommended versions against OSV**: Recommendations are verified only against the vulnerabilities found in the scan (those affecting the current version), so a recommended version could be affected by newer vulnerabilities (for example, cryptography 3.2's candidate 49.0.0 is affected by two vulnerabilities introduced in 44.0.0 and fixed in 50.0.0). The server therefore queries `api.osv.dev` about the recommended version, and if it is affected, adds those vulnerabilities to the set to be fixed and chooses again with their fixed versions as candidates (50.0.0 in this example, with the reason in `upgrade_note`). The result is reported in `candidate_check`:
|
|
448
|
-
- `clean`: OSV reports no known vulnerabilities for the recommended version
|
|
448
|
+
- `clean`: OSV reports no additional known vulnerabilities for the recommended version beyond those already shown in the scan. Known `unfixed` vulnerabilities may still affect it; check `per_cve_detail[].recommended_status`
|
|
449
449
|
- `has_known_vulnerabilities`: no candidate avoids them, so the recommended version has known vulnerabilities (IDs in `recommended_known_vulnerabilities`)
|
|
450
450
|
- `conflict`: OSV reports that a candidate is affected by a vulnerability the scan had evaluated as not affecting it (the range data disagree), and no other candidate is available, so the recommendation is withheld (`recommended_upgrade: null`, `verification: "no_verified_candidate"`)
|
|
451
451
|
- `failed`: the query failed or returned a malformed response (the recommendation, verified against the scanned vulnerabilities, is still returned)
|
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ if (startupWarning !== null) {
|
|
|
61
61
|
// NOTE: リリース時はpackage.jsonのversionと同じ値に更新すること
|
|
62
62
|
const server = new McpServer({
|
|
63
63
|
name: "osv-scanner-mcp",
|
|
64
|
-
version: "0.12.
|
|
64
|
+
version: "0.12.1",
|
|
65
65
|
});
|
|
66
66
|
server.registerTool("scan_project", {
|
|
67
67
|
title: "Scan project dependencies for vulnerabilities (Java / JavaScript / Python / Go / Rust)",
|
|
@@ -103,8 +103,9 @@ server.registerTool("suggest_fix", {
|
|
|
103
103
|
"and the response gives the recommended version, the upgrade distance (upgrade_tier), and the fixed version per CVE. For npm, Go, and PyPI, a minor update within 0.x is also cross_major (may include breaking changes). " +
|
|
104
104
|
"Dependencies scanned at a requirements.txt lower bound (>=) are marked version_is_lower_bound, and the recommendation then means raising the lower bound. " +
|
|
105
105
|
"update_hint explains how to upgrade, depending on whether the package is a direct or transitive dependency (dependency_relation; for npm also introduced_by and declared_in). " +
|
|
106
|
-
"The recommended version is checked against api.osv.dev, and versions with known vulnerabilities that do not affect the current version are avoided (result in candidate_check
|
|
107
|
-
"
|
|
106
|
+
"The recommended version is checked against api.osv.dev, and versions with known vulnerabilities that do not affect the current version are avoided (result in candidate_check). " +
|
|
107
|
+
"clean means no additional known vulnerabilities beyond those shown in the scan; unfixed vulnerabilities may still affect the recommended version. " +
|
|
108
|
+
"With has_known_vulnerabilities, failed, or skipped, the recommended version has not been confirmed safe; conflict means the data disagreed and the recommendation is withheld. " +
|
|
108
109
|
"Candidates are checked against the affected ranges of every vulnerability to fix, and the recommendation is withheld when the data are insufficient. Pre-releases are recommended only when no stable version fixes everything, and are marked recommended_is_prerelease. " +
|
|
109
110
|
"CVEs with no fixed version newer than the current one are reported separately as unfixed, together with their status at the recommended version. " +
|
|
110
111
|
"Always check coverage in the response (if complete is false, some dependencies are not included in the suggestions). " +
|
|
@@ -43,6 +43,14 @@ class QueryBudget {
|
|
|
43
43
|
}
|
|
44
44
|
async function checkPackage(pkg, initial, budget, options) {
|
|
45
45
|
const known = new Set(pkg.vulnerabilities.flatMap((v) => [v.id, ...v.aliases]));
|
|
46
|
+
const unfixed = new Set(initial.per_cve_detail.filter((v) => v.tier === "unfixed").map((v) => v.id));
|
|
47
|
+
const ignoredKnown = new Set(pkg.vulnerabilities.filter((v) => unfixed.has(v.id)).flatMap((v) => [v.id, ...v.aliases]));
|
|
48
|
+
// 別名が修正対象とも重なる場合は、その対象の判定を優先する。
|
|
49
|
+
for (const vuln of pkg.vulnerabilities) {
|
|
50
|
+
if (!unfixed.has(vuln.id))
|
|
51
|
+
for (const id of [vuln.id, ...vuln.aliases])
|
|
52
|
+
ignoredKnown.delete(id);
|
|
53
|
+
}
|
|
46
54
|
const extraTargets = [];
|
|
47
55
|
const excluded = new Set();
|
|
48
56
|
const rejected = [];
|
|
@@ -62,9 +70,15 @@ async function checkPackage(pkg, initial, budget, options) {
|
|
|
62
70
|
return { suggestion, status: "failed", rejected };
|
|
63
71
|
throw error;
|
|
64
72
|
}
|
|
73
|
+
// 修正版なしの既知の脆弱性は修正対象ではなく、推奨先でもaffectedであることと矛盾しない。
|
|
74
|
+
// 新しく照会で見つかった対象はknownへ追加されるが、ignoredKnownには入れない。
|
|
75
|
+
records = records.filter((record) => {
|
|
76
|
+
const matched = recordIds(record).filter((id) => known.has(id));
|
|
77
|
+
return matched.length === 0 || matched.some((id) => !ignoredKnown.has(id));
|
|
78
|
+
});
|
|
65
79
|
if (records.length === 0)
|
|
66
80
|
return { suggestion, status: "clean", rejected };
|
|
67
|
-
//
|
|
81
|
+
// 新しい脆弱性は修正対象に加え、修正版を候補に加える。既知の修正対象の脆弱性に該当と返った場合は、
|
|
68
82
|
// 手元の範囲情報とOSVの判定が食い違っているため、その候補を除外する(安全側)
|
|
69
83
|
let conflict = false;
|
|
70
84
|
for (const record of records) {
|