Back to skill

Security audit

Codex Session History

Security checks for vulnerabilities and agentic risk

Overview

This skill is local-only and not destructive, but it can expose private Codex conversation history and filesystem paths more broadly than users may expect.

Install only if you are comfortable letting the skill inspect your local Codex session history. Avoid using details or JSON output in shared logs or untrusted workflows, because it may reveal prior prompts, project names, usernames, repository paths, and session file locations.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

other

Warning
Location
scripts/list_codex_sessions.py:293
Finding

Exposure of Sensitive Local Codex Session History

Content
View full analysis

Vulnerability Details

File Location: scripts/list_codex_sessions.py:10-13, 40-66, 130-143, 293-366, 456-467, 566-577
Vulnerability Type: Sensitive Local Session Data Access
Risk Level: Medium

Vulnerable Code

python
CODEX_HOME = Path.home() / ".codex"
INDEX_PATH = CODEX_HOME / "session_index.jsonl"
ACTIVE_SESSIONS_DIR = CODEX_HOME / "sessions"
ARCHIVED_SESSIONS_DIR = CODEX_HOME / "archived_sessions"
python
def load_history_titles() -> dict[str, str]:
    history_path = CODEX_HOME / "history.jsonl"
    titles: dict[str, str] = {}
    if not history_path.exists():
        return titles

    with history_path.open() as handle:
        for raw_line in handle:
            raw_line = raw_line.strip()
            if not raw_line:
                continue
            try:
                row = json.loads(raw_line)
            except json.JSONDecodeError:
                continue

            session_id = row.get("session_id")
            text = row.get("text")
            if not isinstance(session_id, str) or not isinstance(text, str):
                continue
            if session_id in titles:
                continue

            normalized = normalize_user_message(text)
            if normalized:
                titles[session_id] = normalized

    return titles
python
def iter_session_files(source: str) -> list[tuple[str, Path]]:
    files: list[tuple[str, Path]] = []

    if source in {"all", "active"} and ACTIVE_SESSIONS_DIR.exists():
        for path in ACTIVE_SESSIONS_DIR.rglob("*.jsonl"):
            files.append(("active", path))

    if source in {"all", "archived"} and ARCHIVED_SESSIONS_DIR.exists():
        for path in ARCHIVED_SESSIONS_DIR.glob("*.jsonl"):
            files.append(("archived", path))

    return files
python
with session_file.open() as handle:
    for raw_line in handle:
        raw_line =
...[truncated 4043 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make metadata-only processing the default and avoid reading message bodies unless the user explicitly requests content inspection.
  2. Require an explicit option such as --include-message-content before extracting or displaying first_user_message.
  3. Display a warning or confirmation prompt before returning conversation content in detailed or JSON output.
  4. Redact common secret patterns, including API keys, tokens, passwords, private keys, and authorization headers.
  5. Omit or abbreviate absolute cwd, project_path, and session_file values by default.
  6. Add separate controls for sensitive fields so callers can request only the minimum necessary data.
  7. Document that detailed and JSON output may contain sensitive local conversation information and should not be written to public logs.
  8. Where interactive confirmation is impractical, require a deliberate environment variable or command-line acknowledgment before exposing message text.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill instructs the agent to read local files under ~/.codex/, which can expose conversation history, workspace paths, project names, and message content, but it does not declare an explicit tool scope such as permissions or allowed-tools. That omission weakens least-privilege controls and makes it easier for the skill to access sensitive local data without clear policy boundaries or user-visible consent expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This skill is specifically designed to enumerate and inspect local session history, including titles, first user messages, workspace paths, and project metadata, all of which may contain sensitive information. Because the description and usage guidance do not warn that running the skill can reveal private prompts, local directory structure, or archived session content, users may invoke it without understanding the privacy impact.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill reads ~/.codex/history.jsonl in addition to the files described in the manifest and derives titles from stored user prompt text. That expands data collection beyond the declared scope and can expose sensitive prompt content from prior sessions even when the user only asked to enumerate sessions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The detailed output includes first_user_message, which reveals actual session content rather than just session identifiers, titles, or project metadata. First user messages often contain secrets, internal paths, credentials, bug details, or proprietary requests, so exposing them broadens disclosure significantly beyond the stated session-listing purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The details mode prints session_file, cwd, and project_path along with first_user_message without any warning, which can disclose sensitive local filesystem structure and session content. Even in a local-only tool, these values may be copied into agent responses or logs and unintentionally reveal usernames, repository locations, confidential project names, or prompt data.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.