openai / openai/codex

Desktop over SSH: inspect, load and verify rollback of managed hooks for native task tools

Open
#46,443 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server documentation hooks remote
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary and requested outcome

We use Codex Desktop connected to a remote Linux workspace over SSH. A custom,
versioned managed hook protects owner-authorized operations on newly registered
tasks. We need a supported way to identify the effective hook configuration
for the caller executing native codex_app task tools, load a reviewed
configuration at the correct lifecycle boundary, and verify both selection
and rollback through actual native hook events.

In a previous bounded test, a candidate configuration was selected and read
back on the remote filesystem, but one native codex_app.read_thread probe
was denied by our older guard. We have not established whether that is due to
process lifetime, execution on a different host/process, a different config
layer, or a local integration mistake. Editing files was not established as
a supported reload operation, so we are not claiming that Codex violated
a documented hot-reload guarantee.

Our own policy keeps cross-task mutation disabled until the integration is
verified. Ordinary independent project work remains available. We are not
requesting bypasses, access to private sessions, or a guarantee that hooks
form a universal security boundary.

Environment and evidence limits

Item Recorded state
Frontend Codex Desktop using a saved remote SSH workspace
Remote environment Linux VM; exact distribution/kernel release not captured in this report
Remote Codex binary codex-cli 0.153.4, recorded by scoped diagnostics on 2026-09-10 and the machine inventory on 2026-09-18
Desktop application build Not captured; the remote CLI version must not be treated as the desktop build
Native task-tool execution host/process Not established; shell ancestry is not proof of the host/process running a native app tool
Hook source tested Root-managed requirements.toml, absolute commands under an immutable managed directory
Hook events configured in the local integration SessionStart, SubagentStart, PreToolUse, PostToolUse
Baseline custom guard transient_thread_guard_v3_6, custom artifact schema 10
Historical candidate under test transient_thread_guard_v3_11, custom artifact schema 14
Custom MCP plugin monasys-ctb 0.4.0+codex.20260731095857; prior scoped inspection found no bundled hook in that plugin
Test mode deny_all_thread_mutations throughout; no real task targeted or created

These custom guard/schema/plugin identifiers belong to our integration, not
Codex product releases. A later local candidate exists but has not passed a
native lifecycle canary and is not presented as installed or working here.

What was observed

A. Historical native probe — 2026-09-10

The retained structured result records:

  1. A bounded maintenance window selected the candidate's managed-hook
    configuration. Candidate selection was verified by filesystem read-back.
  2. One direct native codex_app.read_thread call used a deliberately
    synthetic, non-task identifier, with turnLimit=1. The candidate hook was
    designed to deny this exact diagnostic shape before task lookup and return
    a minimal version/challenge receipt. The request did not select a real
    conversation.
  3. A native pre-tool denial was observed from our v3.6 baseline, not the
    v3.11 candidate. The observed tool spelling was codex_appread_thread.
    The bounded denial reason was:
    read_thread targets a pre-existing or unregistered user chat.
  4. No candidate receipt was observed. No retry, task creation, or mutation
    followed. Full CTB lifecycle and candidate SessionStart were not proved.
  5. The window was ended after approximately 17 seconds. An independent
    restoration path restored the previous files and their checksums.
    This proves disk restoration only, not effective native-hook reload.
    The full 600-second deadline expiry was not exercised in that test.

Redacted call shape, provided for triage only; this is not a new reproduction:

{
  "tool": "codex_app.read_thread",
  "arguments": {
    "threadId": "ctb-native-hook-probe-v1:<redacted-fresh-nonce>",
    "turnLimit": 1
  }
}

The synthetic identifier and denial contract are specific to our guard.
We do not claim this is a standalone stock-Codex reproducer. A new isolated
reproducer would need the supported setup/load procedure clarified first.

B. Current caller-surface observation — 2026-09-18
  • Native saved-project listing succeeded for the expected remote workspace.
  • The active agent surface describes direct create_thread, read_thread,
    set_thread_title, and set_thread_archived tools. This is an inventory,
    not proof that these operations or their hooks work.
  • Direct wait_threads, effective-hook inspection, hook load/reload control,
    and subscriptions to native hook events are not exposed to this agent.
  • A subsequent single direct codex_app.read_thread call used a fresh
    synthetic non-task identifier and turnLimit=1, without changing any
    configuration. The tool boundary returned a PreToolUse hook denial
    identifying transient_thread_guard_v3_6, with the same bounded reason as
    the historical probe and tool spelling codex_appread_thread.
  • This establishes a guard-family denial on this caller's read path at that
    moment. It does not attest an exact source commit, the candidate,
    SessionStart, PostToolUse, or create/title/archive coverage. There was no
    challenge receipt, retry, real conversation read, task creation or mutation.
  • Managed configuration and mode-file checksums remained unchanged. No
    configuration switch or rollback was attempted in this fresh observation.

The absence of a model-callable tool does not imply that the corresponding
app-server API does not exist, or that it ought to be exposed to the model.
We would accept a supported operator/UI diagnostic route instead.

