osv-scanner-mcp 0.3.1 → 0.3.3
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 +24 -1
- package/dist/index.js +6 -3
- package/dist/osv/runner.js +28 -5
- package/dist/tools/scanJavaProject.js +17 -2
- package/dist/tools/suggestFix.js +5 -2
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Google製 [OSV-Scanner](https://github.com/google/osv-scanner) をラップす
|
|
|
25
25
|
- 手動インストール済みのバイナリ(PATH上または `OSV_SCANNER_PATH` 指定)があればそちらを優先します
|
|
26
26
|
- 自動ダウンロードを無効化する場合は `OSV_MCP_AUTO_DOWNLOAD=0`
|
|
27
27
|
- PATH上のバイナリを使わず常に検証済み自動ダウンロードを使う場合は `OSV_MCP_PREFER_DOWNLOAD=1`(運用環境向け)
|
|
28
|
-
-
|
|
28
|
+
- スキャン時と `explain_vulnerability` 実行時にネットワークアクセスが発生します。照会先はOSVデータベース(`api.osv.dev`)ですが、**`pom.xml` のスキャンでは推移的依存を解決するため deps.dev(`api.deps.dev`)にも接続します**。詳細と無効化の方法は[通信先とプライバシー](#通信先とプライバシー)を参照してください
|
|
29
29
|
|
|
30
30
|
## セットアップ
|
|
31
31
|
|
|
@@ -123,6 +123,7 @@ npm run build
|
|
|
123
123
|
| `OSV_MCP_MAX_CONCURRENT_SCANS` | 同時実行できるスキャン数の上限(デフォルト `2`、最大 `16`)。超過したリクエストは待たずに即時エラーになります |
|
|
124
124
|
| `OSV_MCP_AUTO_DOWNLOAD` | `0` または `false` でバイナリの自動ダウンロードを無効化(デフォルト有効) |
|
|
125
125
|
| `OSV_MCP_PREFER_DOWNLOAD` | `1` または `true` 指定時、PATH上のosv-scannerを使わず、チェックサム検証済みの自動ダウンロードバイナリを常に使用します(PATH汚染による偽バイナリ実行の防止。`OSV_SCANNER_PATH` の明示指定は引き続き最優先) |
|
|
126
|
+
| `OSV_MCP_NO_REMOTE_RESOLUTION` | `1` または `true` 指定時、`pom.xml` の推移的依存を deps.dev で解決しません。**止まるのは deps.dev への送信だけで、脆弱性照会のためパッケージの名前とバージョンは引き続き `api.osv.dev` に送られます**。推移的依存の脆弱性は検出できなくなり、その旨が応答の `dependency_resolution.warning` に示されます。詳細は[通信先とプライバシー](#通信先とプライバシー) |
|
|
126
127
|
|
|
127
128
|
> **推奨**: `OSV_MCP_ALLOWED_ROOT` は未設定でも動作しますが、その場合は任意の絶対パスをスキャンできてしまいます。悪意ある指示(プロンプトインジェクション)経由で意図しないディレクトリをスキャンさせられる経路を塞ぐため、プロジェクト置き場のルート(例: `~/projects`)を設定しておくことを推奨します。各クライアントの設定で `"env": {"OSV_MCP_ALLOWED_ROOT": "/Users/you/projects"}` のように渡せます(Codex CLIのTOMLでは `[mcp_servers.osv-scanner.env]` セクション)。
|
|
128
129
|
|
|
@@ -130,6 +131,25 @@ npm run build
|
|
|
130
131
|
> - `OSV_MCP_ALLOWED_ROOT=/スキャン対象のルート` — スキャン範囲の境界を固定
|
|
131
132
|
> - `OSV_MCP_REQUIRE_ALLOWED_ROOT=1` — 境界未設定なら起動を拒否(fail-closed)
|
|
132
133
|
> - `OSV_SCANNER_PATH=/管理者所有の絶対パス` または `OSV_MCP_PREFER_DOWNLOAD=1` — PATH解決に依存せず、実行するバイナリを固定
|
|
134
|
+
>
|
|
135
|
+
> 依存の情報をどこに送るかは[通信先とプライバシー](#通信先とプライバシー)を確認してください。どの設定でも、脆弱性照会のためパッケージの名前とバージョンは `api.osv.dev` に送られます。
|
|
136
|
+
|
|
137
|
+
### 通信先とプライバシー
|
|
138
|
+
|
|
139
|
+
osv-scanner v2.4.0 で接続先を実機確認した結果です(2026-10-07)。
|
|
140
|
+
|
|
141
|
+
| 操作 | 接続先 | 送られる情報 |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| `pom.xml` のスキャン(`scan_java_project` / `suggest_fix`) | `api.osv.dev`、**`api.deps.dev`** | パッケージの名前とバージョン。deps.dev には推移的依存の解決のため、`pom.xml` に宣言された依存(社内パッケージを含む)の名前とバージョンが送られます |
|
|
144
|
+
| `gradle.lockfile` のスキャン | `api.osv.dev` | パッケージの名前とバージョン(lockfileに全依存が記載済みのため、解決のための外部接続はしません) |
|
|
145
|
+
| `scan_java_artifact` / `scan_sbom` | `api.osv.dev` | 同定できたパッケージの名前とバージョン |
|
|
146
|
+
| `explain_vulnerability` | `api.osv.dev` | 指定した脆弱性ID |
|
|
147
|
+
| バイナリの自動ダウンロード(初回のみ) | GitHub(公式Releases) | なし(ピン留めしたバージョンのバイナリを取得) |
|
|
148
|
+
|
|
149
|
+
api.osv.dev と deps.dev はどちらも Google が運営するサービスです。**どの設定でも、スキャンしたパッケージの名前とバージョンは脆弱性照会のため `api.osv.dev` に送られます**(オフラインでの照会には対応していません)。
|
|
150
|
+
|
|
151
|
+
- **deps.dev への送信を止めたい場合**: `OSV_MCP_NO_REMOTE_RESOLUTION=1` を設定すると、`pom.xml` の推移的依存を解決しなくなり、接続先は `api.osv.dev` だけになります。止まるのは deps.dev への送信だけで、OSV への送信は続きます。また `pom.xml` に直接書いた依存しかスキャンされず、**推移的依存の脆弱性を見落とします**。この状態は `scan_java_project` / `suggest_fix` の応答の `dependency_resolution` に `transitive_resolution: "disabled"` と警告で示されるので、検出0件と区別できます。推移的依存も含めて deps.dev を使わずにスキャンするには、Gradleのlockfile方式(`gradle.lockfile`)を使ってください
|
|
152
|
+
- **任意の取得先には接続しません**: osv-scanner の `--data-source native` モードは、スキャン対象の `pom.xml` の `<repositories>` に書かれた任意のURLへ接続します(悪意あるpom.xmlで攻撃者のサーバーへ通信させられる)。本サーバーはこのモードを使わず、`deps.dev` を明示指定しています
|
|
133
153
|
|
|
134
154
|
## 提供ツール
|
|
135
155
|
|
|
@@ -151,6 +171,7 @@ Java(Maven)プロジェクトをスキャンし、既知の脆弱性レポート
|
|
|
151
171
|
{
|
|
152
172
|
"project_dir": "/path/to/project",
|
|
153
173
|
"manifests": ["pom.xml"],
|
|
174
|
+
"dependency_resolution": { "transitive_resolution": "enabled" },
|
|
154
175
|
"source_files": ["/path/to/project/pom.xml"],
|
|
155
176
|
"vulnerable_package_count": 4,
|
|
156
177
|
"vulnerability_count": 14,
|
|
@@ -249,6 +270,7 @@ OSV-Scanner 2.4.0の `java/archive` プラグインを使用し、ネストJAR
|
|
|
249
270
|
{
|
|
250
271
|
"project_dir": "/path/to/project",
|
|
251
272
|
"manifests": ["pom.xml"],
|
|
273
|
+
"dependency_resolution": { "transitive_resolution": "enabled" },
|
|
252
274
|
"vulnerable_package_count": 4,
|
|
253
275
|
"unfixed_vulnerability_count": 1,
|
|
254
276
|
"suggestions": [
|
|
@@ -329,6 +351,7 @@ OSV-Scanner 2.4.0の `java/archive` プラグインを使用し、ネストJAR
|
|
|
329
351
|
- **パストラバーサル対策**: 入力パスは `realpath` でシンボリックリンク解決後に境界チェック。pom.xml探索ではシンボリックリンクを辿りません
|
|
330
352
|
- **DoS対策**: タイムアウト・stdout上限・stderr抜粋上限を設定。スキャン結果は防御的にパースし、形式不正でも例外を投げません。同時実行スキャン数も上限(デフォルト2)を設け、並列リクエストによるプロセスの無制限起動を防ぎます
|
|
331
353
|
- **fail-closedな運用モード**: `OSV_MCP_REQUIRE_ALLOWED_ROOT=1` で、スキャン許可ルート未設定時にサーバーの起動自体を拒否できます
|
|
354
|
+
- **通信先の固定と明示**: osv-scannerの依存解決先は `deps.dev` を明示指定し、スキャン対象のpom.xmlが指定する任意のリポジトリへ接続するモード(`--data-source native`)は使いません(テストで保証)。通信先の一覧と、deps.devへの送信を止める `OSV_MCP_NO_REMOTE_RESOLUTION=1` は[通信先とプライバシー](#通信先とプライバシー)を参照
|
|
332
355
|
- **情報漏えい対策**: 想定外の例外はスタックトレース等を含めず `internal_error` に丸めます。外部由来のテキスト(脆弱性summary等)は長さ上限付きの「データ」として構造化して返します
|
|
333
356
|
- **プロンプトインジェクション対策**: OSVデータベース由来のテキスト(summary / details / ID等)とOSV-Scannerのstderrは、LLMクライアントへ返す前にサニタイズします。制御文字(ANSIエスケープ含む)・ゼロ幅文字・双方向制御文字(RLO等)・Unicodeタグ文字(不可視のテキスト密輸)・行区切り(U+2028/2029)を除去し、NFC正規化を適用。外部データの読み取りアクセサを単一のサニタイズ境界にすることで適用漏れを防いでいます
|
|
334
357
|
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* - OSV_MCP_MAX_CONCURRENT_SCANS: 同時実行スキャン数の上限(デフォルト2)
|
|
10
10
|
* - OSV_MCP_AUTO_DOWNLOAD: 0/false指定時、バイナリの自動ダウンロードを無効化
|
|
11
11
|
* - OSV_MCP_PREFER_DOWNLOAD: 1/true指定時、PATH上のバイナリを使わず検証済み自動ダウンロードを優先
|
|
12
|
+
* - OSV_MCP_NO_REMOTE_RESOLUTION: 1/true指定時、pom.xmlの推移的依存をdeps.devで解決しない
|
|
12
13
|
*/
|
|
13
14
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
15
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -34,13 +35,14 @@ if (startupWarning !== null) {
|
|
|
34
35
|
// NOTE: リリース時はpackage.jsonのversionと同じ値に更新すること
|
|
35
36
|
const server = new McpServer({
|
|
36
37
|
name: "osv-scanner-mcp",
|
|
37
|
-
version: "0.3.
|
|
38
|
+
version: "0.3.3",
|
|
38
39
|
});
|
|
39
40
|
server.registerTool("scan_java_project", {
|
|
40
41
|
title: "Javaプロジェクトの脆弱性スキャン",
|
|
41
42
|
description: "Java(Maven)プロジェクトをGoogle OSV-Scannerでスキャンし、依存ライブラリの既知の脆弱性(CVE/GHSA)を深刻度順のJSONレポートで返す。" +
|
|
42
43
|
"レポートにはパッケージごとの脆弱性一覧(CVSSスコア・5段階深刻度・修正版バージョン)とサマリ集計が含まれる。" +
|
|
43
|
-
"Maven(pom.xml)とGradle(gradle.lockfile)に対応。"
|
|
44
|
+
"Maven(pom.xml)とGradle(gradle.lockfile)に対応。" +
|
|
45
|
+
"dependency_resolution.warningがある場合は推移的依存がスキャン対象外のため、検出0件でも安全とは判断しないこと。",
|
|
44
46
|
inputSchema: {
|
|
45
47
|
project_path: z
|
|
46
48
|
.string()
|
|
@@ -55,7 +57,8 @@ server.registerTool("suggest_fix", {
|
|
|
55
57
|
"(same_minor: 同一major.minor系統内 → major_internal: 同一メジャー内 → cross_major: メジャーアップグレード)で選定し、" +
|
|
56
58
|
"推奨バージョン・アップグレード距離(upgrade_tier)・CVEごとの修正版を返す。" +
|
|
57
59
|
"候補を全修正対象CVEの影響範囲と照合し、情報不足の場合は推奨を保留する。" +
|
|
58
|
-
"現在より新しい修正版候補のないCVEはunfixedとして別表示し、推奨先での判定も返す。Maven(pom.xml)とGradle(gradle.lockfile)に対応。"
|
|
60
|
+
"現在より新しい修正版候補のないCVEはunfixedとして別表示し、推奨先での判定も返す。Maven(pom.xml)とGradle(gradle.lockfile)に対応。" +
|
|
61
|
+
"dependency_resolution.warningがある場合は推移的依存の脆弱性が提案に含まれない。",
|
|
59
62
|
inputSchema: {
|
|
60
63
|
project_path: z
|
|
61
64
|
.string()
|
package/dist/osv/runner.js
CHANGED
|
@@ -37,8 +37,24 @@ function maxConcurrentScansFromEnv() {
|
|
|
37
37
|
const DEFAULT_MAX_OUTPUT_BYTES = 32 * 1024 * 1024;
|
|
38
38
|
/** エラー詳細に含めるstderrの上限(外部由来テキストをそのまま膨らませない) */
|
|
39
39
|
const MAX_STDERR_DETAIL_BYTES = 8 * 1024;
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const NO_REMOTE_RESOLUTION_ENV = "OSV_MCP_NO_REMOTE_RESOLUTION";
|
|
41
|
+
function noRemoteResolutionFromEnv() {
|
|
42
|
+
const value = process.env[NO_REMOTE_RESOLUTION_ENV]?.trim().toLowerCase();
|
|
43
|
+
return value === "1" || value === "true" || value === "yes";
|
|
44
|
+
}
|
|
45
|
+
/** 外部解決を無効にするか。スキャン引数と応答の表示が食い違わないよう、呼び出し側で一度だけ決める */
|
|
46
|
+
export function isRemoteResolutionDisabled(options = {}) {
|
|
47
|
+
return options.noRemoteResolution ?? noRemoteResolutionFromEnv();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* OSV-Scannerに渡す固定引数。ここに無いオプションは一切使わない(ホワイトリスト)
|
|
51
|
+
*
|
|
52
|
+
* pom.xml/requirements.txtの推移的依存はapi.deps.devで解決される(2.4.0で実機確認)。
|
|
53
|
+
* `--data-source native` はスキャン対象pom.xmlの<repositories>に書かれた任意のURLへ
|
|
54
|
+
* 接続するため使わない。既定値の変更に備えてdeps.devを明示する。
|
|
55
|
+
*/
|
|
56
|
+
const FIXED_SCAN_ARGS = ["scan", "source", "-r", "--format", "json", "--data-source", "deps.dev"];
|
|
57
|
+
const NO_RESOLVE_ARG = "--no-resolve";
|
|
42
58
|
const FIXED_ARTIFACT_ARGS = [
|
|
43
59
|
"scan", "source", "--format", "json", "--all-packages", "--no-ignore",
|
|
44
60
|
"--experimental-no-default-plugins", "--experimental-plugins", "java/archive",
|
|
@@ -48,13 +64,20 @@ const FIXED_SBOM_ARGS = [
|
|
|
48
64
|
"--experimental-no-default-plugins", "--experimental-plugins", "sbom",
|
|
49
65
|
];
|
|
50
66
|
const SCAN_ARGS = { project: FIXED_SCAN_ARGS, artifact: FIXED_ARTIFACT_ARGS, sbom: FIXED_SBOM_ARGS };
|
|
67
|
+
/** 外部解決を行うのはマニフェストを読むprojectモードだけ(artifact/sbomはOSV照会のみ) */
|
|
68
|
+
export function buildOsvScanArgs(mode, noRemoteResolution) {
|
|
69
|
+
const args = [...SCAN_ARGS[mode]];
|
|
70
|
+
if (mode === "project" && noRemoteResolution)
|
|
71
|
+
args.push(NO_RESOLVE_ARG);
|
|
72
|
+
return args;
|
|
73
|
+
}
|
|
51
74
|
const EXIT_NO_VULNS = 0;
|
|
52
75
|
const EXIT_VULNS_FOUND = 1;
|
|
53
76
|
const EXIT_NO_PACKAGES = 128;
|
|
54
|
-
function execOsvScanner(binaryPath, targetPaths, timeoutMs, maxOutputBytes,
|
|
77
|
+
function execOsvScanner(binaryPath, targetPaths, timeoutMs, maxOutputBytes, scanArgs) {
|
|
55
78
|
return new Promise((resolve, reject) => {
|
|
56
79
|
const child = spawn(binaryPath, [
|
|
57
|
-
...
|
|
80
|
+
...scanArgs, ...targetPaths,
|
|
58
81
|
], {
|
|
59
82
|
shell: false,
|
|
60
83
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -141,7 +164,7 @@ async function runScan(targetPaths, options, mode) {
|
|
|
141
164
|
}
|
|
142
165
|
async function runOsvScanUnguarded(targetPaths, options, mode) {
|
|
143
166
|
const binaryPath = options.binaryPath ?? (await resolveOsvScannerBinary());
|
|
144
|
-
const result = await execOsvScanner(binaryPath, targetPaths, options.timeoutMs ?? DEFAULT_TIMEOUT_MS, options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES, mode);
|
|
167
|
+
const result = await execOsvScanner(binaryPath, targetPaths, options.timeoutMs ?? DEFAULT_TIMEOUT_MS, options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES, buildOsvScanArgs(mode, isRemoteResolutionDisabled(options)));
|
|
145
168
|
if (result.exitCode === EXIT_NO_PACKAGES && mode === "project") {
|
|
146
169
|
throw new ScanToolError("no_packages_found", `OSV-Scannerがスキャン対象のパッケージを検出できませんでした: ${targetPaths[0]}(pom.xmlに依存関係が定義されているか確認してください)`, result.stderr);
|
|
147
170
|
}
|
|
@@ -2,18 +2,33 @@
|
|
|
2
2
|
* `scan_java_project`ツールのハンドラ。
|
|
3
3
|
* レスポンス形式(成功/エラー)は`toolResult.ts`参照。
|
|
4
4
|
*/
|
|
5
|
-
import { runOsvScan } from "../osv/runner.js";
|
|
5
|
+
import { isRemoteResolutionDisabled, runOsvScan } from "../osv/runner.js";
|
|
6
6
|
import { detectJavaProject } from "../utils/projectDetector.js";
|
|
7
7
|
import { errorResult, jsonResult } from "./toolResult.js";
|
|
8
|
+
const TRANSITIVE_OMITTED_WARNING = "OSV_MCP_NO_REMOTE_RESOLUTIONの設定により、マニフェスト(pom.xml)からの推移的依存の解決を省略しています。" +
|
|
9
|
+
"lockfile(gradle.lockfile)に記録された依存は対象ですが、pom.xmlに直接記載された依存の先にある推移的依存の脆弱性は含まれません。" +
|
|
10
|
+
"検出0件でも推移的依存の安全性は確認できていません";
|
|
11
|
+
/**
|
|
12
|
+
* 推移的依存の解決状態。無効時に「検出0件」を安全と誤読されないよう応答の先頭付近に置く。
|
|
13
|
+
* マニフェスト一覧の探索深さはosv-scannerの`-r`と一致しないため、一覧からpom.xmlの有無を
|
|
14
|
+
* 判定せず、無効時は条件付きの警告を常に返す。
|
|
15
|
+
*/
|
|
16
|
+
export function dependencyResolution(noRemoteResolution) {
|
|
17
|
+
return noRemoteResolution
|
|
18
|
+
? { transitive_resolution: "disabled", warning: TRANSITIVE_OMITTED_WARNING }
|
|
19
|
+
: { transitive_resolution: "enabled" };
|
|
20
|
+
}
|
|
8
21
|
export async function handleScanJavaProject(args, options = {}) {
|
|
9
22
|
try {
|
|
10
23
|
const project = await detectJavaProject(args.project_path, {
|
|
11
24
|
allowedRoot: options.allowedRoot,
|
|
12
25
|
});
|
|
13
|
-
const
|
|
26
|
+
const noRemoteResolution = isRemoteResolutionDisabled(options);
|
|
27
|
+
const report = await runOsvScan(project.projectDir, { ...options, noRemoteResolution });
|
|
14
28
|
return jsonResult({
|
|
15
29
|
project_dir: project.projectDir,
|
|
16
30
|
manifests: project.manifests,
|
|
31
|
+
dependency_resolution: dependencyResolution(noRemoteResolution),
|
|
17
32
|
...report,
|
|
18
33
|
});
|
|
19
34
|
}
|
package/dist/tools/suggestFix.js
CHANGED
|
@@ -3,21 +3,24 @@
|
|
|
3
3
|
* scan_java_projectと同じスキャンを実行し、脆弱なパッケージごとの
|
|
4
4
|
* 推奨アップグレードバージョン(3段階Tier)を返す。
|
|
5
5
|
*/
|
|
6
|
-
import { runOsvScan } from "../osv/runner.js";
|
|
6
|
+
import { isRemoteResolutionDisabled, runOsvScan } from "../osv/runner.js";
|
|
7
7
|
import { suggestUpgrades } from "../osv/suggestFix.js";
|
|
8
8
|
import { detectJavaProject } from "../utils/projectDetector.js";
|
|
9
|
+
import { dependencyResolution, } from "./scanJavaProject.js";
|
|
9
10
|
import { errorResult, jsonResult } from "./toolResult.js";
|
|
10
11
|
export async function handleSuggestFix(args, options = {}) {
|
|
11
12
|
try {
|
|
12
13
|
const project = await detectJavaProject(args.project_path, {
|
|
13
14
|
allowedRoot: options.allowedRoot,
|
|
14
15
|
});
|
|
15
|
-
const
|
|
16
|
+
const noRemoteResolution = isRemoteResolutionDisabled(options);
|
|
17
|
+
const report = await runOsvScan(project.projectDir, { ...options, noRemoteResolution });
|
|
16
18
|
const suggestions = suggestUpgrades(report.packages);
|
|
17
19
|
const unfixedVulnerabilities = suggestions.reduce((sum, s) => sum + s.per_cve_detail.filter((d) => d.tier === "unfixed").length, 0);
|
|
18
20
|
return jsonResult({
|
|
19
21
|
project_dir: project.projectDir,
|
|
20
22
|
manifests: project.manifests,
|
|
23
|
+
dependency_resolution: dependencyResolution(noRemoteResolution),
|
|
21
24
|
vulnerable_package_count: suggestions.length,
|
|
22
25
|
unfixed_vulnerability_count: unfixedVulnerabilities,
|
|
23
26
|
suggestions,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "osv-scanner-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
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",
|
|
@@ -50,8 +50,5 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
52
52
|
"zod": "^4.4.3"
|
|
53
|
-
},
|
|
54
|
-
"overrides": {
|
|
55
|
-
"@hono/node-server": "^2.0.11"
|
|
56
53
|
}
|
|
57
54
|
}
|