T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/job-code.mjs:5
- Finding
- Purge confirmation code does not bind the complete deletion scope<![CDATA[ ## Vulnerability Details **File Location**: `scripts/job-code.mjs:5-25`, used by `scripts/purge-preview.mjs:49-58` and `scripts/purge-runner.mjs:137-153` **Vulnerability Type**: Incomplete authorization-scope binding **Risk Level**: High ### Vulnerable Code ```javascript export function buildConfirmCode({ channelId, authorId, contains, regex, after, before, includePinned, }) { const raw = [ normalizeValue(channelId), normalizeValue(authorId), normalizeValue(contains), normalizeValue(regex), normalizeValue(after), normalizeValue(before), normalizeValue(includePinned), ].join('|'); const hash = crypto.createHash('sha1').update(raw).digest('hex').slice(0, 8).toUpperCase(); return `PURGE-${hash}`; } ``` The runner accepts additional parameters that affect the deletion scope, but they are not included in the confirmation code: ```javascript const filters = normalizeFilters(args); const expectedCode = buildConfirmCode({ channelId, authorId: args['author-id'], contains: args.contains, regex: args.regex, after: args.after, before: args.before, includePinned: filters.includePinned, }); const providedCode = String(args.confirm ?? ''); if (!providedCode) throw new Error('Missing required argument --confirm'); if (providedCode !== expectedCode) { throw new Error(`Confirmation mismatch. Expected ${expectedCode}`); } ``` ### Technical Analysis The confirmation code binds the channel and several content filters, but it omits deletion-relevant parameters including: - `maxScan` - `maxMatches` - `regexFlags` Consequently, a code generated from a limited preview remains valid when the runner is invoked with a much larger scan or match limit. For example, a preview limited to 10 messages can produce the same code as a destructive run scanning 5,000 messages, provided the fields included in `buildConfirmCode` are unchanged. Changing `regexFlags` can also change regular-expression matching behavio ...[truncated 1534 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Bind every behavior- or scope-affecting field into a canonical confirmation manifest, including: - Channel ID - Author ID - Content and regular-expression filters - Regular-expression flags - Time boundaries - Pinned-message handling - Maximum scan count - Maximum match count - Deletion mode and other destructive options - Generate and persist a preview manifest containing the exact matched message IDs or a cryptographic digest of the ordered ID set. - Require the runner to load that manifest and delete only the reviewed message IDs. - Use a cryptographically random, single-use confirmation nonce rather than a deterministic truncated SHA-1 value. - Store the nonce with an expiration time, consumption status, and digest of the complete preview manifest. - Do not reveal a valid expected confirmation code in mismatch errors. - Reject execution if any command-line filter differs from the stored preview manifest. ]]>
