T09 · Insecure Skill Coding Practices
- Location
src/index.ts:104- Finding
Agent-Controlled Identifier Enables Authenticated API Path Traversal
- Content
View full analysis
client.patch(`/contacts/${id as string}`, rest), ``` ```ts handler: async ({ id, ...rest }) => client.patch(`/contacts/${id as string}`, rest), ``` ```ts handler: async ({ id, ...rest }) => client.patch(`/opportunities/${id as string}`, rest), ``` The resulting endpoint is concatenated directly with the API base URL: ```ts async patch(endpoint: string, body: unknown): Promise { const res = await fetch(`${this.base}${endpoint}`, { method: 'PATCH', headers: this.headers, body: JSON.stringify(body), }); return this.parse(res); } ``` ### Technical Analysis The `id` parameters are described as UUIDs, but their tool schemas only enforce `type: 'string'`. No runtime UUID validation or path-component encoding is applied before an identifier is interpolated into a URL. Consequently, an identifier can contain URL-significant sequences such as `../`, `/`, `?`, or `#`. URL parsing performed by `fetch` can normalize dot segments and alter the intended route. For example, an identifier such as `../admin/settings` changes: ```text /api/v1/contacts/../admin/settings ``` into an effective path equivalent to: ```text /api/v1/admin/settings ``` The request retains the plugin's CRMy bearer credential. Exploitation therefore depends on whether another same-origin route accepts `PATCH` and whether the configured API key is authorized for that route, but the plugin does not constrain the request to the intended contact or opportunity resource. ### Attack Path 1. An attacker influences an agent prompt, retrieved CRM content, or another untrusted input used as a record identifier. 2. ...[truncated 882 chars]- Remediation
View remediation
{ const uuid = requireUuid(id); return client.patch(`/contacts/${encodeURIComponent(uuid)}`, rest); }; ``` 5. Consider changing the client API to accept validated resource names and identifiers separately rather than accepting arbitrary endpoint strings. 6. Add regression tests using values such as `../admin`, `%2e%2e%2fadmin`, `id/child`, `id?x=y`, and `id#fragment`, and verify that all are rejected before a network request is made. ]]>
