T09 · Insecure Skill Coding Practices
- Location
plugin/src/store.ts:51- Finding
Approval parameter hashing collapses unrelated tool calls
- Content
View full analysis
): string { // Sort keys for consistent hashing const sortedKeys = Object.keys(params).sort(); const normalized = JSON.stringify({ toolName, params }, sortedKeys); return createHash("sha256").update(normalized).digest("hex").slice(0, 16); } ``` The resulting hash is trusted before security evaluation: ```ts const paramsHash = store.hashParams(toolName, params); const approval = store.consumeApproval(paramsHash); if (approval) { logger.info(`[GA] ${toolName}: approved via nonce ${approval.nonce}`); return; // Allow (approval consumed) } ``` ### Technical Analysis The second argument passed to `JSON.stringify` is an array replacer. It does not merely sort the top-level parameter keys: it acts as a property allowlist at every object level. The object being serialized has root properties named `toolName` and `params`, but those names are normally absent from `sortedKeys`, which is derived only from the keys inside `params`. As a result, the root properties are omitted and many calls normalize to the same value, commonly `{}`. Even where a root property survives, nested properties not present in the top-level allowlist can be omitted. The implementation therefore does not bind approval to the complete tool name and parameters as claimed. This becomes critical because `plugin/src/hook.ts` consumes approval before calling `evaluate()`. A hash collision causes the hook to return immediately, skipping both risk scoring and the intrinsic-evil hard-block checks. ### Attack Path 1. Cause a relatively benign tool call to be escalated. 2. Obtain the escalation nonce and approve that pending action. 3. Before the app ...[truncated 844 chars]- Remediation
View remediation
