[v2] MRTR wipe-cache example reads unvalidated elicitation content and defaults malformed scope to all
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 78/100
- Loại issue
- Tài liệu
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- documentation, security
Hướng nghiên cứu
Mở docs/servers/input-required.md và tìm ví dụ xóa bộ nhớ đệm “Carry state across rounds with requestState”. Đọc cách sử dụng acceptedContent() có nhận biết schema ở phần trước của trang, sau đó cập nhật cả phần xử lý xác nhận và phạm vi để xác thực nội dung của client tại thời điểm chạy. Hoàn tất khi các yêu cầu có phạm vi không hợp lệ hoặc bị thiếu yêu cầu nhập lại thay vì mặc định sử dụng “all”.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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
- Ngôn ngữ chính
- TypeScript
- Star
- 13.6k
- Fork
- 2.3k
- Merge trung bình
- 1 ngày 2 giờ
- Pull request đã merge (30 ngày)
- 51
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của modelcontextprotocol/typescript-sdk
-
Stateless 405 response omits the Allow headerCó thể đã có người làm @Hugo-DDT đã nhận 5 ngày trước. Đang mởv2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
modelcontextprotocol/typescript-sdk#2970 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[v2] @modelcontextprotocol/server inlines fast-uri 3.1.0, which has 9 published advisoriesCó thể đã có người làm @Andiii208 đã nhận 8 ngày trước. Đang mởv2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
modelcontextprotocol/typescript-sdk#2966 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
v1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
modelcontextprotocol/typescript-sdk#2946 · 4 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[v2] URI template reserved expansions encode existing %HH sequences againCó thể đã có người làm @takagibit18 đã nhận 14 ngày trước. Đang mởv1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
modelcontextprotocol/typescript-sdk#2920 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[v2] URI template strict expansions leave !'()* unencodedCó thể đã có người làm @takagibit18 đã nhận 14 ngày trước. Đang mởv1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
modelcontextprotocol/typescript-sdk#2919 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của modelcontextprotocol/typescript-sdk
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Chocobozzz/PeerTube#7832 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Pay to use?Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 66/100
darkreader/darkreader#16108 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Add: Dak Nong TV SDĐang mởcheck:passed streams:add
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug engine
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
frostney/GocciaScript#1746 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
agilepathway/label-checker#739 · 4 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày