[v2] MRTR wipe-cache example reads unvalidated elicitation content and defaults malformed scope to all
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 78/100
- issue の種類
- ドキュメント
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- typescript
調査の方向性
docs/servers/input-required.md を開き、「Carry state across rounds with requestState」というキャッシュ消去の例を見つけます。ページの前半にあるスキーマ対応の acceptedContent() の使用方法を読んだうえで、確認とスコープの両方の処理を更新し、クライアントのコンテンツを実行時に検証します。無効または欠落したスコープのリクエストが、デフォルトで「all」を使用するのではなく、再度入力を要求するようになれば完了です。
索引モデルが issue の本文から書いたものです。
説明
What happened?
The v2 input_required documentation correctly states that
ctx.mcpReq.inputResponses is client-provided and untrusted, and recommends
using the schema-aware overload of acceptedContent().
However, the sequential wipe-cache example uses the unchecked generic
overload for both confirmation and scope:
const confirmed = acceptedContent<{ confirm: boolean }>(
ctx.mcpReq.inputResponses,
'confirm'
);
It later treats that response as proof that the operator confirmed:
if (confirmed?.confirm !== true) {
return inputRequired({
inputRequests: {
confirm: inputRequired.elicit({
message: 'Really wipe the cache?',
requestedSchema: {
type: 'object',
properties: {
confirm: {
type: 'boolean'
}
},
required: ['confirm']
}
})
}
});
}
return inputRequired({
inputRequests: {
scope: inputRequired.elicit({
message: 'Which scope?',
requestedSchema: {
type: 'object',
properties: {
scope: {
type: 'string'
}
},
required: ['scope']
}
})
},
requestState: await stateCodec.mint({
step: 'confirmed'
})
});
The generic type parameter only affects TypeScript typing. It does not perform
runtime validation of the client-provided value.
For example, a malformed accepted response could contain:
{
"action": "accept",
"content": {
"confirm": "false"
}
}
The string "false" is truthy in JavaScript. Because the example only checks:
confirmed?.confirm !== true
this particular value does not equal the boolean true, so the current
!== true check fails closed.
However, the example still demonstrates reading untrusted client content using
a compile-time generic instead of the runtime-validating overload. A copied or
slightly modified version using a normal truthiness check such as:
if (!confirmed?.confirm) {
// request confirmation
}
would treat "false" as confirmation.
The same example later reads the requested scope with the unchecked overload:
const scope = acceptedContent<{ scope: string }>(
ctx.mcpReq.inputResponses,
'scope'
);
return {
content: [{
type: 'text',
text: `Wiped ${scope?.scope ?? 'all'}`
}]
};
If the scope response is missing, malformed, or of an unexpected type, the
example falls back to "all". That feels unsafe for a destructive example and
conflicts with the page's earlier guidance to validate inputResponses using
the schema-aware overload.
This is primarily a documentation and defensive API-usage issue, not a claim
that a malicious MCP client gains a capability it did not already possess.
What did you expect?
I expected the destructive wipe-cache example to follow the page's own
guidance and validate all client-provided elicitation content at runtime.
For example:
const confirmationSchema = z.object({
confirm: z.boolean()
});
const scopeSchema = z.object({
scope: z.string()
});
const confirmed = acceptedContent(
ctx.mcpReq.inputResponses,
'confirm',
confirmationSchema
);
if (confirmed?.confirm !== true) {
return inputRequired({
inputRequests: {
confirm: inputRequired.elicit({
message: 'Really wipe the cache?',
requestedSchema: confirmationSchema
})
}
});
}
const scope = acceptedContent(
ctx.mcpReq.inputResponses,
'scope',
scopeSchema
);
if (scope === undefined) {
return inputRequired({
inputRequests: {
scope: inputRequired.elicit({
message: 'Which scope?',
requestedSchema: scopeSchema
})
}
});
}
return {
content: [{
type: 'text',
text: `Wiped ${scope.scope}`
}]
};
The example should also fail closed when scope content is missing or invalid,
rather than defaulting to "all".
Code to reproduce
Documentation page:
`docs/servers/input-required.md`
Relevant section:
`Carry state across rounds with requestState`
Relevant example:
const confirmed = acceptedContent<{ confirm: boolean }>(
ctx.mcpReq.inputResponses,
'confirm'
);
const scope = acceptedContent<{ scope: string }>(
ctx.mcpReq.inputResponses,
'scope'
);
return {
content: [{
type: 'text',
text: `Wiped ${scope?.scope ?? 'all'}`
}]
};
Minimal demonstration that the generic type does not validate at runtime:
const clientContent: unknown = {
confirm: 'false'
};
const confirmed =
clientContent as {
confirm: boolean;
};
console.log(typeof confirmed.confirm);
// "string"
console.log(Boolean(confirmed.confirm));
// true
The cast changes the TypeScript type but does not transform or validate the
runtime value.
SDK version
main at commit 1e1392e3f91583884fe82a0b4b91335875c3fba6
Area
Documentation
- 主要言語
- TypeScript
- スター
- 13.5k
- フォーク
- 2.3k
- 平均マージ
- 1日 22時間
- マージ済み PR(30日)
- 52
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
modelcontextprotocol/typescript-sdk のほかの issue
-
Stateless 405 response omits the Allow header対応中かも @jstar0 が 1 日前に担当しました。 オープンv2
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
modelcontextprotocol/typescript-sdk#2970 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
[v2] @modelcontextprotocol/server inlines fast-uri 3.1.0, which has 9 published advisories対応中かも @Andiii208 が今日担当しました。 オープンv2
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
modelcontextprotocol/typescript-sdk#2966 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
v1 v2
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
modelcontextprotocol/typescript-sdk#2946 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
[v2] URI template reserved expansions encode existing %HH sequences again対応中かも @takagibit18 が 7 日前に担当しました。 オープンv1 v2
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
modelcontextprotocol/typescript-sdk#2920 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
[v2] URI template strict expansions leave !'()* unencoded対応中かも @takagibit18 が 7 日前に担当しました。 オープンv1 v2
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
modelcontextprotocol/typescript-sdk#2919 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
modelcontextprotocol/typescript-sdk の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
メンテナーはふだん 1 日以内に返信
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:other issue-rating: 🦞 diamond lobster no-stale P2
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
openclaw/openclaw#168089 · コメント 2 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
✨ enhancement needs-discussion
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
-
[Bug]: [MCP/CLI] Bare loopback IP addresses (127.0.0.1:port) and hosts with ports fail to navigate due to erroneous scheme inference対応中かも @alok-108 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
microsoft/playwright#43263 ·
メンテナーはふだん 1 日以内に返信
-
area:studio type:security
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信