T09 · Insecure Skill Coding Practices
- Location
src/index.ts:588- Finding
Unvalidated Identifiers Permit Authenticated API Path Manipulation
- Content
View full analysis
Vulnerability Details
File Location:
src/index.ts:588-594and equivalent identifier interpolation atsrc/index.ts:634-640,src/index.ts:656-693
Vulnerability Type: Improper validation and encoding of URL path segments
Risk Level: MediumVulnerable Code
typescript case "volkern_get_lead": return volkernRequest(`/leads/${args.leadId}`); case "volkern_create_lead": return volkernRequest("/leads", "POST", args); case "volkern_update_lead": { const { leadId, ...data } = args; return volkernRequest(`/leads/${leadId}`, "PATCH", data); }The same pattern is used for catalog items, services, tasks, interactions, and notes:
typescript case "volkern_get_catalogo_item": return volkernRequest(`/catalogo/${args.itemId}`); case "volkern_update_catalogo_item": { const { itemId, ...data } = args; return volkernRequest(`/catalogo/${itemId}`, "PATCH", data); } case "volkern_get_servicio": return volkernRequest(`/servicios/${args.servicioId}`); case "volkern_create_task": { const { leadId, ...taskData } = args; return volkernRequest(`/leads/${leadId}/tasks`, "POST", taskData); } case "volkern_list_tasks": return volkernRequest(`/leads/${args.leadId}/tasks`); case "volkern_complete_task": return volkernRequest(`/tasks/${args.taskId}`, "PATCH", { completada: true }); case "volkern_list_interactions": return volkernRequest(`/leads/${args.leadId}/interactions`); case "volkern_create_interaction": { const { leadId, ...interactionData } = args; return volkernRequest(`/leads/${leadId}/interactions`, "POST", interactionData); } case "volkern_list_notes": return volkernRequest(`/leads/${args.leadId}/notes`); case "volkern_create_note": { const { leadId: noteLeadId, ...noteData } = args; return volkernRequest(`/leads/${noteLeadId}/notes`, "POST", noteData); }The resulting request includes the configured bearer credent ...[truncated 3130 chars]
- Remediation
View remediation
Remediation Suggestions
- Validate every entity identifier before constructing an API path. Use the exact identifier grammar supported by Volkern rather than merely checking that the value is a string.
- Reject identifiers containing path separators, traversal sequences, query delimiters, fragment delimiters, control characters, or encoded variants of those values.
- Encode each validated path segment with
encodeURIComponentbefore interpolation. - Centralize path construction to prevent future handlers from bypassing validation.
typescript function encodeEntityId(value: unknown, fieldName: string): string { if (typeof value !== "string") { throw new Error(`${fieldName} must be a string`); } // Replace this expression with Volkern's exact documented CUID grammar. if (!/^c[a-z0-9]+$/i.test(value)) { throw new Error(`${fieldName} has an invalid format`); } return encodeURIComponent(value); } case "volkern_get_lead": { const leadId = encodeEntityId(args.leadId, "leadId"); return volkernRequest(`/leads/${leadId}`); }- Apply the same protection to
leadId,itemId,servicioId,taskId, and every future identifier used in a URL path. - Perform runtime argument validation in the request handler rather than relying only on MCP tool-schema declarations.
- Add negative tests covering
/,../,?,#,%2f,%2e%2e, backslashes, control characters, and mixed or double encoding. - Regenerate
dist/index.jsfrom the corrected TypeScript source and verify that the distributed code contains the same validation. - Continue enforcing server-side API authorization, tenant isolation, and per-object permission checks as a separate defense-in-depth boundary.
