T09 · Insecure Skill Coding Practices
- Location
scripts/scrub-codex-session-images.mjs:155- Finding
Mixed Image Arrays Cause Unintended Deletion of Non-Image Session Data
- Content
View full analysis
Vulnerability Details
File Location:
scripts/scrub-codex-session-images.mjs, lines 155–166
Vulnerability Type: Improper data preservation during image-array sanitization
Risk Level: MediumVulnerable Code
js if (Array.isArray(value)) { if (key === 'images' && value.some(looksLikeImageString)) { stats.imageArraysCleared += 1; for (const item of value) { const bytes = typeof item === 'string' ? byteLength(item) : countImageBytes(item); if (bytes > 0) { stats.imageStringsReplaced += 1; stats.approxBytesRemoved += Math.max(0, bytes - byteLength(PLACEHOLDER)); } } return []; } return value.map((item) => scrub(item, stats, options, '', value)); }Technical Analysis
When an array is stored under the
imageskey, the code checks whether at least one direct element matches a recognized image-string signature. If a single element matches, the function returns an empty array rather than sanitizing only the matching element.Consequently, mixed arrays containing both an embedded image and unrelated values—such as text, metadata, references, identifiers, or unsupported image objects—are cleared in their entirety. This behavior violates the documented safety rule in
SKILL.mdthat only image payloads should be removed.The issue is an integrity flaw rather than a privilege-escalation vulnerability. Exploitation requires a crafted or naturally occurring mixed
imagesarray in a selected session file and execution of the scrubber with--write.Attack Path
- A Codex session JSONL record contains an
imagesarray with at least one recognized image string and one or more non-image elements. - The user selects that session through
--fileor--thread-id. - A dry run may report image removal but does not identify the unrelated elements that will be discarded.
- The user reruns the tool with
--write. value.some(looksLikeImageString)evaluates to true.- The scrubb ...[truncated 704 chars]
- A Codex session JSONL record contains an
- Remediation
View remediation
Remediation Suggestions
Replace only confirmed image elements rather than clearing the entire array. Preserve non-image values and recursively sanitize nested objects. For example:
js if (Array.isArray(value)) { return value.map((item) => { if (key === 'images' && looksLikeImageString(item)) { stats.imageStringsReplaced += 1; stats.approxBytesRemoved += Math.max( 0, byteLength(item) - byteLength(PLACEHOLDER), ); return PLACEHOLDER; } return scrub(item, stats, options, '', value); }); }Additionally:
- Add tests covering mixed
imagesarrays containing image strings, text, metadata, null values, and nested objects. - Verify that dry-run statistics accurately distinguish replaced image elements from preserved elements.
- Add post-write validation comparing the semantic structure before and after sanitization.
- Document and test restoration from the generated backup.
- Consider reporting the JSON paths of all proposed replacements during dry runs so users can review the exact scope before writing.
- Add tests covering mixed
