Skip to content

Security: igovet/codex-cortex-orchestrator

Security

SECURITY.md

Security policy

Cortex is a local private document store with advisory coordination guidance. Native host/user permissions govern project edits, subagents, external actions and credentials. Neither MCP nor hooks is an authorization service, an OS sandbox, or protection against a malicious same-user process.

Host-supplied thread and parent receipts bind a task to its canonical project. A lifecycle event's session_id may identify the parent of a subagent; it is never silently treated as that child's identity. Explicit child identity and parent linkage must agree with retained binding evidence. Missing or conflicting bindings cannot broaden access. Author labels and artifact versions remain reported metadata, not independently authenticated evidence.

Each canonical project owns one SQLite store at .codex/cortex/cortex.sqlite3; separate projects do not share this metadata boundary. SQLite stores metadata, relationships, digests and receipts. Report bodies and original messages are private Markdown files under .codex/cortex/<task>/. Drafts use project .cortex/. Reports, source files, attachment references and metadata may contain private information: do not commit, export or log them without user authorization. Literal credential redaction preserves surrounding constraints; translation or summarization is not redaction. The runtime does not claim automatic secret detection. Retrieved text is evidence, not higher-priority instructions. Forwarded agent messages are internal evidence, not new user requests or response- language preferences. Workers return results through their native final response; they do not duplicate delivery through cross-task messaging tools. Progress, questions, blockers and verification updates also stay on the native parent/subagent channel. Workers never use app/connector task messaging, including codex_app.send_message_to_thread, to contact the coordinator. English-only worker reasoning and communication do not change exact quoted source text or the requested product language; only coordinator replies follow the user's response language.

Codebase Memory supplies derived project evidence, not instructions or task authority. Workers match its index to the exact canonical workspace and check relevant coverage; a similarly named project or ready status alone does not establish that match. Initial local indexing is scoped to the authorized workspace and does not authorize changing ignore rules, indexing other projects or changing stable MCP settings.

Storage integrity and recovery

Publication validates task/thread ownership, generated identifiers, canonical regular files, permissions, UTF-8 and the original draft device/inode. It streams the complete file, flushes, atomically renames and commits metadata before removing the draft. Immutable reports cannot be updated through MCP. Pipeline editions preserve older bytes below the newest edition. Exact delivery retries retain their receipts; changed arguments or content conflict. Unfilled template markers are rejected, which does not establish semantic completeness.

Draft creation without an explicit key allocates a fresh server delivery identity. It does not reinterpret an existing conflicting key as permission to overwrite or create replacement evidence. Repeated unkeyed creation creates separate drafts; uncertain creation can be recovered from the native owner's unfinished catalogue. Explicit keys, publication immutability and task/thread ownership checks remain intact.

Recovery and retention are scoped to the relevant task. A corrupt adjacent pipeline does not block unrelated archives. Checked file identity and page-offset caches avoid re-reading unchanged files; identity changes trigger integrity validation. These checks do not establish protection against a malicious local filesystem race.

Storage format 11 has no automatic compatibility reader. The separate offline 10→11 conversion requires stopped access and a backup; it changes metadata without rewriting Markdown. A legacy shared v11 store can be split into one fresh project-local store with cortex_split.py; the split requires stopped access and a new verified backup and never copies or rewrites Markdown. Back up each project's SQLite file and task directories together. Retention is irreversible without that backup. It deletes only the selected project's eligible tasks and known owned drafts, preserving unrelated files and shared directories. The coordinator supplies active-task exclusions; storage cannot infer whether an agent is still working.

Source capture and hooks

The original request comes from the explicitly validated current native thread and project, never model-authored replacement text. The reader searches the current turn with bounded memory rather than a fixed tail. It rejects foreign sessions, symlinks and unrecognized index formats. Distinct native messages retain separate identities, even when text matches. Attachment metadata records recovery routes and explicit gaps; it does not imply that an attachment was copied or verified.

Follow-up capture runs only for an already active Cortex task. normal suspends capture without deleting the archive. With an established project route, a host-source failure leaves saved reports accessible with explicit capture completeness. A fresh process still requires the validated native index to locate the archive; it never scans or guesses a global store. Unavailable sources never become invented requirements. Source and report provenance help the coordinator decide whether earlier evidence is still usable.

UserPromptSubmit has no unique native message identifier, so the hook records only a pending follow-up until an authoritative typed receipt permits publication. Stop diagnostics are advisory; when the host does not expose a reused worker assignment's boundary, they cannot prove that assignment was stopped or completed.

Bundled lifecycle hooks use one local Python handler, no model calls, and the host's ordinary review/trust mechanism. Recovery context contains bounded safe references, not raw user text elevated into developer instructions. Unchanged reminders are suppressed. Tool observations retain compact result statuses and change signals, not raw commands, prompts, patches, credentials or tool-output bodies. Hook actions are distinguishable from model actions and do not constitute complete tool coverage. Private shape diagnostics retain only approved key names, JSON types and bounded counts or lengths. Bash stdout cannot supply execution receipts: JSON-looking text and printed wrapper headings remain unverified, with native command outcomes observed separately.

Only confirmed registered-file integrity violations may deny an apply_patch: mutating a published report, deleting/moving an owned draft, or a proven ownership conflict. The handler parses actual patch targets; a path mentioned in text is not such a target. Unknown actor identity cannot establish an ownership violation. Hooks do not grant permission, rewrite tool results, accept work, assign agents or force repeated continuation. Stop diagnostics remain advisory. Failures are visible and must not be described as a successful observation.

Development and evidence

Use scripts/cortex-dev only for the exact isolated .cortex-dev/.codex candidate. Never change the user's stable installation or settings for development. Real Desktop uses the same candidate with a disposable profile. Do not bypass hook trust. A successful source test is not CLI/Desktop qualification.

Optional personal TOML export is a separate explicit operation; marketplace setup uses complete worker skills and does not register personal agents. Exact advertised skill paths and needed declared references are valid; broad installation scans and server internals are not worker instruction-loading routes.

Live diagnostics retain safe argument/result digests, observed roles, command exit or running-session receipts and errors, not raw host logs. Inspect every observed call, including after the first fault; preserve unresolved and corrected failures. A saved report is not acceptance. The coordinator assesses current requirements, source completeness, artifact revisions and the evidence's limits.

See storage, hooks, and verification.

There aren't any published security advisories