Back to skill

Security audit

Codex Session Image Scrubber

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent cleanup purpose, but it can rewrite sensitive Codex session history and has a real bug that may delete non-image data from selected session records.

Only use this on a session you explicitly choose, review the dry-run output before using --write, and keep the backup. Be aware that arrays named images may be cleared entirely if they contain an image string, so this version can remove some non-image data from the selected session file.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
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: Medium

Vulnerable 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 images key, 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.md that 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 images array in a selected session file and execution of the scrubber with --write.

Attack Path

  1. A Codex session JSONL record contains an images array with at least one recognized image string and one or more non-image elements.
  2. The user selects that session through --file or --thread-id.
  3. A dry run may report image removal but does not identify the unrelated elements that will be discarded.
  4. The user reruns the tool with --write.
  5. value.some(looksLikeImageString) evaluates to true.
  6. The scrubb ...[truncated 704 chars]
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:

  1. Add tests covering mixed images arrays containing image strings, text, metadata, null values, and nested objects.
  2. Verify that dry-run statistics accurately distinguish replaced image elements from preserved elements.
  3. Add post-write validation comparing the semantic structure before and after sanitization.
  4. Document and test restoration from the generated backup.
  5. Consider reporting the JSON paths of all proposed replacements during dry runs so users can review the exact scope before writing.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 56)May include surrounding context.

md
The deterministic scrubber is at `scripts/scrub-codex-session-images.mjs`.

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
85% confidence
Finding

The skill is designed to access and modify files inside the agent's configuration/session area under ~/.codex, which is sensitive because it contains conversation history and possibly other local agent state. Even though the stated purpose is maintenance, this creates a path for privacy exposure or destructive modification if the wrong file/path is selected or if the script is abused.

Content

Scanner excerpt · SKILL.md (reported line 60)May include surrounding context.

md
Useful options:

- `--thread-id <id>`: find a rollout JSONL under `~/.codex/sessions`.
- `--file <path>`: scrub a specific JSONL.
- `--write`: perform the rewrite; without this the script is dry-run only.
- `--backup-dir <path>`: override the backup directory.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill invokes shell commands and a local Node.js script but does not declare any explicit tool restrictions or allowed-tools scope. That increases the chance an agent can execute broader shell actions than intended, especially because the workflow includes file search, file rewrite, and validation commands against local session data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
76% confidence
Finding

The skill persists changes to session history by rewriting JSONL files, which can permanently alter audit/history data and affect later agent behavior or user records. The presence of backups and dry-run guidance reduces risk, but the capability still enables tampering with session persistence if misused or applied to an unintended file.

Content

Scanner excerpt · SKILL.md (reported line 30)May include surrounding context.

node ~/.codex/skills/codex-session-image-scrubber/scripts/scrub-codex-session-images.mjs --file /path/to/rollout.jsonl

text

3. If the dry-run looks right, write the cleaned file.
```bash
node ~/.codex/skills/codex-session-image-scrubber/scripts/scrub-codex-session-images.mjs --thread-id <thread-id> --write

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/scrub-codex-session-images.mjs (reported line 19)May include surrounding context.

js
Options:
  --thread-id <id>       Find a Codex session JSONL by thread id.
  --file <path>          Scrub a specific JSONL file.
  --write                Rewrite the file. Without this, dry-run only.
  --backup-dir <path>    Backup directory. Default: ~/.codex/session_backups
  --sessions-dir <path>  Sessions root. Default: ~/.codex/sessions
  --min-bytes <n>        Large image-field threshold. Default: ${DEFAULT_MIN_BYTES}