C. Settings UI and bounded configuration inspection — 2026-09-18

The owner opened Desktop Settings > Hooks. The page displayed "No hooks
found"; the owner confirmed the same result after pressing its refresh icon.
No host/project selector was visible in the supplied view. The screenshot is
retained privately and is not attached. We have not established which host or
project context this page queried, or whether it issued a hooks-list request.

In the remote workspace, the managed requirements file contained five entries:
SessionStart, SubagentStart, two PreToolUse entries, and PostToolUse. Their
absolute commands pointed to the immutable baseline directory. The checked
user, system and ancestor/project configuration paths contained no additional
hook definitions; absent files were recorded as absent. The current shell's
Codex configuration root matched its default. This bounded check did not
enumerate cloud/MDM/session sources or prove the native caller's configuration
root. No authentication values or unrelated configuration content were read
into the report.

Together, the UI observation and actual native denial show that the empty
page cannot be used as proof that this caller has no executing hook. They do
not establish a root cause or a safe candidate-loading procedure.

Related reports, not assumed duplicates
  • #30701 reports an empty Hooks
    page despite an executing plugin hook when no projects are saved. It is
    closed; its report and comments do not establish a fix applicable here.
  • #43123 reports a Windows
    Hooks UI discovery problem with no local projects. Our saved workspace is
    remote, but the local-project inventory was not established in this check.

Those reports concern UI discovery. Our additional request is the supported
inspection/load/rollback contract for managed hooks on native task tools in
Desktop over SSH. We have not reproduced their empty-project conditions or
confirmed a shared cause.

Relevant documented contract

The App Server documentation
lists hooks/list for discovering lifecycle hooks and synchronous
hook/started / hook/completed notifications. Their presence in protocol
documentation does not establish access from this desktop/SSH caller.
We need the supported client/operator route.

The Hooks documentation says managed
hooks are trusted by policy, while other hooks have a trust-review flow. It
also states that some specialized tool paths can bypass the usual hook path.
We therefore do not assume that native task tools receive both hook events,
or treat plugin installation, a file hash, MCP refresh, or CLI /hooks in a
different process as proof about this desktop caller. Sources checked
2026-09-18.

Questions for the Codex team

  1. Execution ownership: In Desktop over SSH, which host/process and config
    layers govern codex_app.create_thread, read_thread, set_thread_title
    and set_thread_archived? Is this different from the remote shell tool?
  2. Effective inspection: What supported UI/API/export lets the operator
    inspect resolved hook sources for that exact caller and correlate an
    invocation with the selected hook command/version? Is hooks/list a
    discovered-config view only, or does it reflect the active engine? Which
    host/project does Desktop Settings > Hooks inspect for an SSH task?
  3. Load boundary: When are changes to managed requirements.toml and
    managed hook commands read by a Desktop SSH session? Is a supported reload
    available? If restart/new session is required, which component and what
    procedure preserve unrelated active work? We do not assume hot reload.
  4. Coverage: For each native task tool above, are PreToolUse and
    PostToolUse guaranteed, conditional, or intentionally unsupported? What
    tool names/aliases are documented, and is codex_appread_thread expected?
  5. Runtime evidence: How can a desktop operator obtain the corresponding
    synchronous hook events without scraping transcripts/session databases or
    privately attaching to the application-owned app-server?
  6. Rollback: How can the operator verify that the running caller uses the
    restored hook after restoring files? Are in-flight turns pinned to their
    initial configuration?

A precise statement that a route is unsupported would also resolve the
integration question. We could then change our architecture explicitly,
instead of repeating configuration switches that cannot prove readiness.

What has not been established

  • No confirmed cached-config defect, hook bypass, or host-routing defect.
  • No evidence that all configured sources or cloud/MDM layers were enumerated.
  • No proof of the candidate hook on create/title/archive or a complete native
    create → execute → receive → archive workflow.
  • No current desktop build, independent clean-profile reproduction, or full
    deadline-expiry test. These gaps should remain explicit during triage.
  • Local source tests validate our guard logic, not the native app integration.
    Separate local binding/version/whole-window rollback gaps also remain;
    an answer to this report alone would not certify our complete system.

Safe next reproduction, only after clarification

Use a disposable workspace and exact client/remote versions; establish the
documented load boundary; collect only a harmless synchronous diagnostic event
bound to a versioned handler; restore the baseline and verify that handler
again. Use no existing user task, secrets, raw transcripts or business job.
Task mutations need their own bounded approval and subsequent coverage test.
This procedure is proposed and NOT RUN, not an executable authorization.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the App Server and Hooks documentation, then trace hooks/list and hook/started/hook/completed for the Desktop Settings > Hooks SSH context. Compare those documented surfaces with native codex_app.create_thread, read_thread, set_thread_title, and set_thread_archived behavior. Done means a supported inspection, load boundary, event-evidence, and rollback procedure is documented, or the route is explicitly declared unsupported.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux, rust
Domain
backend-api-design, desktop, devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.