osv-scanner-mcp 0.4.0 → 0.4.2

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.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Semantic Versioning 2.0.0のバージョン解釈と優先順位比較(semver.org 11節)。
3
+ *
4
+ * OSVのnpm・Goの範囲(SEMVER型、およびECOSYSTEM型)の順序はSemVerの優先順位に従う。
5
+ * 実データ(docs/DESIGN_TODO.md「suggest_fix npm/Go対応」)の要点:
6
+ * - Goの疑似バージョン(`0.0.0-20190101120000-abcdef123456`)はプレリリースとして正しく並ぶ
7
+ * - Goの`+incompatible`はビルドメタデータとして比較で無視する(`20.10.14+incompatible` = `20.10.14`)
8
+ * - `19.03.9`(数値部の先頭ゼロ)や`13.0`のような値はSemVerではないためnullを返す
9
+ */
10
+ const NUMERIC = "0|[1-9]\\d*";
11
+ const PRE_ID = "(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)";
12
+ const BUILD_ID = "[0-9A-Za-z-]+";
13
+ const SEMVER_RE = new RegExp(`^v?(${NUMERIC})\\.(${NUMERIC})\\.(${NUMERIC})` +
14
+ `(?:-(${PRE_ID}(?:\\.${PRE_ID})*))?` +
15
+ `(?:\\+${BUILD_ID}(?:\\.${BUILD_ID})*)?$`);
16
+ /**
17
+ * SemVer 2.0.0として厳密に解釈する。解釈できなければnull。
18
+ * 先頭の`v`は防御的に1文字だけ受け付ける(OSVとosv-scannerはGoの版を`v`なしで返す)。
19
+ */
20
+ export function parseSemver(version) {
21
+ const m = SEMVER_RE.exec(version);
22
+ if (!m)
23
+ return null;
24
+ const numbers = [m[1], m[2], m[3]].map(Number);
25
+ if (!numbers.every(Number.isSafeInteger))
26
+ return null;
27
+ return {
28
+ major: numbers[0],
29
+ minor: numbers[1],
30
+ patch: numbers[2],
31
+ prerelease: m[4] === undefined ? [] : m[4].split(".").map((id) => (/^\d+$/.test(id) ? BigInt(id) : id)),
32
+ };
33
+ }
34
+ function cmp(a, b) {
35
+ return a < b ? -1 : a > b ? 1 : 0;
36
+ }
37
+ /** 解釈済みの2つの版をSemVerの優先順位で比較する(ビルドメタデータは無視)。 */
38
+ export function compareParsedSemver(a, b) {
39
+ const core = cmp(a.major, b.major) || cmp(a.minor, b.minor) || cmp(a.patch, b.patch);
40
+ if (core !== 0)
41
+ return core;
42
+ // プレリリースを持つ版は、同じ版の正式リリースより小さい
43
+ if (a.prerelease.length === 0 || b.prerelease.length === 0) {
44
+ return a.prerelease.length === b.prerelease.length ? 0 : a.prerelease.length === 0 ? 1 : -1;
45
+ }
46
+ const length = Math.min(a.prerelease.length, b.prerelease.length);
47
+ for (let i = 0; i < length; i++) {
48
+ const x = a.prerelease[i];
49
+ const y = b.prerelease[i];
50
+ if (typeof x === typeof y) {
51
+ const result = cmp(x, y);
52
+ if (result !== 0)
53
+ return result;
54
+ }
55
+ else {
56
+ // 数値の識別子は英数字の識別子より小さい
57
+ return typeof x === "bigint" ? -1 : 1;
58
+ }
59
+ }
60
+ return cmp(a.prerelease.length, b.prerelease.length);
61
+ }
62
+ /**
63
+ * 2つの版をSemVerの優先順位で比較する。どちらかを解釈できなければnull。
64
+ */
65
+ export function compareSemver(a, b) {
66
+ const x = parseSemver(a);
67
+ const y = parseSemver(b);
68
+ return x === null || y === null ? null : compareParsedSemver(x, y);
69
+ }
@@ -14,14 +14,22 @@ function isTruthy(value) {
14
14
  const normalized = value.trim().toLowerCase();
15
15
  return normalized === "1" || normalized === "true" || normalized === "yes";
16
16
  }
17
+ /**
18
+ * 許可ルートの設定値。空文字・空白のみは未設定(undefined)として扱う。
19
+ * 起動時の検証とツールへの受け渡しで判定がずれないよう、必ずこの関数で読む
20
+ * (空文字をそのまま渡すと`path.resolve("")`=起動ディレクトリが許可ルートになっていた)。
21
+ */
22
+ export function allowedRootFromEnv(env = process.env) {
23
+ const allowedRoot = env[ALLOWED_ROOT_ENV];
24
+ return allowedRoot !== undefined && allowedRoot.trim() !== "" ? allowedRoot : undefined;
25
+ }
17
26
  /**
18
27
  * 起動を拒否すべき設定不備があればエラーメッセージを返す。問題なければnull。
19
28
  */
20
29
  export function allowedRootStartupError(env = process.env) {
21
30
  if (!isTruthy(env[REQUIRE_ALLOWED_ROOT_ENV]))
22
31
  return null;
23
- const allowedRoot = env[ALLOWED_ROOT_ENV];
24
- if (allowedRoot !== undefined && allowedRoot.trim() !== "")
32
+ if (allowedRootFromEnv(env) !== undefined)
25
33
  return null;
26
34
  return (`${REQUIRE_ALLOWED_ROOT_ENV}が有効ですが、${ALLOWED_ROOT_ENV}が未設定のため起動を中止します。` +
27
35
  `スキャンを許可するルートディレクトリを${ALLOWED_ROOT_ENV}に設定してください`);
@@ -31,8 +39,7 @@ export function allowedRootStartupError(env = process.env) {
31
39
  * (許可ルート未設定=任意の絶対パスをスキャン可能な状態の可視化)
32
40
  */
33
41
  export function allowedRootStartupWarning(env = process.env) {
34
- const allowedRoot = env[ALLOWED_ROOT_ENV];
35
- if (allowedRoot !== undefined && allowedRoot.trim() !== "")
42
+ if (allowedRootFromEnv(env) !== undefined)
36
43
  return null;
37
44
  return (`${ALLOWED_ROOT_ENV}が未設定のため、任意の絶対パスをスキャンできる状態です。` +
38
45
  `プロジェクト置き場のルートを${ALLOWED_ROOT_ENV}に設定することを推奨します` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osv-scanner-mcp",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "MCP server that wraps Google's OSV-Scanner to scan Java projects for known vulnerabilities",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",