[v2] MRTR wipe-cache example reads unvalidated elicitation content and defaults malformed scope to all
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 78/100
- Issue-Typ
- Dokumentation
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- typescript
- Bereich
- documentation, security
Rechercherichtung
Öffne docs/servers/input-required.md und suche das Beispiel zum Löschen des Caches („Carry state across rounds with requestState“). Lies die frühere Verwendung von acceptedContent() mit Schema-Unterstützung auf der Seite und aktualisiere dann sowohl die Behandlung der Bestätigung als auch des Gültigkeitsbereichs, um den Client-Inhalt zur Laufzeit zu validieren. Erledigt ist es, wenn Anfragen mit ungültigem oder fehlendem Gültigkeitsbereich erneut Eingaben anfordern, anstatt standardmäßig „all“ zu verwenden.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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
- Vorherrschende Sprache
- TypeScript
- Sterne
- 13.7k
- Forks
- 2.4k
- Ø Merge
- 2 T. 7 Std.
- Gemergte PRs (30 T.)
- 26
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus modelcontextprotocol/typescript-sdk
-
[v2] createMcpHandler legacy fallback misses an abort that happens before it subscribesEvtl. vergeben @mariano-aguero hat das vor 5 Tagen übernommen. Offenv2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
modelcontextprotocol/typescript-sdk#3136 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
[v2] requireBearerAuth: drop error="invalid_token" when no credentials were sent and resource_metadata is set (RFC 6750 §3.1)Evtl. vergeben @Anandumv hat das vor 4 Tagen übernommen. Offenv2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
modelcontextprotocol/typescript-sdk#3124 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
The `maxToolInputElements` refusal lacks the `Input validation error:` prefix that the schema refusal carriesEvtl. vergeben @barry166 hat das vor 8 Tagen übernommen. Offenv1 v2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
modelcontextprotocol/typescript-sdk#3111 · 3 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
server: registeredResource.update and registeredResourceTemplate.update desync title and metadata.title when updating metadata aloneEvtl. vergeben @SameRainbows hat das vor 3 Tagen übernommen. Offenv1 v2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
modelcontextprotocol/typescript-sdk#3103 · 6 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
[v1.x] Protocol.request keeps its abort listener after the request resolved, so a later abort sends notifications/cancelled for an answered request (1.30.0)Evtl. vergeben Ein verknüpfter Pull Request ist offen oder bereits gemergt. Offenv1
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
modelcontextprotocol/typescript-sdk#3090 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in modelcontextprotocol/typescript-sdk
Ähnliche Issues
-
[Text] Add Reading Time & Word Count Estimator for Reflection Notes in src/lib/text/reading-time.tsOffenarea:core beginner-friendly community contributions-welcome difficulty:easy enhancement good first issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
Maintainer antworten meist innerhalb von 1 Tag
-
[fullsend] E2E: scorecard — filecheck GitLab entity metrics unavailable due to initialDelay timingOffene2e-failure ready-to-code
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
redhat-developer/rhdh-plugin-export-overlays#4698 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
devswha/herdr-web-ui#2884 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
b:minor bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
software-mansion/argent#1771 ·
Maintainer antworten meist innerhalb von 1 Tag